diff --git a/ci-scripts/Jenkinsfile-poll-gNB-UE b/ci-scripts/Jenkinsfile-poll-gNB-UE index dfac9b969de149dc38de0912444876cd236b1334..80df21f62d5d2209f308a4eccd43cbf4787b41ed 100644 --- a/ci-scripts/Jenkinsfile-poll-gNB-UE +++ b/ci-scripts/Jenkinsfile-poll-gNB-UE @@ -296,7 +296,7 @@ pipeline { } if(fileExists("ci-scripts/test_results.html")) { sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" - sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" archiveArtifacts "test_results-${JOB_NAME}.html" } } diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 9809846c046ba6d0dc93119f310887441ff8de23..068de97c4ab55748a53a25ed408ae4a57df10719 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -3229,6 +3229,17 @@ class SSHConnection(): if result is not None: self.OsVersion = result.group('os_type') logging.debug('OS is: ' + self.OsVersion) + else: + self.command('hostnamectl', '\$', 5) + result = re.search('Operating System: (?P<os_type>[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) + if result is not None: + self.OsVersion = result.group('os_type') + if self.OsVersion == 'CentOS Linux 7 ': + self.command('cat /etc/redhat-release', '\$', 5) + result = re.search('CentOS Linux release (?P<os_version>[0-9\.]+)', str(self.ssh.before)) + if result is not None: + self.OsVersion = self.OsVersion.replace('7 ', result.group('os_version')) + logging.debug('OS is: ' + self.OsVersion) self.command('uname -r', '\$', 5) result = re.search('uname -r\\\\r\\\\n(?P<kernel_version>[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) if result is not None: @@ -3239,11 +3250,23 @@ class SSHConnection(): if result is not None: self.UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + self.UhdVersion) - self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) - result = re.search('product: (?P<usrp_board>[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) - if result is not None: - self.UsrpBoard = result.group('usrp_board') - logging.debug('USRP Board is: ' + self.UsrpBoard) + else: + self.command('uhd_config_info --version', '\$', 5) + result = re.search('UHD (?P<uhd_version>[a-zA-Z0-9\.\-]+)', str(self.ssh.before)) + if result is not None: + self.UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + self.UhdVersion) + self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 12) + usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) + count = 0 + for board in usrp_boards: + if count == 0: + self.UsrpBoard = board + else: + self.UsrpBoard += ',' + board + count += 1 + if count > 0: + logging.debug('USRP Board(s) : ' + self.UsrpBoard) self.command('lscpu', '\$', 5) result = re.search('CPU\(s\): *(?P<nb_cpus>[0-9]+).*Model name: *(?P<model>[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P<cpu_mhz>[0-9\.]+)', str(self.ssh.before)) if result is not None: @@ -3452,6 +3475,7 @@ class SSHConnection(): self.htmlFile.write(' <td></td>\n') self.htmlFile.write(' <td></td>\n') self.htmlFile.write(' </tr>\n') + self.htmlFile.write(' <tr>\n') self.htmlFile.write(' <th colspan=5 bgcolor = "#33CCFF">Final Status</th>\n') if passStatus: diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool index bd814cc3a43900af24bec5f7a947c081b4301dad..7865b6b3896d337f464c742e1aca80bbeb3f3829 100755 --- a/ci-scripts/oai-ci-vm-tool +++ b/ci-scripts/oai-ci-vm-tool @@ -259,7 +259,7 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=8 + NB_PATTERN_FILES=12 BUILD_OPTIONS="--phy_simulators" VM_MEMORY=8192 RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b" @@ -372,7 +372,7 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=8 + NB_PATTERN_FILES=12 BUILD_OPTIONS="--phy_simulators" VM_MEMORY=8192 RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b" diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh index 9fd6a6e8e90ce484c30ee8b37245bfb4127778cf..deb429afa7d2f61ad62a2eded94729b8a81c1b1c 100755 --- a/ci-scripts/reportBuildLocally.sh +++ b/ci-scripts/reportBuildLocally.sh @@ -573,32 +573,45 @@ function report_build { summary_table_row "NASMESH - Release 14" ./archives/basic_sim/nasmesh.Rel14.txt "Built target nasmesh" ./basic_sim_row5.html summary_table_footer - summary_table_header "OAI Build Physical simulators option" ./archives/phy_sim - summary_table_row "DL Simulator - Release 15" ./archives/phy_sim/dlsim.Rel15.txt "Built target dlsim" ./phy_sim_row1.html - summary_table_row "UL Simulator - Release 15" ./archives/phy_sim/ulsim.Rel15.txt "Built target ulsim" ./phy_sim_row2.html + summary_table_header "OAI Build Physical simulators option" + summary_table_row "LTE DL Simulator - Release 15" ./archives/phy_sim/dlsim.Rel15.txt "Built target dlsim" ./phy_sim_row1.html + summary_table_row "LTE UL Simulator - Release 15" ./archives/phy_sim/ulsim.Rel15.txt "Built target ulsim" ./phy_sim_row2.html + summary_table_row "Coding - Release 15" ./archives/phy_sim/coding.Rel15.txt "Built target coding" ./phy_sim_row3.html if [ -f ./archives/phy_sim/ldpctest.Rel15.txt ] then - summary_table_row "LDPC Test - Release 15" ./archives/phy_sim/ldpctest.Rel15.txt "Built target ldpctest" ./phy_sim_row3.html + summary_table_row "NR LDPC Test - Release 15" ./archives/phy_sim/ldpctest.Rel15.txt "Built target ldpctest" ./phy_sim_row4.html fi if [ -f ./archives/phy_sim/polartest.Rel15.txt ] then - summary_table_row "Polar Test - Release 15" ./archives/phy_sim/polartest.Rel15.txt "Built target polartest" ./phy_sim_row4.html + summary_table_row "NR Polar Test - Release 15" ./archives/phy_sim/polartest.Rel15.txt "Built target polartest" ./phy_sim_row5.html fi if [ -f ./archives/phy_sim/nr_pbchsim.Rel15.txt ] then - summary_table_row "PBCH Test - Release 15" ./archives/phy_sim/nr_pbchsim.Rel15.txt "Built target nr_pbchsim" ./phy_sim_row5.html + summary_table_row "NR PBCH Test - Release 15" ./archives/phy_sim/nr_pbchsim.Rel15.txt "Built target nr_pbchsim" ./phy_sim_row6.html fi if [ -f ./archives/phy_sim/nr_dlschsim.Rel15.txt ] then - summary_table_row "DLSCH Test - Release 15" ./archives/phy_sim/nr_dlschsim.Rel15.txt "Built target nr_dlschsim" ./phy_sim_row6.html + summary_table_row "NR DLSCH Test - Release 15" ./archives/phy_sim/nr_dlschsim.Rel15.txt "Built target nr_dlschsim" ./phy_sim_row7.html + fi + if [ -f ./archives/phy_sim/nr_pucchsim.Rel15.txt ] + then + summary_table_row "NR PUCCH Test - Release 15" ./archives/phy_sim/nr_pucchsim.Rel15.txt "Built target nr_pucchsim" ./phy_sim_row8.html fi if [ -f ./archives/phy_sim/smallblocktest.Rel15.txt ] then - summary_table_row "Small Block Test - Release 15" ./archives/phy_sim/smallblocktest.Rel15.txt "Built target smallblocktest" ./phy_sim_row7.html + summary_table_row "NR Small Block Test - Release 15" ./archives/phy_sim/smallblocktest.Rel15.txt "Built target smallblocktest" ./phy_sim_row9.html fi if [ -f ./archives/phy_sim/nr_dlsim.Rel15.txt ] then - summary_table_row "NR DL Simulator - Release 15" ./archives/phy_sim/nr_dlsim.Rel15.txt "Built target nr_dlsim" ./phy_sim_row8.html + summary_table_row "NR DL Sim Test - Release 15" ./archives/phy_sim/nr_dlsim.Rel15.txt "Built target nr_dlsim" ./phy_sim_row10.html + fi + if [ -f ./archives/phy_sim/nr_ulschsim.Rel15.txt ] + then + summary_table_row "NR ULSCH Test - Release 15" ./archives/phy_sim/nr_ulschsim.Rel15.txt "Built target nr_ulschsim" ./phy_sim_row11.html + fi + if [ -f ./archives/phy_sim/nr_ulsim.Rel15.txt ] + then + summary_table_row "NR UL Sim Test - Release 15" ./archives/phy_sim/nr_ulsim.Rel15.txt "Built target nr_ulsim" ./phy_sim_row12.html fi summary_table_footer diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 584050cb0e09116d0fb84ee64043a853aef12494..3e7370cc290bc8c66bd41dff807795a574c1953e 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -672,8 +672,6 @@ set(HWLIB_TCP_BRIDGE_OAI_SOURCE add_library(tcp_bridge_oai MODULE ${HWLIB_TCP_BRIDGE_OAI_SOURCE} ) set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") -add_library(rfsimulator MODULE ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c) - ########################################################## include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON") @@ -1346,6 +1344,7 @@ set(PHY_SRC_RU ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_tools.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c + ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c ${OPENAIR1_DIR}/PHY/MODULATION/ul_7_5_kHz.c ${OPENAIR1_DIR}/PHY/MODULATION/gen_75KHz.cpp ${OPENAIR1_DIR}/PHY/MODULATION/beamforming.c @@ -1399,6 +1398,7 @@ set(PHY_SRC_UE set(PHY_NR_SRC ${OPENAIR1_DIR}/PHY/INIT/nr_init.c ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c + ${OPENAIR1_DIR}/PHY/MODULATION/nr_modulation.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pss.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sss.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pbch.c @@ -1408,8 +1408,11 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c @@ -1430,8 +1433,9 @@ set(PHY_SRC_UE ) set(PHY_NR_UE_SRC - ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c + ${OPENAIR1_DIR}/PHY/MODULATION/nr_modulation.c + ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c @@ -1443,12 +1447,14 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/ ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_prach.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_tools_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pucch_nr.c + ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c @@ -2270,6 +2276,12 @@ target_link_libraries(uescope ${XFORMS_LIBRARIES}) add_library(gnbscope MODULE ${XFORMS_SOURCE_NR}) target_link_libraries(gnbscope ${XFORMS_LIBRARIES}) +add_library(rfsimulator MODULE + ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c + ) +target_link_libraries(rfsimulator SIMU ${ATLAS_LIBRARIES}) + + set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}") #include T directory even if the T is off because T macros are in the code @@ -2683,6 +2695,12 @@ add_executable(nr_ulschsim ${T_SOURCE}) target_link_libraries(nr_ulschsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl) +add_executable(nr_ulsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c + ${OPENAIR_DIR}/common/utils/backtrace.c + ${T_SOURCE}) +target_link_libraries(nr_ulsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_NR -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl) + foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 2f9bcead3298aa913ab352619e1020884ff51c6a..2a881dbd505ee8bf4c01e36615d289ed277a57c6 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -671,7 +671,7 @@ function main() { echo_info "Compiling unitary tests simulators" # TODO: fix: dlsim_tm4 pucchsim prachsim pdcchsim pbchsim mbmssim #simlist="dlsim_tm4 dlsim ulsim pucchsim prachsim pdcchsim pbchsim mbmssim" - simlist="nr_pucchsim dlsim ulsim polartest ldpctest smallblocktest nr_pbchsim nr_dlschsim nr_dlsim nr_ulschsim" + simlist="nr_pucchsim dlsim ulsim polartest ldpctest smallblocktest nr_pbchsim nr_dlschsim nr_dlsim nr_ulschsim nr_ulsim" for f in $simlist ; do compilations \ phy_simulators $f \ diff --git a/common/utils/LOG/vcd_signal_dumper.c b/common/utils/LOG/vcd_signal_dumper.c index 1fc1a16f53dd279c756d393fd97afe3cd4df9c01..59ef80656d5b857cd81f454145c74c8d52d58aaa 100644 --- a/common/utils/LOG/vcd_signal_dumper.c +++ b/common/utils/LOG/vcd_signal_dumper.c @@ -321,6 +321,7 @@ const char* eurecomFunctionsNames[] = { "phy_enb_prach_rx", "phy_ru_prach_rx", "phy_enb_pdcch_tx", + "phy_enb_common_tx", "phy_enb_rs_tx", "phy_ue_generate_prach", "phy_ue_ulsch_modulation", diff --git a/common/utils/LOG/vcd_signal_dumper.h b/common/utils/LOG/vcd_signal_dumper.h index 9e34bea25ccccbf35a778a390cf947bf8215c307..b8494614fe1b8625c80ac2987107a58c9f890e54 100644 --- a/common/utils/LOG/vcd_signal_dumper.h +++ b/common/utils/LOG/vcd_signal_dumper.h @@ -300,6 +300,7 @@ typedef enum { VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX, + VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX, VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_MODULATION, diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h index 5b630e9da8a4199c406829c0d63f3bae3b2e81c2..a5ed103683b44386e42b7713bd7574c19d82f449 100644 --- a/common/utils/T/T_defs.h +++ b/common/utils/T/T_defs.h @@ -73,7 +73,7 @@ typedef struct { } T_cache_t; /* number of VCD functions (to be kept up to date! see in T_messages.txt) */ -#define VCD_NUM_FUNCTIONS 192 +#define VCD_NUM_FUNCTIONS 193//192//190 /* number of VCD variables (to be kept up to date! see in T_messages.txt) */ #define VCD_NUM_VARIABLES 144 diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index c68fac8ae1e89f6efaf578ee2421d03d37341ab0..e666f3e7b520c60f322f06eb749b3be6bf0173bb 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -2374,6 +2374,11 @@ ID = VCD_FUNCTION_PHY_ENB_PDCCH_TX GROUP = ALL:VCD:ENB:VCD_FUNCTION FORMAT = int,value VCD_NAME = phy_enb_pdcch_tx +ID = VCD_FUNCTION_PHY_ENB_COMMON_TX + DESC = VCD function PHY_ENB_COMMON_TX + GROUP = ALL:VCD:ENB:VCD_FUNCTION + FORMAT = int,value + VCD_NAME = phy_enb_common_tx ID = VCD_FUNCTION_PHY_ENB_RS_TX DESC = VCD function PHY_ENB_RS_TX GROUP = ALL:VCD:ENB:VCD_FUNCTION diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index d006e30912aa622b0c886b20a6f88de382c89c2e..467930354ddc6ad6555fb5dcca6cfe19357d1be2 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -8,17 +8,25 @@ 5. [eNB RRC Layer](#enb-rrc-layer) 6. [eNB X2AP](#enb-x2ap) 7. [eNB Advanced Features](#enb-advanced-features) -2. [OpenAirInterface Functional Split](#openairinterface-functional-split) -3. [OpenAirInterface UE Feature Set](#openairinterface-ue-feature-set) +2. [OpenAirInterface UE Feature Set](#openairinterface-ue-feature-set) 1. [LTE UE PHY Layer](#lte-ue-phy-layer) 2. [LTE UE MAC Layer](#lte-ue-mac-layer) 3. [LTE UE RLC Layer](#lte-ue-rlc-layer) 4. [LTE UE PDCP Layer](#lte-ue-pdcp-layer) 5. [LTE UE RRC Layer](#lte-ue-rrc-layer) +3. [OpenAirInterface Functional Split](#openairinterface-functional-split) +4. [OpenAirInterface 5G-NR Feature Set](#openairinterface-5g-nr-feature-set) + 1. [General Parameters](#general-parameters) + 2. [gNB Features](#gnb-features) + 1. [gNB Physical Layer](#gnb-phy-layer) + 2. [gNB Higher Layers](#gnb-higher-layers) + 3. [NR UE Features](#nr-ue-features) + 1. [NR UE Physical Layer](#nr-ue-phy-layer) + 2. [NR UE Higher Layers](#nr-ue-higher-layers) # OpenAirInterface Block diagram # - + # OpenAirInterface eNB Feature Set # @@ -141,18 +149,6 @@ The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following **To be completed** -# OpenAirInterface Functional Split # - -- RCC: Radio-Cloud Center -- RAU: Radio-Access Unit -- RRU: Remote Radio-Unit - - - -- IF4.5 / IF5 : similar to IEEE P1914.1 -- FAPI (IF2) : specified by Small Cell Forum (open-nFAPI implementation) -- IF1 : F1 in 3GPP Release 15 (not implemented yet) - # OpenAirInterface UE Feature Set # ## LTE UE PHY Layer ## @@ -202,9 +198,80 @@ The NAS layer is based on **3GPP 24.301** and implements the following functions - EMM attach/detach, authentication, tracking area update, and more - ESM default/dedicated bearer, PDN connectivity, and more -[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) +# OpenAirInterface Functional Split # + +- RCC: Radio-Cloud Center +- RAU: Radio-Access Unit +- RRU: Remote Radio-Unit + + + +- IF4.5 / IF5 : similar to IEEE P1914.1 +- FAPI (IF2) : specified by Small Cell Forum (open-nFAPI implementation) +- IF1 : F1 in 3GPP Release 15 + +# OpenAirInterface 5G-NR Feature Set # + +## General Parameters ## + +The following features are valid for the gNB and the 5G-NR UE. + +* Static TDD, +* Normal CP +* 30 kHz subcarrier spacing +* Bandwidths up to 80MHz (217 Physical Resource Blocks) +* Single antenna port (single beam) +* Slot format: 14 OFDM symbols in UL or DL +* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 supported) +* Highly efficient 3GPP compliant polar encoder and decoder +* Encoder and decoder for short blocks + +## gNB Features ## + +### gNB PHY Layer ### + +* Generation of PSS/SSS/PBCH for multiple beams and +* Generation of PDCCH for SIB1 (including generation of DCI, polar encoding, scrambling, modulation, RB mapping, etc) + - common search space configured by MIB + - user-specific search space configured by RRC + - DCI formats: 00, 10 +* Generation of PDSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). + - Single symbol DMRS, dmrs-TypeA-Position Pos2, DMRS configuration type 1 + - PDSCH mapping type A +* NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). +* NR-PUCCH + - Format 0 (ACK/NACK) + +### gNB higher Layers ### + +- NR RRC (38.331) Rel 15 messages using new asn1c +- LTE RRC (36.331) also updated to Rel 15 +- Generation of MIB +- Application to read configuration file and program gNB RRC +- RRC -> MAC configuration +- MAC -> PHY configuration (using NR FAPI P5 interface) +- FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU + +For more details see [this document](https://gitlab.eurecom.fr/oai/openairinterface5g/uploads/ba5368448d627743a28c770c29e8978e/OAI_Software_Architecture_for_Dual_Connectivity_in_E-UTRA_and_5G-NR_and_nFAPI_for_MAC-PHY_Interface.docx) + +## NR UE Features ## + +### NR UE PHY Layer ### + +- initial synchronization +- Time tracking based on PDCCH DMRS +- Frequency offset estimation +- PBCH RX +- PDCCH RX +- PDSCH RX + - including first version of dual stream receiver for PDSCH + +### NR UE higher Layers ### + +For more details see [this document](https://gitlab.eurecom.fr/oai/openairinterface5g/uploads/f7386f3a64806fd6b2ac1fc3d0252fff/UE_FAPI-like_interface.docx) -[oai softmodem build procedure](BUILD.md) +[OAI wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) -[running the oai softmodem ](RUNMODEM.md) +[OAI softmodem build procedure](BUILD.md) +[Running the OAI softmodem ](RUNMODEM.md) \ No newline at end of file diff --git a/doc/oai_enb_block_diagram.png b/doc/oai_enb_block_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..58c8eb9e959fae8616de03cc9f56fcfe2cc0f0e7 Binary files /dev/null and b/doc/oai_enb_block_diagram.png differ diff --git a/doc/oai_enb_func_split_arch.png b/doc/oai_enb_func_split_arch.png new file mode 100644 index 0000000000000000000000000000000000000000..5cb6ce795759122eebc4cd1f261b3d8f2b8ca9b7 Binary files /dev/null and b/doc/oai_enb_func_split_arch.png differ diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 899cf8878f49aa5092be47c3122b433aff0b3dba..c610107da6f764d2ecb4c722f08e98c0729b7f1f 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -413,9 +413,6 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot RU_proc_t *ru_proc; int waitret,ret; - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=10000000L; @@ -487,10 +484,6 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t int ret; - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); @@ -527,7 +520,6 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { RU_proc_t *ru_proc=&ru->proc; int ret; int i; - struct timespec wait; AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); for (i=0;i<gNB->num_RU;i++) { @@ -549,9 +541,6 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { } - wait.tv_sec=0; - wait.tv_nsec=5000000L; - // wake up TX for subframe n+sl_ahead // lock the TX mutex and make sure the thread is ready AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex)) == 0,"mutex_lock returns %d\n", ret); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 77f96b8bb0f913a17eefa46cbd4f880e9641c35b..1645f12ca7bdd8c48c6e8252c9ae315bb59b8aab 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1212,6 +1212,12 @@ static void *ru_thread_tx( void *param ) { int i = 0; int ret; + + if(ru->if_south == LOCAL_RF) + { + uhd_set_thread_prio(); + LOG_I(PHY,"set ru_thread_tx uhd priority"); + } wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); printf( "ru_thread_tx ready\n"); diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h new file mode 100644 index 0000000000000000000000000000000000000000..82e303faae24cd87c9a2333824a0854efb72c06c --- /dev/null +++ b/executables/nr-softmodem-common.h @@ -0,0 +1,144 @@ +#ifndef NR_SOFTMODEM_COMMON_H +#define NR_SOFTMODEM_COMMON_H + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <execinfo.h> +#include <fcntl.h> +#include <getopt.h> +#include <linux/sched.h> +#include <sched.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syscall.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/sysinfo.h> +#include <sys/types.h> +#include <unistd.h> + +#include <sys/sysinfo.h> +#include "targets/ARCH/COMMON/common_lib.h" +#undef MALLOC +#include "assertions.h" +#include "PHY/types.h" +#include <threadPool/thread-pool.h> + +#if defined(ENABLE_USE_MME) +#include "s1ap_eNB.h" +#ifdef PDCP_USE_NETLINK +#include "SIMULATION/ETH_TRANSPORT/proto.h" +#endif +#endif + +/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ +#define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" +#define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" +#define CONFIG_HLP_CALUER "set UE RX calibration\n" +#define CONFIG_HLP_CALUERM "" +#define CONFIG_HLP_CALUERB "" +#define CONFIG_HLP_DBGUEPR "UE run normal prach power ramping, but don't continue random-access\n" +#define CONFIG_HLP_CALPRACH "UE run normal prach with maximum power, but don't continue random-access\n" +#define CONFIG_HLP_NOL2CN "bypass L2 and upper layers\n" +#define CONFIG_HLP_UERXG "set UE RX gain\n" +#define CONFIG_HLP_UERXGOFF "external UE amplifier offset\n" +#define CONFIG_HLP_UETXG "set UE TX gain\n" +#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n" +#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n" +#define CONFIG_HLP_UESCAN "set UE to scan around carrier\n" +#define CONFIG_HLP_UEFO "set UE to enable estimation and compensation of frequency offset\n" +#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n" +#define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" +#define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n" +#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n" +#define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n" +#define CONFIG_HLP_EXCCLK "tells hardware to use an external clock reference\n" +#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" +#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" +#define CONFIG_HLP_TADV "Set timing_advance\n" +#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" +#define CONFIG_HLP_CHOFF "Channel id offset\n" +#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" +#define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" +#define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" +#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" +#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" +#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n" +#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" +#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" +#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" +#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" +#define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" +#define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n" +#define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n" +#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n" +#define CONFIG_HLP_TPORT "tracer port\n" +#define CONFIG_HLP_NOTWAIT "don't wait for tracer, start immediately\n" +#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n" +#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" + +#define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n" +#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n" +#define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n" +#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" +#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" + +#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n" +#define CONFIG_HLP_USRP_CLK_SRC "USRP clock source: 'internal' or 'external'\n" + +#define CONFIG_HLP_FLOG "Enable online log \n" +#define CONFIG_HLP_LOGL "Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n" +#define CONFIG_HLP_LOGV "Set the global log verbosity \n" +#define CONFIG_HLP_TELN "Start embedded telnet server \n" +#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n" +/*------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters for LOG utility */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_LOGPARAMS_DESC { \ + {"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \ + {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ + {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \ + {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ + } +#define CMDLINE_ONLINELOG_IDX 0 +#define CMDLINE_GLOGLEVEL_IDX 1 +#define CMDLINE_GLOGVERBO_IDX 2 +#define CMDLINE_STARTTELN_IDX 3 + +/***************************************************************************************************************************************/ + +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; + + +extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; +extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +extern int rx_input_level_dBm; +extern uint8_t exit_missed_slots; +extern uint64_t num_missed_slots; // counter for the number of missed slots + +extern int oaisim_flag; +extern volatile int oai_exit; + +extern openair0_config_t openair0_cfg[MAX_CARDS]; +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; +extern int transmission_mode; +extern double cpuf; + +#if defined(ENABLE_ITTI) + extern volatile int start_eNB; + extern volatile int start_UE; +#endif + +#endif diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index e20c0ad46746038fcc9b03c4b3fdff762de9a977..69bc0102087533a1dba124ef3455c0e45f379733 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -126,6 +126,7 @@ unsigned char NB_gNB_INST = 1; int UE_scan = 1; int UE_scan_carrier = 0; runmode_t mode = normal_txrx; +double snr_dB=20; FILE *input_fd=NULL; diff --git a/executables/nr-softmodem.h b/executables/nr-softmodem.h index 48ddfba20955cf2962c7263e284c201941957f8b..f0f9e0f48d5fe79f3a0d8e097a5289f5e0f73306 100644 --- a/executables/nr-softmodem.h +++ b/executables/nr-softmodem.h @@ -1,177 +1,51 @@ #ifndef NR_SOFTMODEM_H #define NR_SOFTMODEM_H -#define _GNU_SOURCE -#include <execinfo.h> -#include <fcntl.h> -#include <getopt.h> -#include <linux/sched.h> -#include <sched.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syscall.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/sysinfo.h> -#include <sys/types.h> -#include <unistd.h> - -#include <sys/sysinfo.h> -#include "targets/ARCH/COMMON/common_lib.h" -#undef MALLOC -#include "assertions.h" -#include "msc.h" -#include "PHY/types.h" +#include <executables/nr-softmodem-common.h> #include "flexran_agent.h" #include "PHY/defs_gNB.h" -#if defined(ENABLE_ITTI) - #if defined(ENABLE_USE_MME) - #include "s1ap_eNB.h" - #ifdef PDCP_USE_NETLINK - #include "SIMULATION/ETH_TRANSPORT/proto.h" - #endif - #endif -#endif +#define DEFAULT_DLF 2680000000 -/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ -#define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" -#define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" -#define CONFIG_HLP_CALUER "set UE RX calibration\n" -#define CONFIG_HLP_CALUERM "" -#define CONFIG_HLP_CALUERB "" -#define CONFIG_HLP_DBGUEPR "UE run normal prach power ramping, but don't continue random-access\n" -#define CONFIG_HLP_CALPRACH "UE run normal prach with maximum power, but don't continue random-access\n" -#define CONFIG_HLP_NOL2CN "bypass L2 and upper layers\n" -#define CONFIG_HLP_UERXG "set UE RX gain\n" -#define CONFIG_HLP_UERXGOFF "external UE amplifier offset\n" -#define CONFIG_HLP_UETXG "set UE TX gain\n" -#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n" -#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n" -#define CONFIG_HLP_UESCAN "set UE to scan around carrier\n" -#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n" -#define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" -#define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n" -#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n" -#define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n" -#define CONFIG_HLP_EXCCLK "tells hardware to use an external clock reference\n" -#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" -#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" -#define CONFIG_HLP_TADV "Set timing_advance\n" -#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" -#define CONFIG_HLP_CHOFF "Channel id offset\n" -#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" -#define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" -#define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" -#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" -#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" -#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n" -#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" -#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" -#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" -#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" -#define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" -#define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n" -#define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n" -#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n" -#define CONFIG_HLP_TPORT "tracer port\n" -#define CONFIG_HLP_NOTWAIT "don't wait for tracer, start immediately\n" -#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n" -#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" - -#define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n" -#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n" -#define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n" -#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument when calling config_get or config_getlist functions */ - -/*------------------------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters defining UE running mode */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CMDLINE_UEMODEPARAMS_DESC { \ - {"calib-ue-rx", CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"calib-ue-rx-med", CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"calib-ue-rx-byp", CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"debug-ue-prach", CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"no-L2-connect", CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"calib-prach-tx", CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"loop-memory", CONFIG_HLP_UELOOP, 0, strptr:&loopfile, defstrval:"iqs.in", TYPE_STRING,0}, \ - {"ue-dump-frame", CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ - } -#define CMDLINE_CALIBUERX_IDX 0 -#define CMDLINE_CALIBUERXMED_IDX 1 -#define CMDLINE_CALIBUERXBYP_IDX 2 -#define CMDLINE_DEBUGUEPRACH_IDX 3 -#define CMDLINE_NOL2CONNECT_IDX 4 -#define CMDLINE_CALIBPRACHTX_IDX 5 -#define CMDLINE_MEMLOOP_IDX 6 -#define CMDLINE_DUMPMEMORY_IDX 7 -/*------------------------------------------------------------------------------------------------------------------------------------------*/ - - -#define DEFAULT_DLF 2680000000 - /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters common to eNodeB and UE */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_PARAMS_DESC { \ - {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \ - {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ - {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \ - {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \ - {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ - {"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \ - {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&wait_for_sync, defintval:0, TYPE_INT, 0}, \ - {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ - {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT, 0}, \ - {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ - {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ - {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \ - {"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \ - {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ - {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ - {"W" , CONFIG_HLP_L2MONW, 0, strptr:(char **)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, sizeof(in_ip)}, \ - {"P" , CONFIG_HLP_L2MONP, 0, strptr:(char **)&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, sizeof(in_path)}, \ - {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ - {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ - {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ - {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ - {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ - {"parallel-config", CONFIG_HLP_PARALLEL_CMD, 0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ - {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ - {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0} \ - } - -#define CONFIG_HLP_FLOG "Enable online log \n" -#define CONFIG_HLP_LOGL "Set the global log level, valid options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n" -#define CONFIG_HLP_LOGV "Set the global log verbosity \n" -#define CONFIG_HLP_TELN "Start embedded telnet server \n" -/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters for LOG utility */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CMDLINE_LOGPARAMS_DESC { \ - {"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \ - {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ - {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \ - {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ + {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)},\ + {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ + {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \ + {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \ + {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ + {"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \ + {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&wait_for_sync, defintval:0, TYPE_INT, 0}, \ + {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT, 0}, \ + {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ + {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \ + {"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \ + {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ + {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ + {"W" , CONFIG_HLP_L2MONW, 0, strptr:(char **)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, sizeof(in_ip)}, \ + {"P" , CONFIG_HLP_L2MONP, 0, strptr:(char **)&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, sizeof(in_path)},\ + {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ + {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ + {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ + {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ + {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ + {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ + {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0} \ } -#define CMDLINE_ONLINELOG_IDX 0 -#define CMDLINE_GLOGLEVEL_IDX 1 -#define CMDLINE_GLOGVERBO_IDX 2 -#define CMDLINE_STARTTELN_IDX 3 typedef struct { @@ -184,34 +58,6 @@ extern int T_nowait; extern int T_dont_fork; -/***************************************************************************************************************************************/ -/* */ -extern pthread_cond_t sync_cond; -extern pthread_mutex_t sync_mutex; -extern int sync_var; - - -extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; -extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; - -extern int rx_input_level_dBm; -extern uint8_t exit_missed_slots; -extern uint64_t num_missed_slots; // counter for the number of missed slots - -extern int oaisim_flag; -extern volatile int oai_exit; - -extern openair0_config_t openair0_cfg[MAX_CARDS]; -extern pthread_cond_t sync_cond; -extern pthread_mutex_t sync_mutex; -extern int sync_var; -extern int transmission_mode; -extern double cpuf; - -#if defined(ENABLE_ITTI) - extern volatile int start_gNB; -#endif - #include "threads_t.h" extern threads_t threads; @@ -238,4 +84,3 @@ extern int stop_L1L2(module_id_t gnb_id); extern int restart_L1L2(module_id_t gnb_id); #endif - diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 64efe1597f085bac3d61587b8aa3d228e3e18ff8..3b334660d5ab3b22d465d68bd4600302dace8747 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -42,6 +42,7 @@ #include "SCHED/sched_common_vars.h" #include "PHY/MODULATION/modulation_vars.h" //#include "../../SIMU/USER/init_lte.h" +#include "PHY/NR_REFSIG/nr_mod_table.h" #include "LAYER2/MAC/mac_vars.h" #include "LAYER2/MAC/mac_proto.h" @@ -113,6 +114,7 @@ volatile int oai_exit = 0; static clock_source_t clock_source = internal; int single_thread_flag=1; +double snr_dB=20; int threequarter_fs=0; diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 168b0e4d22d11574d2a54a78c09d39cdc271325d..228afa02abde42bd4e354e1665028e56ca120e2e 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -1,100 +1,10 @@ #ifndef NR_UESOFTMODEM_H #define NR_UESOFTMODEM_H - -#define _GNU_SOURCE -#include <execinfo.h> -#include <fcntl.h> -#include <getopt.h> -#include <linux/sched.h> -#include <sched.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syscall.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/sysinfo.h> -#include <sys/types.h> -#include <unistd.h> - -#include <sys/sysinfo.h> -#include "../../ARCH/COMMON/common_lib.h" -#undef MALLOC -#include "assertions.h" -#include "PHY/types.h" +#include <executables/nr-softmodem-common.h> #include "PHY/defs_nr_UE.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" -#include <threadPool/thread-pool.h> #include <openair2/LAYER2/NR_MAC_gNB/mac_proto.h> - -#if defined(ENABLE_ITTI) - #if defined(ENABLE_USE_MME) - #include "s1ap_eNB.h" - #ifdef PDCP_USE_NETLINK - #include "SIMULATION/ETH_TRANSPORT/proto.h" - #endif - #endif -#endif - -/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ -#define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" -#define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" -#define CONFIG_HLP_CALUER "set UE RX calibration\n" -#define CONFIG_HLP_CALUERM "" -#define CONFIG_HLP_CALUERB "" -#define CONFIG_HLP_DBGUEPR "UE run normal prach power ramping, but don't continue random-access\n" -#define CONFIG_HLP_CALPRACH "UE run normal prach with maximum power, but don't continue random-access\n" -#define CONFIG_HLP_NOL2CN "bypass L2 and upper layers\n" -#define CONFIG_HLP_UERXG "set UE RX gain\n" -#define CONFIG_HLP_UERXGOFF "external UE amplifier offset\n" -#define CONFIG_HLP_UETXG "set UE TX gain\n" -#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n" -#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n" -#define CONFIG_HLP_UESCAN "set UE to scan around carrier\n" -#define CONFIG_HLP_UEFO "set UE to enable estimation and compensation of frequency offset\n" -#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n" -#define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" -#define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n" -#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n" -#define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n" -#define CONFIG_HLP_EXCCLK "tells hardware to use an external clock reference\n" -#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" -#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" -#define CONFIG_HLP_TADV "Set timing_advance\n" -#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" -#define CONFIG_HLP_CHOFF "Channel id offset\n" -#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" -#define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" -#define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" -#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" -#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" -#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n" -#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" -#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" -#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" -#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" -#define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" -#define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n" -#define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n" -#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n" -#define CONFIG_HLP_TPORT "tracer port\n" -#define CONFIG_HLP_NOTWAIT "don't wait for tracer, start immediately\n" -#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n" - -#define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n" -#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n" -#define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n" -#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" - -#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" - -#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n" -#define CONFIG_HLP_USRP_CLK_SRC "USRP clock source: 'internal' or 'external'\n" - /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument when calling config_get or config_getlist functions */ @@ -105,14 +15,14 @@ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_UEMODEPARAMS_DESC { \ - {"calib-ue-rx", CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"calib-ue-rx-med", CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"calib-ue-rx-byp", CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - {"debug-ue-prach", CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"no-L2-connect", CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"calib-prach-tx", CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {"loop-memory", CONFIG_HLP_UELOOP, 0, strptr:&loopfile, defstrval:"iqs.in", TYPE_STRING,0}, \ - {"ue-dump-frame", CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ + {"calib-ue-rx", CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + {"calib-ue-rx-med", CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + {"calib-ue-rx-byp", CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + {"debug-ue-prach", CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + {"no-L2-connect", CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + {"calib-prach-tx", CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + {"loop-memory", CONFIG_HLP_UELOOP, 0, strptr:&loopfile, defstrval:"iqs.in", TYPE_STRING,0}, \ + {"ue-dump-frame", CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ } #define CMDLINE_CALIBUERX_IDX 0 #define CMDLINE_CALIBUERXMED_IDX 1 @@ -148,53 +58,35 @@ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters common to eNodeB and UE */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_PARAMS_DESC_UE { \ - {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \ - {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ - {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \ - {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \ - {"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \ - {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ - {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ - {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \ - {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ - {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, iptr:&do_forms, defintval:0, TYPE_INT, 0}, \ - {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0}, \ - {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ - {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ - {"W" , CONFIG_HLP_L2MONW, 0, strptr:(char **)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, sizeof(in_ip)}, \ - {"P" , CONFIG_HLP_L2MONP, 0, strptr:(char **)&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, sizeof(in_path)}, \ - {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ - {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ - {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ - {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ - {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ - {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ - {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ - {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0} \ - } - -#define CONFIG_HLP_FLOG "Enable online log \n" -#define CONFIG_HLP_LOGL "Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n" -#define CONFIG_HLP_LOGV "Set the global log verbosity \n" -#define CONFIG_HLP_TELN "Start embedded telnet server \n" -/*-------------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters for LOG utility */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*-------------------------------------------------------------------------------------------------------------------------------*/ -#define CMDLINE_LOGPARAMS_DESC { \ - {"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \ - {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ - {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \ - {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ - } -#define CMDLINE_ONLINELOG_IDX 0 -#define CMDLINE_GLOGLEVEL_IDX 1 -#define CMDLINE_GLOGVERBO_IDX 2 -#define CMDLINE_STARTTELN_IDX 3 + {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)},\ + {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ + {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \ + {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \ + {"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \ + {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ + {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \ + {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ + {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, iptr:&do_forms, defintval:0, TYPE_INT, 0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0}, \ + {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ + {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ + {"W" , CONFIG_HLP_L2MONW, 0, strptr:(char **)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, sizeof(in_ip)}, \ + {"P" , CONFIG_HLP_L2MONP, 0, strptr:(char **)&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, sizeof(in_path)}, \ + {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ + {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ + {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ + {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ + {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ + {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ + {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0} \ +} extern int T_port; @@ -202,38 +94,9 @@ extern int T_nowait; extern int T_dont_fork; - -/***************************************************************************************************************************************/ - -extern pthread_cond_t sync_cond; -extern pthread_mutex_t sync_mutex; -extern int sync_var; - - -extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; -extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; - -extern int rx_input_level_dBm; -extern uint8_t exit_missed_slots; -extern uint64_t num_missed_slots; // counter for the number of missed slots - -extern int oaisim_flag; -extern volatile int oai_exit; - -extern openair0_config_t openair0_cfg[MAX_CARDS]; -extern pthread_cond_t sync_cond; -extern pthread_mutex_t sync_mutex; -extern int sync_var; -extern int transmission_mode; -extern double cpuf; - -#if defined(ENABLE_ITTI) - extern volatile int start_eNB; - extern volatile int start_UE; -#endif - // In nr-ue.c -extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg); +extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, + openair0_config_t *openair0_cfg); extern void fill_ue_band_info(void); extern void init_NR_UE(int); extern void reset_opp_meas(void); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index 69a8476129fe4a2199194b0332112d46cf47f105..3e0891e4d90a5dd37a27a667c28a8bea0f573ebf 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -689,12 +689,13 @@ typedef struct { uint8_t frame_offset; uint16_t number_symbols; uint16_t start_symbol; + uint8_t nb_re_dmrs; + uint8_t length_dmrs; nr_pusch_freq_hopping_t pusch_freq_hopping; uint8_t mcs; uint8_t Qm; uint8_t ndi; uint8_t rv; - uint8_t harq_process_nbr; int8_t accumulated_delta_PUSCH; int8_t absolute_delta_PUSCH; uint8_t n_layers; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index a0c310bfa55ea3c185501b2143e9bf7bb3d3ac61..67ddffcfcb8b30fdfd07c638b4ed04fb5ed30761 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -81,8 +81,8 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *const fp = &gNB->frame_parms; nfapi_nr_config_request_t *cfg = &gNB->gNB_config; NR_gNB_COMMON *const common_vars = &gNB->common_vars; - /*LTE_eNB_PUSCH **const pusch_vars = gNB->pusch_vars; - LTE_eNB_SRS *const srs_vars = gNB->srs_vars; + NR_gNB_PUSCH **const pusch_vars = gNB->pusch_vars; + /*LTE_eNB_SRS *const srs_vars = gNB->srs_vars; LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars;*/ int i; @@ -157,12 +157,14 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, gNB->first_run_I0_measurements = 1; ///This flag used to be static. With multiple gNBs this does no longer work, hence we put it in the structure. However it has to be initialized with 1, which is performed here. - common_vars->rxdata = (int32_t **)NULL; + common_vars->rxdata = (int32_t **)malloc16(15*sizeof(int32_t*)); common_vars->txdataF = (int32_t **)malloc16(15*sizeof(int32_t*)); - common_vars->rxdataF = (int32_t **)malloc16(64*sizeof(int32_t*)); + common_vars->rxdataF = (int32_t **)malloc16(15*sizeof(int32_t*)); for (i=0;i<15;i++){ - common_vars->txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t) ); // [hna] samples_per_frame without CP + common_vars->txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); // [hna] samples_per_frame without CP + common_vars->rxdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); + common_vars->rxdata[i] = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)); LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n", i,common_vars->txdataF[i], @@ -199,39 +201,38 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, for (i=0; i<64; i++) prach_vars->prach_ifft[0][i] = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t)); prach_vars->rxsigF[0] = (int16_t **)malloc16_clear(64*sizeof(int16_t *)); +*/ - for (int ulsch_id=0; ulsch_id<NUMBER_OF_NR_ULSCH_MAX; ulsch_id++) { + for (int UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { //FIXME - - pusch_vars[UE_id] = (LTE_eNB_PUSCH *)malloc16_clear( NUMBER_OF_UE_MAX*sizeof(LTE_eNB_PUSCH) ); - pusch_vars[UE_id]->rxdataF_ext = (int32_t **)malloc16( 2*sizeof(int32_t *) ); - pusch_vars[UE_id]->rxdataF_ext2 = (int32_t **)malloc16( 2*sizeof(int32_t *) ); - pusch_vars[UE_id]->drs_ch_estimates = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[UE_id] = (NR_gNB_PUSCH *)malloc16_clear( sizeof(NR_gNB_PUSCH) ); + pusch_vars[UE_id]->rxdataF_ext = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[UE_id]->rxdataF_ext2 = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[UE_id]->drs_ch_estimates = (int32_t **)malloc16( 2*sizeof(int32_t *) ); pusch_vars[UE_id]->drs_ch_estimates_time = (int32_t **)malloc16( 2*sizeof(int32_t *) ); - pusch_vars[UE_id]->rxdataF_comp = (int32_t **)malloc16( 2*sizeof(int32_t *) ); - pusch_vars[UE_id]->ul_ch_mag = (int32_t **)malloc16( 2*sizeof(int32_t *) ); - pusch_vars[UE_id]->ul_ch_magb = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[UE_id]->rxdataF_comp = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[UE_id]->ul_ch_mag = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[UE_id]->ul_ch_magb = (int32_t **)malloc16( 2*sizeof(int32_t *) ); for (i=0; i<2; i++) { // RK 2 times because of output format of FFT! // FIXME We should get rid of this - pusch_vars[UE_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); - pusch_vars[UE_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); - pusch_vars[UE_id]->drs_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->drs_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); pusch_vars[UE_id]->drs_ch_estimates_time[i] = (int32_t *)malloc16_clear( 2*sizeof(int32_t)*fp->ofdm_symbol_size ); - pusch_vars[UE_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); - pusch_vars[UE_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 ); - pusch_vars[UE_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 ); + pusch_vars[UE_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 ); + pusch_vars[UE_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 ); } - pusch_vars[UE_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + pusch_vars[UE_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear } //UE_id - +/* for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) gNB->UE_stats_ptr[UE_id] = &gNB->UE_stats[UE_id]; - - gNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration */ + gNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration return (0); } /* @@ -282,8 +283,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) { //NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms; //nfapi_nr_config_request_t *cfg = &gNB->gNB_config; NR_gNB_COMMON *const common_vars = &gNB->common_vars; - /*LTE_eNB_PUSCH **const pusch_vars = gNB->pusch_vars; - LTE_eNB_SRS *const srs_vars = gNB->srs_vars; + NR_gNB_PUSCH **const pusch_vars = gNB->pusch_vars; + /*LTE_eNB_SRS *const srs_vars = gNB->srs_vars; LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars;*/ uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs; @@ -452,13 +453,17 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { gNB->dlsch[i][j]->rnti=0; LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,gNB->dlsch[i][j], gNB->dlsch[i][j]->rnti); }*/ + } + } - ///////////////////////// Initializing gNB ULSCH ///////////////////////// - LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); + for (i=0; i<NUMBER_OF_NR_UE_MAX; i++) { + LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); + + for (j=0; j<2; j++) { // ULSCH for RA if(i==0) { - gNB->ulsch[i][j] = new_gNB_ulsch(5, fp->N_RB_UL, 0); + gNB->ulsch[i][j] = new_gNB_ulsch(MAX_LDPC_ITERATIONS, fp->N_RB_UL, 0); if (!gNB->ulsch[i][j]) { LOG_E(PHY,"Can't get gNB ulsch structures\n"); @@ -467,7 +472,7 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { } // ULSCH for data - gNB->ulsch[i+1][j] = new_gNB_ulsch(5, fp->N_RB_UL, 0); + gNB->ulsch[i+1][j] = new_gNB_ulsch(MAX_LDPC_ITERATIONS, fp->N_RB_UL, 0); if (!gNB->ulsch[i+1][j]) { LOG_E(PHY,"Can't get gNB ulsch structures\n"); @@ -487,7 +492,7 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { LOG_D(PHY,"gNB %d.%d : RA %p\n",gNB->Mod_id,gNB->CC_id,gNB->dlsch_ra); gNB->rx_total_gain_dB=130; - for(i=0; i<NUMBER_OF_UE_MAX; i++) + for(i=0; i<NUMBER_OF_NR_UE_MAX; i++) gNB->mu_mimo_mode[i].dl_pow_off = 2; gNB->check_for_total_transmissions = 0; diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 4855958dac8ca6269df31640598c3e107ca569fc..ba8a89ee73ac8d4e9b98b743a2d8c78b2267ca5f 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -37,7 +37,8 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/INIT/phy_init.h" #include "PHY/NR_REFSIG/pss_nr.h" -#include "openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h" +#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" +#include "PHY/NR_REFSIG/refsig_defs_ue.h" //uint8_t dmrs1_tab_ue[8] = {0,2,3,4,6,8,9,10}; @@ -645,6 +646,19 @@ void phy_init_nr_ue__PDSCH( NR_UE_PDSCH* const pdsch, const NR_DL_FRAME_PARMS* c } } +void phy_init_nr_ue_PUSCH( NR_UE_PUSCH* const pusch, const NR_DL_FRAME_PARMS* const fp ) +{ + + int i; + AssertFatal( pusch, "pusch==0" ); + + for (i=0; i<NR_MAX_NB_LAYERS; i++){ + pusch->txdataF_layers[i] = (int32_t *)malloc16_clear((NR_MAX_PUSCH_ENCODED_LENGTH)*sizeof(int32_t*)); + + } + +} + int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_eNB, uint8_t abstraction_flag) @@ -656,18 +670,22 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, NR_UE_PDSCH** const pdsch_vars_ra = ue->pdsch_vars_ra; NR_UE_PDSCH** const pdsch_vars_p = ue->pdsch_vars_p; NR_UE_PDSCH** const pdsch_vars_mch = ue->pdsch_vars_MCH; - NR_UE_PDSCH* (*pdsch_vars_th)[][NUMBER_OF_CONNECTED_eNB_MAX+1] = &ue->pdsch_vars; - NR_UE_PDCCH* (*pdcch_vars_th)[][NUMBER_OF_CONNECTED_eNB_MAX] = &ue->pdcch_vars; + NR_UE_PDSCH* (*const pdsch_vars_th)[][NUMBER_OF_CONNECTED_eNB_MAX+1] = ue->pdsch_vars; + NR_UE_PDCCH* (*const pdcch_vars_th)[][NUMBER_OF_CONNECTED_eNB_MAX] = ue->pdcch_vars; NR_UE_PBCH** const pbch_vars = ue->pbch_vars; NR_UE_PRACH** const prach_vars = ue->prach_vars; + NR_UE_PUSCH* (*const pusch_vars)[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX] = ue->pusch_vars; - int i,j,k,l; + int i,j,k,l,slot,symb,q,layer; int eNB_id; int th_id; int n_ssb_crb=(fp->N_RB_DL-20); int k_ssb=0; + uint32_t ****pusch_dmrs; + int N_n_scid[2] = {0,1}; // [HOTFIX] This is a temporary implementation of scramblingID0 and scramblingID1 which are given by DMRS-UplinkConfig + int n_scid; abstraction_flag = 0; fp->nb_antennas_tx = 1; fp->nb_antennas_rx=1; @@ -699,6 +717,59 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->total_received_bits[eNB_id] = 0; } +/////////////////////////PUSCH init///////////////////////// +/////////// + for (th_id = 0; th_id < RX_NB_TH_MAX; th_id++){ + for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++){ + + (*pusch_vars)[th_id][eNB_id] = (NR_UE_PUSCH *)malloc16(sizeof(NR_UE_PUSCH)); + phy_init_nr_ue_PUSCH( (*pusch_vars)[th_id][eNB_id], fp ); + + } + } + +/////////// +//////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////PUSCH DMRS init///////////////////////// +/////////// + + // default values until overwritten by RRCConnectionReconfiguration + + for (i=0;i<MAX_NR_OF_UL_ALLOCATIONS;i++){ + ue->pusch_config.pusch_TimeDomainResourceAllocation[i] = (PUSCH_TimeDomainResourceAllocation_t *)malloc16(sizeof(PUSCH_TimeDomainResourceAllocation_t)); + ue->pusch_config.pusch_TimeDomainResourceAllocation[i]->mappingType = typeA; + } + + + + //------------- config DMRS parameters--------------// + ue->dmrs_UplinkConfig.pusch_dmrs_type = pusch_dmrs_type1; + ue->dmrs_UplinkConfig.pusch_dmrs_AdditionalPosition = pusch_dmrs_pos0; + ue->dmrs_UplinkConfig.pusch_maxLength = pusch_len1; + //-------------------------------------------------// + + ue->nr_gold_pusch_dmrs = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t***)); + pusch_dmrs = ue->nr_gold_pusch_dmrs; + n_scid = 0; // This quantity is indicated by higher layer parameter dmrs-SeqInitialization + + for (slot=0; slot<fp->slots_per_frame; slot++) { + pusch_dmrs[slot] = (uint32_t ***)malloc16(fp->symbols_per_slot*sizeof(uint32_t**)); + AssertFatal(pusch_dmrs[slot]!=NULL, "init_nr_ue_signal: pusch_dmrs for slot %d - malloc failed\n", slot); + for (symb=0; symb<fp->symbols_per_slot; symb++){ + pusch_dmrs[slot][symb] = (uint32_t **)malloc16(NR_MAX_NB_CODEWORDS*sizeof(uint32_t*)); + AssertFatal(pusch_dmrs[slot][symb]!=NULL, "init_nr_ue_signal: pusch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb); + for (q=0; q<NR_MAX_NB_CODEWORDS; q++) { + pusch_dmrs[slot][symb][q] = (uint32_t*)malloc16(NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD*sizeof(uint32_t)); + AssertFatal(pusch_dmrs[slot][symb][q]!=NULL, "init_nr_ue_signal: pusch_dmrs for slot %d symbol %d codeword %d - malloc failed\n", slot, symb, q); + } + } + } + + nr_init_pusch_dmrs(ue, N_n_scid, n_scid); +/////////// +//////////////////////////////////////////////////////////////////////////////////////////// + for (i=0;i<10;i++) ue->tx_power_dBm[i]=-127; @@ -712,7 +783,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, for (i=0; i<fp->nb_antennas_tx; i++) { common_vars->txdata[i] = (int32_t*)malloc16_clear( fp->samples_per_subframe*10*sizeof(int32_t) ); - common_vars->txdataF[i] = (int32_t *)malloc16_clear( fp->ofdm_symbol_size*fp->symbols_per_slot*10*sizeof(int32_t) ); + common_vars->txdataF[i] = (int32_t *)malloc16_clear( fp->samples_per_slot_wCP*sizeof(int32_t) ); } // init RX buffers @@ -724,7 +795,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, for (i=0; i<fp->nb_antennas_rx; i++) { common_vars->rxdata[i] = (int32_t*) malloc16_clear( (2*(fp->samples_per_frame)+2048)*sizeof(int32_t) ); for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) { - common_vars->common_vars_rx_data_per_thread[th_id].rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->ofdm_symbol_size*14) ); + common_vars->common_vars_rx_data_per_thread[th_id].rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->samples_per_slot_wCP) ); } } } @@ -896,6 +967,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->pdsch_config_dedicated->p_a = dBm3; else ue->pdsch_config_dedicated->p_a = dB0; + // set channel estimation to do linear interpolation in time ue->high_speed_flag = 1; diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 5c38ab3056689e436c5dd12116350ba4943bda69..00b2b6a7da16791dbc02f4e2bfafcbd72e0d1fdc 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -133,13 +133,13 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, case 106: //40 MHz if (fp->threequarter_fs) { fp->ofdm_symbol_size = 1536; - fp->first_carrier_offset = 900; //1536 - 636 + fp->first_carrier_offset = 900; //1536 - ( (106*12) / 2 ) fp->nb_prefix_samples0 = 132; fp->nb_prefix_samples = 108; } else { fp->ofdm_symbol_size = 2048; - fp->first_carrier_offset = 1412; //2048 - 636 + fp->first_carrier_offset = 1412; //2048 - ( (106*12) / 2 ) fp->nb_prefix_samples0 = 176; fp->nb_prefix_samples = 144; } @@ -152,13 +152,13 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, case 217: //80 MHz if (fp->threequarter_fs) { fp->ofdm_symbol_size = 3072; - fp->first_carrier_offset = 1770; //3072 - 1302 + fp->first_carrier_offset = 1770; //3072 - ( (217*12) / 2 ) fp->nb_prefix_samples0 = 264; fp->nb_prefix_samples = 216; } else { fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2794; //4096 - 1302 + fp->first_carrier_offset = 2794; //4096 - ( (217*12) / 2 ) fp->nb_prefix_samples0 = 352; fp->nb_prefix_samples = 288; } @@ -167,14 +167,14 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, case 245: AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for N_RB %d and MU %d\n",N_RB_DL,mu); fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2626; //4096 - 1478 + fp->first_carrier_offset = 2626; //4096 - ( (245*12) / 2 ) fp->nb_prefix_samples0 = 352; fp->nb_prefix_samples = 288; break; case 273: AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for N_RB %d and MU %d\n",N_RB_DL,mu); fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2458; //4096 - 1638 + fp->first_carrier_offset = 2458; //4096 - ( (273*12) / 2 ) fp->nb_prefix_samples0 = 352; fp->nb_prefix_samples = 288; break; diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c new file mode 100644 index 0000000000000000000000000000000000000000..74f09d9fae0054651f34a599dc00436bdfceb512 --- /dev/null +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -0,0 +1,301 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_modulation.h" + +extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; + +void nr_modulation(uint32_t *in, + uint16_t length, + uint16_t mod_order, + int16_t *out) { + + uint16_t offset; + uint16_t order; + int i,j; + uint8_t idx, b_idx; + + offset = (mod_order==2)? NR_MOD_TABLE_QPSK_OFFSET : (mod_order==4)? NR_MOD_TABLE_QAM16_OFFSET : \ + (mod_order==6)? NR_MOD_TABLE_QAM64_OFFSET: (mod_order==8)? NR_MOD_TABLE_QAM256_OFFSET : 0; + + for (i=0; i<length/mod_order; i++) { + idx = 0; + + for (j=0; j<mod_order; j++) { + b_idx = (i*mod_order+j)&0x1f; + if (i && (!b_idx)) + in++; + idx ^= (((*in)>>b_idx)&1)<<(mod_order-j-1); + } + + out[i<<1] = nr_mod_table[(offset+idx)<<1]; + out[(i<<1)+1] = nr_mod_table[((offset+idx)<<1)+1]; + } +} + +void nr_layer_mapping(int16_t **mod_symbs, + uint8_t n_layers, + uint16_t n_symbs, + int16_t **tx_layers) { + + switch (n_layers) { + + case 1: + memcpy((void*)tx_layers[0], (void*)mod_symbs[0], (n_symbs<<1)*sizeof(int16_t)); + break; + + case 2: + case 3: + case 4: + for (int i=0; i<n_symbs/n_layers; i++) + for (int l=0; l<n_layers; l++) { + tx_layers[l][i<<1] = mod_symbs[0][(n_layers*i+l)<<1]; + tx_layers[l][(i<<1)+1] = mod_symbs[0][((n_layers*i+l)<<1)+1]; + } + break; + + case 5: + for (int i=0; i<n_symbs>>1; i++) + for (int l=0; l<2; l++) { + tx_layers[l][i<<1] = mod_symbs[0][((i<<1)+l)<<1]; + tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<1)+l)<<1)+1]; + } + for (int i=0; i<n_symbs/3; i++) + for (int l=2; l<5; l++) { + tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1]; + tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1]; + } + break; + + case 6: + for (int q=0; q<2; q++) + for (int i=0; i<n_symbs/3; i++) + for (int l=0; l<3; l++) { + tx_layers[l][i<<1] = mod_symbs[q][(3*i+l)<<1]; + tx_layers[l][(i<<1)+1] = mod_symbs[q][((3*i+l)<<1)+1]; + } + break; + + case 7: + for (int i=0; i<n_symbs/3; i++) + for (int l=0; l<3; l++) { + tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1]; + tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1]; + } + for (int i=0; i<n_symbs/4; i++) + for (int l=3; l<7; l++) { + tx_layers[l][i<<1] = mod_symbs[0][((i<<2)+l)<<1]; + tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<2)+l)<<1)+1]; + } + break; + + case 8: + for (int q=0; q<2; q++) + for (int i=0; i<n_symbs>>2; i++) + for (int l=0; l<3; l++) { + tx_layers[l][i<<1] = mod_symbs[q][((i<<2)+l)<<1]; + tx_layers[l][(i<<1)+1] = mod_symbs[q][(((i<<2)+l)<<1)+1]; + } + break; + + default: + AssertFatal(0, "Invalid number of layers %d\n", n_layers); + } +} + + +void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) +{ +#if defined(__x86_64__) || defined(__i386__) + __m128i dft_in128[1][1200], dft_out128[1][1200]; +#elif defined(__arm__) + int16x8_t dft_in128[1][1200], dft_out128[1][1200]; +#endif + uint32_t *dft_in0 = (uint32_t*)dft_in128[0], *dft_out0 = (uint32_t*)dft_out128[0]; + + uint32_t i, ip; + +#if defined(__x86_64__) || defined(__i386__) + __m128i norm128; +#elif defined(__arm__) + int16x8_t norm128; +#endif + + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { + dft_in0[ip] = d[i]; + } + + switch (Msc_PUSCH) { + case 12: + dft12((int16_t *)dft_in0, (int16_t *)dft_out0); + +#if defined(__x86_64__) || defined(__i386__) + norm128 = _mm_set1_epi16(9459); +#elif defined(__arm__) + norm128 = vdupq_n_s16(9459); +#endif + for (i=0; i<12; i++) { +#if defined(__x86_64__) || defined(__i386__) + ((__m128i*)dft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)dft_out0)[i], norm128), 1); +#elif defined(__arm__) + ((int16x8_t*)dft_out0)[i] = vqdmulhq_s16(((int16x8_t*)dft_out0)[i], norm128); +#endif + } + + break; + + case 24: + dft24((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 36: + dft36((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 48: + dft48((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 60: + dft60((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 72: + dft72((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 96: + dft96((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 108: + dft108((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 120: + dft120((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 144: + dft144((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 180: + dft180((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 192: + dft192((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 216: + dft216((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 240: + dft240((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 288: + dft288((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 300: + dft300((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 324: + dft324((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 360: + dft360((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 384: + dft384((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 432: + dft432((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 480: + dft480((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 540: + dft540((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 576: + dft576((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 600: + dft600((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 648: + dft648((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 720: + dft720((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 768: + dft768((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 864: + dft864((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 900: + dft900((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 960: + dft960((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 972: + dft972((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1080: + dft1080((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1152: + dft1152((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1200: + dft1200((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + } + + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { + z[i] = dft_out0[ip]; + } +} diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h new file mode 100644 index 0000000000000000000000000000000000000000..249a92e8e309532e285a109a436c1ea2d23cf863 --- /dev/null +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -0,0 +1,83 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef __NR_MODULATION_H__ +#define __NR_MODULATION_H__ + +#include <stdint.h> +#include "PHY/defs_nr_common.h" +#include "PHY/defs_gNB.h" + +#define DMRS_MOD_ORDER 2 + +/*! \brief Perform NR modulation. TS 38.211 V15.4.0 subclause 5.1 + @param[in] in, Pointer to input bits + @param[in] length, size of input bits + @param[in] modulation_type, modulation order + @param[out] out, complex valued modulated symbols +*/ + +void nr_modulation(uint32_t *in, + uint16_t length, + uint16_t mod_order, + int16_t *out); + +/*! \brief Perform NR layer mapping. TS 38.211 V15.4.0 subclause 7.3.1.3 + @param[in] mod_symbs, double Pointer to modulated symbols for each codeword + @param[in] n_layers, number of layers + @param[in] n_symbs, number of modulated symbols + @param[out] tx_layers, modulated symbols for each layer +*/ + +void nr_layer_mapping(int16_t **mod_symbs, + uint8_t n_layers, + uint16_t n_symbs, + int16_t **tx_layers); + + +/*! +\brief This function implements the OFDM front end processor on reception (FEP) +\param frame_parms Pointer to frame parameters +\param rxdata Pointer to input data in time domain +\param rxdataF Pointer to output data in frequency domain +\param symbol symbol within slot (0..12/14) +\param Ns Slot number (0..19) +\param sample_offset offset within rxdata (points to beginning of subframe) +\param no_prefix if 1 prefix is removed by HW +*/ + +int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdata, + int32_t *rxdataF, + unsigned char symbol, + unsigned char Ns, + int sample_offset, + int no_prefix); + +/*! +\brief This function implements the dft transform precoding in PUSCH +\param z Pointer to output in frequnecy domain +\param d Pointer to input in time domain +\param Msc_PUSCH number of allocated data subcarriers +*/ +void nr_dft(int32_t *z,int32_t *d, uint32_t Msc_PUSCH); + +#endif \ No newline at end of file diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 7ff88612a1ab036cff3653d47b8ad6ac7fe86511..b93f6be2502943d66f34851043319b6c657cb2ae 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -19,9 +19,10 @@ * contact@openairinterface.org */ -#include "PHY/defs_UE.h" #include "PHY/defs_nr_UE.h" +#include "PHY/defs_gNB.h" #include "modulation_UE.h" +#include "nr_modulation.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" @@ -198,3 +199,71 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, return(0); } + +int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, + int32_t *rxdata, + int32_t *rxdataF, + unsigned char symbol, + unsigned char Ns, + int sample_offset, + int no_prefix) +{ + uint32_t slot_offset; + uint32_t rxdata_offset; + + unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); + unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + + void (*dft)(int16_t *,int16_t *, int); + + switch (frame_parms->ofdm_symbol_size) { + case 128: + dft = dft128; + break; + + case 256: + dft = dft256; + break; + + case 512: + dft = dft512; + break; + + case 1024: + dft = dft1024; + break; + + case 1536: + dft = dft1536; + break; + + case 2048: + dft = dft2048; + break; + + case 4096: + dft = dft4096; + break; + + case 8192: + dft = dft8192; + break; + + default: + dft = dft512; + break; + } + + slot_offset = Ns * frame_parms->samples_per_slot; + + + if(symbol == 0) + rxdata_offset = slot_offset + nb_prefix_samples0 - SOFFSET; + else + rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; + + dft((int16_t *)&rxdata[rxdata_offset], + (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); + + return(0); +} diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.h b/openair1/PHY/NR_REFSIG/dmrs_nr.h index a695006304762b3eee95e0d644ce2cb5b7d683e0..9b02d2b1afcd07df9ccdda06e29055c67d478bbe 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.h +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.h @@ -54,6 +54,8 @@ int pseudo_random_sequence(int M_PN, uint32_t *c, uint32_t cinit); void lte_gold_new(LTE_DL_FRAME_PARMS *frame_parms, uint32_t lte_gold_table[20][2][14], uint16_t Nid_cell); void generate_dmrs_pbch(uint32_t dmrs_pbch_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_HF][DMRS_BITMAP_SIZE], uint16_t Nid_cell); +uint8_t get_l0_ul(uint8_t mapping_type, uint8_t dmrs_typeA_position); +uint16_t get_dmrs_freq_idx_ul(uint8_t n, uint8_t k_prime, uint8_t delta, uint8_t dmrs_type); #undef EXTERN diff --git a/openair1/PHY/NR_REFSIG/nr_gold.c b/openair1/PHY/NR_REFSIG/nr_gold.c index bd60933155bf27a38401856ff36d402abf9f412d..1492d7f03f3f91d32943c94a10c836d546e4c924 100644 --- a/openair1/PHY/NR_REFSIG/nr_gold.c +++ b/openair1/PHY/NR_REFSIG/nr_gold.c @@ -81,7 +81,7 @@ void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid) { uint32_t x1, x2; - uint8_t reset; + uint8_t reset, q; NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; uint32_t ****pdsch_dmrs = gNB->nr_gold_pdsch_dmrs; @@ -89,16 +89,15 @@ void nr_init_pdsch_dmrs(PHY_VARS_gNB* gNB, uint32_t Nid) uint8_t n_scid=0; // again works only for 1_0 for (uint8_t slot=0; slot<fp->slots_per_frame; slot++) { for (uint8_t symb=0; symb<fp->symbols_per_slot; symb++) { - for (uint8_t q=0; q<NR_MAX_NB_CODEWORDS; q++) { - reset = 1; x2 = ((1<<17) * (fp->symbols_per_slot*slot+symb+1) * ((N_n_scid[n_scid]<<1)+1) +((N_n_scid[n_scid]<<1)+n_scid)); for (uint32_t n=0; n<NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD; n++) { - pdsch_dmrs[slot][symb][q][n] = lte_gold_generic(&x1, &x2, reset); + pdsch_dmrs[slot][symb][0][n] = lte_gold_generic(&x1, &x2, reset); reset = 0; - } - } - } - } + } + for (q = 1; q < NR_MAX_NB_CODEWORDS; q++) + memcpy(pdsch_dmrs[slot][symb][q],pdsch_dmrs[slot][symb][0],sizeof(uint32_t)*NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD); + } + } } diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c index 726aab8a37b98a772a6b099e5cdb09ab52f6d655..098931430eb887d733bccdf6a81f9d0c375c5a97 100644 --- a/openair1/PHY/NR_REFSIG/nr_gold_ue.c +++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c @@ -160,3 +160,29 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue,unsigned short lbar,unsigned short *n_idDM } } } + +void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue, uint16_t *N_n_scid, uint8_t n_scid) +{ + + uint32_t x1, x2, n; + uint8_t reset, slot, symb, q; + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + uint32_t ****pusch_dmrs = ue->nr_gold_pusch_dmrs; + + for (slot=0; slot<fp->slots_per_frame; slot++) { + + for (symb=0; symb<fp->symbols_per_slot; symb++) { + + reset = 1; + x2 = ((1<<17) * (fp->symbols_per_slot*slot+symb+1) * ((N_n_scid[n_scid]<<1)+1) +((N_n_scid[n_scid]<<1)+n_scid)); + + for (n=0; n<NR_MAX_PUSCH_DMRS_INIT_LENGTH_DWORD; n++) { + pusch_dmrs[slot][symb][0][n] = lte_gold_generic(&x1, &x2, reset); + reset = 0; + } + + for (q = 1; q < NR_MAX_NB_CODEWORDS; q++) + memcpy(pusch_dmrs[slot][symb][q],pusch_dmrs[slot][symb][0],sizeof(uint32_t)*NR_MAX_PUSCH_DMRS_INIT_LENGTH_DWORD); + } + } +} diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index a47e65d0b0d157ac2ed2cd21a708a55ca2610ca4..d1a72dd2fc1c40a056ce80da069b00acca13c4ca 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -23,7 +23,9 @@ /* Author R. Knopp / EURECOM / OpenAirInterface.org */ #ifndef __NR_REFSIG_DEFS__H__ #define __NR_REFSIG_DEFS__H__ + #include "PHY/defs_nr_UE.h" +#include "PHY/LTE_REFSIG/lte_refsig.h" /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS. @@ -61,5 +63,6 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue, unsigned short *n_idDMRS, unsigned short length_dmrs); +void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue, uint16_t *N_n_scid, uint8_t n_scid); #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index e59c03b745fb79c26ff96a7123a4efce6e71dc88..ab3cf4af9b04a60ec28602d1095e0e32a8f4a83c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -32,14 +32,14 @@ #include "nr_dci.h" #include "nr_dlsch.h" +#include "nr_sch_dmrs.h" +#include "PHY/MODULATION/nr_modulation.h" //#define DEBUG_PDCCH_DMRS //#define DEBUG_DCI //#define DEBUG_CHANNEL_CODING -extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; - uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, nfapi_nr_rnti_type_e rnti_type, uint16_t N_RB, @@ -217,9 +217,9 @@ uint8_t nr_generate_dci_top(NR_gNB_PDCCH pdcch_vars, #endif } - nr_modulation(dmrs_seq, dmrs_length, MOD_QPSK, mod_dmrs[symb]); + nr_modulation(dmrs_seq, dmrs_length, DMRS_MOD_ORDER, mod_dmrs[symb]); //Qm = 2 as DMRS is QPSK modulated } else - nr_modulation(gold_pdcch_dmrs[symb], dmrs_length, MOD_QPSK, mod_dmrs[symb]); + nr_modulation(gold_pdcch_dmrs[symb], dmrs_length, DMRS_MOD_ORDER, mod_dmrs[symb]); //Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_PDCCH_DMRS @@ -264,7 +264,7 @@ uint8_t nr_generate_dci_top(NR_gNB_PDCCH pdcch_vars, #endif /// QPSK modulation int16_t mod_dci[NR_MAX_DCI_SIZE>>1]; - nr_modulation(scrambled_output, encoded_length, MOD_QPSK, mod_dci); + nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, mod_dci); //Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_DCI for (int i=0; i<encoded_length>>1; i++) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 7b10404fc9994beb1ac83d265995349cf8e336c9..9a4df3889514ae1c517292773013309e91f2a35d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -33,13 +33,11 @@ #include "nr_dlsch.h" #include "nr_dci.h" #include "nr_sch_dmrs.h" +#include "PHY/MODULATION/nr_modulation.h" //#define DEBUG_DLSCH //#define DEBUG_DLSCH_MAPPING -uint8_t mod_order[5] = {1, 2, 4, 6, 8}; -uint16_t mod_offset[5] = {1,3,7,23,87}; - void nr_pdsch_codeword_scrambling(uint8_t *in, uint16_t size, uint8_t q, @@ -67,146 +65,23 @@ void nr_pdsch_codeword_scrambling(uint8_t *in, } -void nr_modulation(uint32_t *in, - uint16_t length, - nr_mod_t modulation_type, - int16_t *out) { - - uint16_t offset; - uint16_t order; - order = mod_order[modulation_type]; - offset = mod_offset[modulation_type]; - - for (int i=0; i<length/order; i++) { - uint8_t idx = 0, b_idx; - - for (int j=0; j<order; j++) { - b_idx = (i*order+j)&0x1f; - if (i && (!b_idx)) - in++; - idx ^= (((*in)>>b_idx)&1)<<(order-j-1); - } - - out[i<<1] = nr_mod_table[(offset+idx)<<1]; - out[(i<<1)+1] = nr_mod_table[((offset+idx)<<1)+1]; - } -} - -void nr_pdsch_codeword_modulation(uint32_t *in, - uint8_t Qm, - uint32_t length, - int16_t *out) { - - uint16_t offset = (Qm==2)? NR_MOD_TABLE_QPSK_OFFSET : (Qm==4)? NR_MOD_TABLE_QAM16_OFFSET : \ - (Qm==6)? NR_MOD_TABLE_QAM64_OFFSET: (Qm==8)? NR_MOD_TABLE_QAM256_OFFSET : 0; - AssertFatal(offset, "Invalid modulation order %d\n", Qm); - - for (int i=0; i<length/Qm; i++) { - uint8_t idx = 0, b_idx; - - for (int j=0; j<Qm; j++) { - b_idx = (i*Qm+j)&0x1f; - if (i && (!b_idx)) - in++; - idx ^= (((*in)>>b_idx)&1)<<(Qm-j-1); - } - - out[i<<1] = nr_mod_table[(offset+idx)<<1]; - out[(i<<1)+1] = nr_mod_table[((offset+idx)<<1)+1]; - } -} - -void nr_pdsch_layer_mapping(int16_t **mod_symbs, - uint8_t n_layers, - uint16_t n_symbs, - int16_t **tx_layers) { - - switch (n_layers) { - - case 1: - memcpy((void*)tx_layers[0], (void*)mod_symbs[0], (n_symbs<<1)*sizeof(int16_t)); - break; - - case 2: - case 3: - case 4: - for (int i=0; i<n_symbs/n_layers; i++) - for (int l=0; l<n_layers; l++) { - tx_layers[l][i<<1] = mod_symbs[0][(n_layers*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[0][((n_layers*i+l)<<1)+1]; - } - break; - - case 5: - for (int i=0; i<n_symbs>>1; i++) - for (int l=0; l<2; l++) { - tx_layers[l][i<<1] = mod_symbs[0][((i<<1)+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<1)+l)<<1)+1]; - } - for (int i=0; i<n_symbs/3; i++) - for (int l=2; l<5; l++) { - tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1]; - } - break; - - case 6: - for (int q=0; q<2; q++) - for (int i=0; i<n_symbs/3; i++) - for (int l=0; l<3; l++) { - tx_layers[l][i<<1] = mod_symbs[q][(3*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[q][((3*i+l)<<1)+1]; - } - break; - - case 7: - for (int i=0; i<n_symbs/3; i++) - for (int l=0; l<3; l++) { - tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1]; - } - for (int i=0; i<n_symbs/4; i++) - for (int l=3; l<7; l++) { - tx_layers[l][i<<1] = mod_symbs[0][((i<<2)+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<2)+l)<<1)+1]; - } - break; - - case 8: - for (int q=0; q<2; q++) - for (int i=0; i<n_symbs>>2; i++) - for (int l=0; l<3; l++) { - tx_layers[l][i<<1] = mod_symbs[q][((i<<2)+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[q][(((i<<2)+l)<<1)+1]; - } - break; - - default: - AssertFatal(0, "Invalid number of layers %d\n", n_layers); - } -} - -static inline uint16_t get_pdsch_dmrs_idx(uint8_t n, uint8_t k_prime, uint8_t delta, uint8_t dmrs_type) { - uint16_t dmrs_idx = (dmrs_type)? (6*n+k_prime+delta):((n<<2)+(k_prime<<1)+delta); - return dmrs_idx; -} -uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch, - NR_gNB_DCI_ALLOC_t dci_alloc, +uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, + NR_gNB_DCI_ALLOC_t *dci_alloc, uint32_t ***pdsch_dmrs, int32_t** txdataF, int16_t amp, int frame, uint8_t slot, - NR_DL_FRAME_PARMS frame_parms, - nfapi_nr_config_request_t config) { + NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_config_request_t *config) { - NR_DL_gNB_HARQ_t *harq = dlsch.harq_processes[dci_alloc.harq_pid]; + NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[dci_alloc->harq_pid]; nfapi_nr_dl_config_dlsch_pdu_rel15_t *rel15 = &harq->dlsch_pdu.dlsch_pdu_rel15; - nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params = dci_alloc.pdcch_params; + nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params = dci_alloc->pdcch_params; uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; - int16_t **mod_symbs = (int16_t**)dlsch.mod_symbs; - int16_t **tx_layers = (int16_t**)dlsch.txdataF; + int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; + int16_t **tx_layers = (int16_t**)dlsch->txdataF; int8_t Wf[2], Wt[2], l0, l_prime[2], delta; uint16_t nb_symbols = rel15->nb_mod_symbols; uint8_t Qm = rel15->modulation_order; @@ -214,7 +89,7 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch, /// CRC, coding, interleaving and rate matching AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); - nr_dlsch_encoding(harq->pdu, frame,slot, &dlsch, &frame_parms); + nr_dlsch_encoding(harq->pdu, frame, slot, dlsch, frame_parms); #ifdef DEBUG_DLSCH printf("PDSCH encoding:\nPayload:\n"); for (int i=0; i<harq->B>>7; i++) { @@ -237,7 +112,7 @@ printf("\n"); uint16_t n_RNTI = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? \ ((pdcch_params.scrambling_id==0)?pdcch_params.rnti:0) : 0; uint16_t Nid = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? \ - pdcch_params.scrambling_id : config.sch_config.physical_cell_id.value; + pdcch_params.scrambling_id : config->sch_config.physical_cell_id.value; for (int q=0; q<rel15->nb_codewords; q++) nr_pdsch_codeword_scrambling(harq->f, encoded_length, @@ -255,10 +130,11 @@ for (int i=0; i<encoded_length>>8; i++) { #endif /// Modulation + for (int q=0; q<rel15->nb_codewords; q++) - nr_pdsch_codeword_modulation(scrambled_output[q], - Qm, + nr_modulation(scrambled_output[q], encoded_length, + Qm, mod_symbs[q]); #ifdef DEBUG_DLSCH printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_symbols); @@ -272,7 +148,7 @@ for (int i=0; i<nb_symbols>>3; i++) { /// Layer mapping - nr_pdsch_layer_mapping(mod_symbs, + nr_layer_mapping(mod_symbs, rel15->nb_layers, nb_symbols, tx_layers); @@ -293,9 +169,12 @@ for (int l=0; l<rel15->nb_layers; l++) /// DMRS QPSK modulation uint16_t n_dmrs = (rel15->n_prb*rel15->nb_re_dmrs)<<1; int16_t mod_dmrs[n_dmrs<<1]; - uint8_t dmrs_type = config.pdsch_config.dmrs_type.value; - l0 = get_l0(dmrs_type, 2);//config.pdsch_config.dmrs_typeA_position.value); - nr_modulation(pdsch_dmrs[l0][0], n_dmrs, MOD_QPSK, mod_dmrs); // currently only codeword 0 is modulated + uint8_t dmrs_type = config->pdsch_config.dmrs_type.value; + uint8_t mapping_type = config->pdsch_config.mapping_type.value; + + l0 = get_l0(mapping_type, 2);//config->pdsch_config.dmrs_typeA_position.value); + nr_modulation(pdsch_dmrs[l0][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + #ifdef DEBUG_DLSCH printf("DMRS modulation (single symbol %d, %d symbols, type %d):\n", l0, n_dmrs>>1, dmrs_type); for (int i=0; i<n_dmrs>>4; i++) { @@ -306,13 +185,13 @@ for (int i=0; i<n_dmrs>>4; i++) { } #endif - /// Resource mapping + /// Resource mapping - // Non interleaved VRB to PRB mapping - uint16_t start_sc = frame_parms.first_carrier_offset + rel15->start_prb*NR_NB_SC_PER_RB; - if (start_sc >= frame_parms.ofdm_symbol_size) - start_sc -= frame_parms.ofdm_symbol_size; + // Non interleaved VRB to PRB mapping + uint16_t start_sc = frame_parms->first_carrier_offset + rel15->start_prb*NR_NB_SC_PER_RB; + if (start_sc >= frame_parms->ofdm_symbol_size) + start_sc -= frame_parms->ofdm_symbol_size; #ifdef DEBUG_DLSCH_MAPPING printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_symbols %d)\n", @@ -337,13 +216,13 @@ ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol); for (int l=rel15->start_symbol; l<rel15->start_symbol+rel15->nb_symbols; l++) { k = start_sc; for (int i=0; i<rel15->n_prb*NR_NB_SC_PER_RB; i++) { - if ((l == dmrs_symbol) && (k == ((start_sc+get_pdsch_dmrs_idx(n, k_prime, delta, dmrs_type))%(frame_parms.ofdm_symbol_size)))) { - ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15; - ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + if ((l == dmrs_symbol) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_type))%(frame_parms->ofdm_symbol_size)))) { + ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15; + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; #ifdef DEBUG_DLSCH_MAPPING printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n", -dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1], -((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1]); +dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1], +((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]); #endif dmrs_idx++; k_prime++; @@ -353,17 +232,17 @@ dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_s else { - ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * tx_layers[ap][m<<1]) >> 15; - ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15; + ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * tx_layers[ap][m<<1]) >> 15; + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15; #ifdef DEBUG_DLSCH_MAPPING printf("m %d\t l %d \t k %d \t txdataF: %d %d\n", -m, l, k, ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1], -((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1]); +m, l, k, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1], +((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]); #endif m++; } - if (++k >= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; + if (++k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; } } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index a2de3a231af2169a2f985c5d34b5004f25c612a3..7c3e22a9e713c0fb9e95e545821508ba37fa59db 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -30,9 +30,10 @@ * \warning */ -#include "PHY/defs_gNB.h" +#ifndef __NR_DLSCH__H +#define __NR_DLSCH__H -extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; +#include "PHY/defs_gNB.h" void nr_get_time_domain_allocation_type(nfapi_nr_config_request_t config, nfapi_nr_dl_config_dci_dl_pdu dci_pdu, @@ -52,14 +53,6 @@ void nr_get_rbg_list(uint32_t bitmap, uint8_t n_rbg, uint8_t* rbg_list); void nr_get_PRG_parms(NR_BWP_PARMS* bwp, NR_gNB_DCI_ALLOC_t dci_alloc, uint8_t prb_bundling_type); -uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx); - -uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx); - -void nr_get_tbs(nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu, - nfapi_nr_dl_config_dci_dl_pdu dci_pdu, - nfapi_nr_config_request_t config); - void nr_pdsch_codeword_scrambling(uint8_t *in, uint16_t size, uint8_t q, @@ -67,42 +60,21 @@ void nr_pdsch_codeword_scrambling(uint8_t *in, uint32_t n_RNTI, uint32_t* out); -void nr_modulation(uint32_t *in, - uint16_t length, - nr_mod_t modulation_type, - int16_t *out); - -void nr_pdsch_codeword_modulation(uint32_t *in, - uint8_t Qm, - uint32_t length, - int16_t *out); - -void nr_pdsch_layer_mapping(int16_t **mod_symbs, - uint8_t n_layers, - uint16_t n_symbs, - int16_t **tx_layers); - void nr_fill_dlsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu, unsigned char *sdu); -uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch, - NR_gNB_DCI_ALLOC_t dci_alloc, +uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, + NR_gNB_DCI_ALLOC_t *dci_alloc, uint32_t ***pdsch_dmrs, int32_t** txdataF, int16_t amp, int frame, uint8_t slot, - NR_DL_FRAME_PARMS frame_parms, - nfapi_nr_config_request_t config); - -/** \brief Computes available bits G. - @param nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs */ -uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16_t length_dmrs,uint8_t Qm, uint8_t Nl); - -uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r); + NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_config_request_t *config); void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); @@ -120,3 +92,4 @@ int nr_dlsch_encoding(unsigned char *a,int frame, void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size); +#endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index c8a602e8d04bf6cf7d005e6659a0f21eaece2dce..b3ce80d1ae2e6a2b5cfa8e841ed0791346f60d07 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -151,11 +151,11 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(unsigned char Kmimo, } } - dlsch->txdataF[layer] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH>>1)*sizeof(int32_t*)); + dlsch->txdataF[layer] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH/NR_MAX_NB_LAYERS)*sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH } for (int q=0; q<NR_MAX_NB_CODEWORDS; q++) - dlsch->mod_symbs[q] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH>>1)*sizeof(int32_t*)); + dlsch->mod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH*sizeof(int32_t)); dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(64*sizeof(int32_t*)); for (aa=0; aa<64; aa++) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c index 4ec1083cfce4b682e97dae57276529b47662abf7..8d9bf00639ae1816183699c18923b67862280514 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c @@ -34,6 +34,7 @@ /*Table 7.4.1.1.2-1 and 7.4.1.1.2-2 38211 Columns: ap - CDM group - Delta - Wf(0) - Wf(1) - Wt(0) - Wt(1)*/ +/*Table 6.4.1.1.3-1 is identical to Table 7.4.1.1.2-1 and Table 6.4.1.1.3-2 is identical to Table 7.4.1.1.2-2. UL DMRS can reuse these tables*/ int8_t pdsch_dmrs_1[8][7] = {{0,0,0,1,1,1,1}, {1,0,0,1,-1,1,1}, {2,1,1,1,1,1,1}, @@ -84,6 +85,13 @@ uint8_t get_delta(uint8_t ap, uint8_t config) { return ((config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][2]):(pdsch_dmrs_2[ap][2])); } -uint8_t get_l0(uint8_t config, uint8_t dmrs_typeA_position) { - return ((config==NFAPI_NR_DMRS_TYPE1)?dmrs_typeA_position:0); +uint16_t get_dmrs_freq_idx(uint8_t n, uint8_t k_prime, uint8_t delta, uint8_t dmrs_type) { + uint16_t dmrs_idx = (dmrs_type)? (6*n+k_prime+delta):((n<<2)+(k_prime<<1)+delta); + return dmrs_idx; +} + +uint8_t get_l0(uint8_t mapping_type, uint8_t dmrs_typeA_position) { + + return ((mapping_type==NFAPI_NR_PDSCH_MAPPING_TYPE_A)?dmrs_typeA_position:0); + } diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h index b112e46c1c71a0a454d12d83b59c1c7c286107d3..02f454b7d0120969dafc547dc0e164db16ce87fc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_TRANSPORT/nr_sch_dmrs.c +/*! \file PHY/NR_TRANSPORT/nr_sch_dmrs.h * \brief * \author * \date @@ -30,7 +30,7 @@ * \warning */ -#include "PHY/defs_gNB.h" +#include "PHY/defs_nr_common.h" #define NR_PDSCH_DMRS_ANTENNA_PORT0 1000 #define NR_PDSCH_DMRS_NB_ANTENNA_PORTS 12 @@ -45,4 +45,6 @@ void get_Wf(int8_t *Wf, uint8_t ap, uint8_t config); uint8_t get_delta(uint8_t ap, uint8_t config); -uint8_t get_l0(uint8_t config, uint8_t dmrs_typeA_position); +uint16_t get_dmrs_freq_idx(uint8_t n, uint8_t k_prime, uint8_t delta, uint8_t dmrs_type); + +uint8_t get_l0(uint8_t mapping_type, uint8_t dmrs_typeA_position); diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c index 79fe3817a88109c7b4aa6bba9bb00e09724395f8..07ca17cd6d825b0612ad9bf4e16e615b780919a0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file PHY/LTE_TRANSPORT/dlsch_coding.c +/*! \file PHY/NR_TRANSPORT/nr_tbs_tools.c * \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2 * \author H.Wang * \date 2018 @@ -30,7 +30,7 @@ * \warning */ -#include "nr_dlsch.h" +#include "nr_transport_common_proto.h" /// Target code rate tables indexed by Imcs uint16_t nr_target_code_rate_table1[29] = {120, 157, 193, 251, 308, 379, 449, 526, 602, 679, 340, 378, 434, 490, 553, \ diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index 14ba3de923786dd4d906e6a42fbb2f09640fb441..36f3fb5c2c6a2446f17a583624db94a61f7e65ac 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -20,8 +20,8 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_TRANSPORT/nr_mcs.c -* \brief Some support routines for NR MCS computations +/*! \file PHY/NR_TRANSPORT/nr_transport_common_proto.h +* \brief Some support routines * \author * \date 2018 * \version 0.1 @@ -34,6 +34,8 @@ #ifndef __NR_TRANSPORT_COMMON_PROTO__H__ #define __NR_TRANSPORT_COMMON_PROTO__H__ +#include "PHY/defs_nr_common.h" + #define MAX_NUM_NR_DLSCH_SEGMENTS 16 #define MAX_NUM_NR_ULSCH_SEGMENTS MAX_NUM_NR_DLSCH_SEGMENTS @@ -43,14 +45,21 @@ #define MAX_NUM_NR_CHANNEL_BITS (14*273*12*6) // 14 symbols, 273 RB #define MAX_NUM_NR_RE (14*273*12) -// Functions below implement minor procedures from 38-214 +#define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1 +#define NR_PUSCH_y 3 // UCI placeholder bit + +/** \brief Computes Q based on I_MCS PDSCH and table_idx. Implements Table 5.1.3.1-2 from 38.214. */ +uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx); + +uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx); + +void nr_get_tbs(nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu, + nfapi_nr_dl_config_dci_dl_pdu dci_pdu, + nfapi_nr_config_request_t config); -/** \brief Computes Q based on I_MCS PDSCH and when 'MCS-Table-PDSCH' is set to "256QAM". Implements Table 5.1.3.1-2 from 38.214. - @param I_MCS */ -uint8_t get_nr_Qm(uint8_t I_MCS); +/** \brief Computes available bits G. */ +uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch, uint8_t nb_re_dmrs, uint16_t length_dmrs, uint8_t Qm, uint8_t Nl); -/** \brief Computes Q based on I_MCS PUSCH. Implements Table 6.1.4.1-1 from 38.214. - @param I_MCS */ -uint8_t get_nr_Qm_ul(uint8_t I_MCS); +uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r); #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h new file mode 100644 index 0000000000000000000000000000000000000000..2dbef1d733ff2b88aabc9194306ff110d725d29c --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -0,0 +1,140 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_TRANSPORT/nr_transport_proto.h.c +* \brief Function prototypes for PHY physical/transport channel processing and generation +* \author Ahmed Hussein +* \date 2019 +* \version 0.1 +* \company Fraunhofer IIS +* \email: ahmed.hussein@iis.fraunhofer.de +* \note +* \warning +*/ + +#include "PHY/defs_nr_common.h" + +/** \brief This function is the top-level entry point to PUSCH demodulation, after frequency-domain transformation and channel estimation. It performs + - RB extraction (signal and channel estimates) + - channel compensation (matched filtering) + - RE extraction (dmrs) + - antenna combining (MRC, Alamouti, cycling) + - LLR computation + This function supports TM1, 2, 3, 5, and 6. + @param ue Pointer to PHY variables + @param UE_id id of current UE + @param frame Frame number + @param nr_tti_rx TTI number + @param symbol Symbol on which to act (within-in nr_TTI_rx) + @param harq_pid HARQ process ID +*/ +void nr_rx_pusch(PHY_VARS_gNB *gNB, + uint8_t UE_id, + uint32_t frame, + uint8_t nr_tti_rx, + unsigned char symbol, + unsigned char harq_pid); + + +/** \brief This function performs RB extraction (signal and channel estimates) (currently signal only until channel estimation and compensation are implemented) + @param rxdataF pointer to the received frequency domain signal + @param rxdataF_ext pointer to the extracted frequency domain signal + @param rb_alloc RB allocation map (used for Resource Allocation Type 0 in NR) + @param symbol Symbol on which to act (within-in nr_TTI_rx) + @param start_rb The starting RB in the RB allocation (used for Resource Allocation Type 1 in NR) + @param nb_rb_pusch The number of RBs allocated (used for Resource Allocation Type 1 in NR) + @param frame_parms, Pointer to frame descriptor structure + +*/ +void nr_ulsch_extract_rbs_single(int **rxdataF, + int **rxdataF_ext, + uint32_t rxdataF_ext_offset, + // unsigned int *rb_alloc, [hna] Resource Allocation Type 1 is assumed only for the moment + unsigned char symbol, + unsigned short start_rb, + unsigned short nb_rb_pusch, + NR_DL_FRAME_PARMS *frame_parms); + +/*! +\brief This function implements the idft transform precoding in PUSCH +\param z Pointer to input in frequnecy domain, and it is also the output in time domain +\param Msc_PUSCH number of allocated data subcarriers +*/ +void nr_idft(uint32_t *z, uint32_t Msc_PUSCH); + +/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms. + @param rxdataF_comp Compensated channel output + @param ulsch_llr llr output + @param nb_re number of REs for this allocation + @param symbol OFDM symbol index in sub-frame +*/ +void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol); + + +/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 16 QAM received waveforms. + @param rxdataF_comp Compensated channel output + @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 16 + @param ulsch_llr llr output + @param nb_re number of RBs for this allocation + @param symbol OFDM symbol index in sub-frame +*/ +void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, + int32_t **ul_ch_mag, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol); + + +/** \brief This function generates log-likelihood ratios (decoder input) for single-stream 64 QAM received waveforms. + @param rxdataF_comp Compensated channel output + @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 + @param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 64 + @param ulsch_llr llr output + @param nb_re number of REs for this allocation + @param symbol OFDM symbol index in sub-frame +*/ +void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, + int32_t **ul_ch_mag, + int32_t **ul_ch_magb, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol); + + +/** \brief This function computes the log-likelihood ratios for 4, 16, and 64 QAM + @param rxdataF_comp Compensated channel output + @param ul_ch_mag uplink channel magnitude multiplied by the 1st amplitude threshold in QAM 64 + @param ul_ch_magb uplink channel magnitude multiplied by the 2bd amplitude threshold in QAM 64 + @param ulsch_llr llr output + @param nb_re number of REs for this allocation + @param symbol OFDM symbol index in sub-frame + @param mod_order modulation order +*/ +void nr_ulsch_compute_llr(int32_t *rxdataF_comp, + int32_t **ul_ch_mag, + int32_t **ul_ch_magb, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol, + uint8_t mod_order); \ No newline at end of file diff --git a/openair1/PHY/NR_TRANSPORT/nr_mcs.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c similarity index 59% rename from openair1/PHY/NR_TRANSPORT/nr_mcs.c rename to openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 979a576256e8b37048f47aa65673c989d1e0883f..2bc623a66c2db7aa152983aab7b5af6621e5740a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_mcs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -19,41 +19,40 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_TRANSPORT/nr_mcs.c -* \brief Some support routines for NR MCS computations -* \author -* \date 2018 +/*! \file PHY/NR_TRANSPORT/nr_ulsch.c +* \brief Top-level routines for the reception of the PUSCH TS 38.211 v 15.4.0 +* \author Ahmed Hussein +* \date 2019 * \version 0.1 -* \company Eurecom -* \email: +* \company Fraunhofer IIS +* \email: ahmed.hussein@iis.fraunhofer.de * \note * \warning */ +#include <stdint.h> #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_TRANSPORT/nr_ulsch.h" +#include "PHY/LTE_REFSIG/lte_refsig.h" -//get_Qm under PHY/LTE_TRANSPORT/lte_mcs.c is the same for NR. - -uint8_t get_nr_Qm(uint8_t I_MCS) +void nr_ulsch_unscrambling(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI) { - if (I_MCS < 5) - return(2); - else if (I_MCS < 11) - return(4); - else if (I_MCS < 20) - return(6); - else - return(8); -} + uint8_t reset; + uint32_t x1, x2, s=0; -uint8_t get_nr_Qm_ul(uint8_t I_MCS) { + reset = 1; + x2 = (n_RNTI<<15) + Nid; - if (I_MCS < 2) - return(2); //This should be 1 if UE has reported to support pi/2 BPSK, and 2 otherwise. - else if (I_MCS < 10) - return(2); - else if (I_MCS < 17) - return(4); - else - return(6); + for (uint32_t i=0; i<size; i++) { + if ((i&0x1f)==0) { + s = lte_gold_generic(&x1, &x2, reset); + reset = 0; + } + if (((s>>(i&0x1f))&1)==1) + llr[i] = -llr[i]; + } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index 77cc1016795a7d6512dc55c2b134390db34ff337..11521563e499cc812d15101a2942f00a6688611d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -36,6 +36,18 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch); NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag); + +/*! \brief Perform PUSCH decoding. TS 38.212 V15.4.0 subclause 6.2 + @param phy_vars_gNB, Pointer to PHY data structure for gNB + @param UE_id, ID of UE transmitting this PUSCH + @param ulsch_llr, Pointer to received llr in ulsch + @param frame_parms, Pointer to frame descriptor structure + @param nb_symb_sch, number of symbols used in the uplink shared channel + @param nr_tti_rx, current received TTI + @param harq_pid, harq process id + @param is_crnti +*/ + uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t UE_id, short *ulsch_llr, @@ -44,6 +56,26 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint16_t nb_symb_sch, uint8_t nr_tti_rx, uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag); + uint8_t is_crnti); + + +/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 + @param llr, Pointer to llr bits + @param size, length of llr bits + @param q, codeword index (0,1) + @param Nid, cell id + @param n_RNTI, CRNTI +*/ + +void nr_ulsch_unscrambling(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI); + + +void nr_ulsch_procedures(PHY_VARS_gNB *gNB, + gNB_L1_rxtx_proc_t *proc, + int UE_id, + uint8_t harq_pid); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index f9d82914234200649435a7931c80dccb3a3c3f23..6ca27331204ea2b2782f5da0f4e3893120a3a998 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -233,7 +233,6 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch) /// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) //int16_t e[MAX_NUM_NR_DLSCH_SEGMENTS][3*8448]; ulsch->harq_processes[i]->E=0; - ulsch->harq_processes[i]->G=0; ulsch->harq_processes[i]->n_DMRS=0; @@ -278,8 +277,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint16_t nb_symb_sch, uint8_t nr_tti_rx, uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag) + uint8_t is_crnti) { uint32_t A,E; @@ -291,7 +289,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); - NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0]; + NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id+1][0]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; nfapi_nr_ul_config_ulsch_pdu_rel15_t *nfapi_ulsch_pdu_rel15 = &harq_process->ulsch_pdu.ulsch_pdu_rel15; @@ -301,16 +299,22 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, t_nrLDPC_time_stats* p_procTime = &procTime ; t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf; - int16_t z [68*384]; - int8_t l [68*384]; - //int16_t inv_d [68*384]; - uint8_t kc; - uint8_t Ilbrm = 0; + int16_t z [68*384]; + int8_t l [68*384]; + uint8_t kc; + uint8_t Ilbrm = 0; uint32_t Tbslbrm = 950984; - uint16_t nb_rb = 30; //to update - uint8_t nb_re_dmrs = 6; - uint16_t length_dmrs = 1; - double Coderate = 0.0; + double Coderate = 0.0; + + // ------------------------------------------------------------------ + uint16_t nb_rb = nfapi_ulsch_pdu_rel15->number_rbs; + uint16_t number_symbols = nfapi_ulsch_pdu_rel15->number_symbols; + uint8_t Qm = nfapi_ulsch_pdu_rel15->Qm; + uint8_t mcs = nfapi_ulsch_pdu_rel15->mcs; + uint8_t n_layers = nfapi_ulsch_pdu_rel15->n_layers; + uint8_t nb_re_dmrs = nfapi_ulsch_pdu_rel15->nb_re_dmrs; + uint8_t length_dmrs = nfapi_ulsch_pdu_rel15->length_dmrs; + // ------------------------------------------------------------------ uint32_t i,j; @@ -333,19 +337,18 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, return(ulsch->max_ldpc_iterations); } - nb_rb = nfapi_ulsch_pdu_rel15->number_rbs; - // harq_process->trials[nfapi_ulsch_pdu_rel15->round]++; - - harq_process->TBS = nr_compute_tbs(nfapi_ulsch_pdu_rel15->mcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, nfapi_ulsch_pdu_rel15->n_layers); + + harq_process->TBS = nr_compute_tbs(mcs, nb_rb, number_symbols, nb_re_dmrs, length_dmrs, n_layers); A = harq_process->TBS; ret = ulsch->max_ldpc_iterations; + + G = nr_get_G(nb_rb, number_symbols, nb_re_dmrs, length_dmrs, Qm, n_layers); + // G = 0; + // G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, nfapi_ulsch_pdu_rel15->Qm, nfapi_ulsch_pdu_rel15->n_layers); - harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, nfapi_ulsch_pdu_rel15->Qm,nfapi_ulsch_pdu_rel15->n_layers); - G = harq_process->G; - - LOG_I(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nfapi_ulsch_pdu_rel15->mcs, nfapi_ulsch_pdu_rel15->n_layers, nb_symb_sch,nb_rb); + LOG_I(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, mcs, n_layers, nb_symb_sch,nb_rb); if (harq_process->round == 0) { @@ -443,7 +446,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, nfapi_ulsch_pdu_rel15->n_layers); for (r=0; r<harq_process->C; r++) { - E = nr_get_E(G, harq_process->C, nfapi_ulsch_pdu_rel15->Qm, nfapi_ulsch_pdu_rel15->n_layers, r); #if gNB_TIMING_TRACE @@ -582,10 +584,10 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, p_procTime); if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - printf("Segment %d CRC OK\n",r); + LOG_I(PHY, "Segment %d CRC OK\n",r); ret = 2; } else { - printf("CRC NOK\n"); + LOG_I(PHY, "CRC NOK\n"); ret = 1+ulsch->max_ldpc_iterations; } @@ -595,7 +597,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, } ret=no_iteration_ldpc; - + for (int m=0; m < Kr>>3; m ++) { harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c new file mode 100644 index 0000000000000000000000000000000000000000..d70e61e3581bd730c2c5b75fa65d179ba8433594 --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -0,0 +1,309 @@ +#include "PHY/defs_gNB.h" +#include "PHY/phy_extern.h" +#include "nr_transport_proto.h" +#include "PHY/impl_defs_top.h" +#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" +#include "PHY/defs_nr_common.h" + +void nr_idft(uint32_t *z, uint32_t Msc_PUSCH) +{ + +#if defined(__x86_64__) || defined(__i386__) + __m128i idft_in128[1][1200], idft_out128[1][1200]; + __m128i norm128; +#elif defined(__arm__) + int16x8_t idft_in128[1][1200], idft_out128[1][1200]; + int16x8_t norm128; +#endif + int16_t *idft_in0 = (int16_t*)idft_in128[0], *idft_out0 = (int16_t*)idft_out128[0]; + + int i, ip; + + LOG_T(PHY,"Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH); + + // conjugate input + for (i = 0; i < (Msc_PUSCH>>2); i++) { +#if defined(__x86_64__)||defined(__i386__) + *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]); +#elif defined(__arm__) + *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); +#endif + } + + for (i=0,ip=0; i<Msc_PUSCH; i++, ip+=4) { + ((uint32_t*)idft_in0)[ip+0] = z[i]; + } + + + switch (Msc_PUSCH) { + case 12: + dft12((int16_t *)idft_in0, (int16_t *)idft_out0); + +#if defined(__x86_64__)||defined(__i386__) + norm128 = _mm_set1_epi16(9459); +#elif defined(__arm__) + norm128 = vdupq_n_s16(9459); +#endif + + for (i = 0; i < 12; i++) { +#if defined(__x86_64__)||defined(__i386__) + ((__m128i*)idft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out0)[i], norm128), 1); +#elif defined(__arm__) + ((int16x8_t*)idft_out0)[i] = vqdmulhq_s16(((int16x8_t*)idft_out0)[i], norm128); +#endif + } + + break; + + case 24: + dft24(idft_in0, idft_out0, 1); + break; + + case 36: + dft36(idft_in0, idft_out0, 1); + break; + + case 48: + dft48(idft_in0, idft_out0, 1); + break; + + case 60: + dft60(idft_in0, idft_out0, 1); + break; + + case 72: + dft72(idft_in0, idft_out0, 1); + break; + + case 96: + dft96(idft_in0, idft_out0, 1); + break; + + case 108: + dft108(idft_in0, idft_out0, 1); + break; + + case 120: + dft120(idft_in0, idft_out0, 1); + break; + + case 144: + dft144(idft_in0, idft_out0, 1); + break; + + case 180: + dft180(idft_in0, idft_out0, 1); + break; + + case 192: + dft192(idft_in0, idft_out0, 1); + break; + + case 216: + dft216(idft_in0, idft_out0, 1); + break; + + case 240: + dft240(idft_in0, idft_out0, 1); + break; + + case 288: + dft288(idft_in0, idft_out0, 1); + break; + + case 300: + dft300(idft_in0, idft_out0, 1); + break; + + case 324: + dft324((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 360: + dft360((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 384: + dft384((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 432: + dft432((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 480: + dft480((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 540: + dft540((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 576: + dft576((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 600: + dft600((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 648: + dft648((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 720: + dft720((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 768: + dft768((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 864: + dft864((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 900: + dft900((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 960: + dft960((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 972: + dft972((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 1080: + dft1080((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 1152: + dft1152((int16_t*)idft_in0, (int16_t*)idft_out0, 1); + break; + + case 1200: + dft1200(idft_in0, idft_out0, 1); + break; + + default: + // should not be reached + LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH ); + return; + } + + + + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { + z[i] = ((uint32_t*)idft_out0)[ip]; + } + + // conjugate output + for (i = 0; i < (Msc_PUSCH>>2); i++) { +#if defined(__x86_64__) || defined(__i386__) + ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]); +#elif defined(__arm__) + *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); +#endif + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif + +} + +void nr_ulsch_extract_rbs_single(int **rxdataF, + int **rxdataF_ext, + uint32_t rxdataF_ext_offset, + // unsigned int *rb_alloc, [hna] Resource Allocation Type 1 is assumed only for the moment + unsigned char symbol, + unsigned short start_rb, + unsigned short nb_rb_pusch, + NR_DL_FRAME_PARMS *frame_parms) +{ + unsigned short start_re, re, nb_re_pusch; + unsigned char aarx, is_dmrs_symbol = 0; + uint32_t rxF_ext_index = 0; + + int16_t *rxF,*rxF_ext; + + is_dmrs_symbol = (symbol == 2) ? 1 : 0; //to be updated from config + + start_re = frame_parms->first_carrier_offset + (start_rb * NR_NB_SC_PER_RB); + + nb_re_pusch = NR_NB_SC_PER_RB * nb_rb_pusch; + + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + + rxF = (int16_t *)&rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; + rxF_ext = (int16_t *)&rxdataF_ext[aarx][symbol * nb_re_pusch]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6 + + for (re = 0; re < nb_re_pusch; re++) { + + if ( (is_dmrs_symbol && ((re&1) != 0)) || (is_dmrs_symbol == 0) ) { // [hna] (re&1) != frame_parms->nushift) assuming only dmrs type 1 and mapping type A + // frame_parms->nushift should be initialized with 0 + rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); + rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]); + rxF_ext_index = rxF_ext_index + 2; + } + } + } +} + + + +void nr_rx_pusch(PHY_VARS_gNB *gNB, + uint8_t UE_id, + uint32_t frame, + uint8_t nr_tti_rx, + unsigned char symbol, + unsigned char harq_pid) +{ + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15; + uint32_t nb_re_pusch; + + if(symbol == rel15_ul->start_symbol) + gNB->pusch_vars[UE_id]->rxdataF_ext_offset = 0; + + if (symbol == 2) // [hna] here it is assumed that symbol 2 carries 6 DMRS REs (dmrs-type 1) + nb_re_pusch = rel15_ul->number_rbs * 6; + else + nb_re_pusch = rel15_ul->number_rbs * NR_NB_SC_PER_RB; + + //---------------------------------------------------------- + //--------------------- RBs extraction --------------------- + //---------------------------------------------------------- + + nr_ulsch_extract_rbs_single(gNB->common_vars.rxdataF, + gNB->pusch_vars[UE_id]->rxdataF_ext, + gNB->pusch_vars[UE_id]->rxdataF_ext_offset, + // rb_alloc, [hna] Resource Allocation Type 1 is assumed only for the moment + symbol, + rel15_ul->start_rb, + rel15_ul->number_rbs, + frame_parms); + +#ifdef NR_SC_FDMA + nr_idft(&((uint32_t*)gNB->pusch_vars[UE_id]->rxdataF_ext[0])[symbol * rel15_ul->number_rbs * NR_NB_SC_PER_RB], nb_re_pusch); +#endif + + //---------------------------------------------------------- + //-------------------- LLRs computation -------------------- + //---------------------------------------------------------- + + nr_ulsch_compute_llr(&gNB->pusch_vars[UE_id]->rxdataF_ext[0][symbol * rel15_ul->number_rbs * NR_NB_SC_PER_RB], + gNB->pusch_vars[UE_id]->ul_ch_mag, + gNB->pusch_vars[UE_id]->ul_ch_magb, + &gNB->pusch_vars[UE_id]->llr[gNB->pusch_vars[UE_id]->rxdataF_ext_offset * rel15_ul->Qm], + nb_re_pusch, + symbol, + rel15_ul->Qm); + + gNB->pusch_vars[UE_id]->rxdataF_ext_offset = gNB->pusch_vars[UE_id]->rxdataF_ext_offset + nb_re_pusch; + +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c new file mode 100644 index 0000000000000000000000000000000000000000..d2d8cdd927bb5dae4e79e3074f90bdc7084569b7 --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -0,0 +1,364 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c + * \brief Top-level routines for LLR computation of the PDSCH physical channel + * \author Ahmed Hussein + * \date 2019 + * \version 0.1 + * \company Fraunhofer IIS + * \email: ahmed.hussein@iis.fraunhofer.de + * \note + * \warning + */ + + +#include "PHY/defs_nr_common.h" +#include "PHY/sse_intrin.h" +#include "PHY/impl_defs_top.h" + +__m128i xmm0 __attribute__ ((aligned(32))); +__m128i xmm1 __attribute__ ((aligned(32))); +__m128i xmm2 __attribute__ ((aligned(32))); + + +//---------------------------------------------------------------------------------------------- +// QPSK +//---------------------------------------------------------------------------------------------- +void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol) +{ + int i; + + uint32_t *rxF = (uint32_t*)rxdataF_comp; + uint32_t *llr32 = (uint32_t*)ulsch_llr; + + if (!llr32) { + LOG_E(PHY,"nr_ulsch_qpsk_llr: llr is null, symbol %d, llr32 = %p\n",symbol, llr32); + } + + for (i = 0; i < nb_re; i++) { + *llr32 = *rxF; + rxF++; + llr32++; + } +} + +//---------------------------------------------------------------------------------------------- +// 16-QAM +//---------------------------------------------------------------------------------------------- + +void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, + int32_t **ul_ch_mag, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol) +{ +#if defined(__x86_64__) || defined(__i386__) + __m128i *rxF = (__m128i*)rxdataF_comp; + // __m128i *ch_mag; // [hna] This should be uncommented once channel estimation is implemented + __m128i llr128[2]; + uint32_t *llr32; + + // [hna] temp_channel and one_over_sqrt_2 are for temporary use until channel estimation is implemented + // else ul_ch_mag and ul_ch_magb should be used after channel estimation has benn implemented + __m128i temp_channel; + int16_t one_over_sqrt_2 = 23170; + +#elif defined(__arm__) + int16x8_t *rxF = (int16x8_t*)&rxdataF_comp; + // int16x8_t *ch_mag; // [hna] This should be uncommented once channel estimation is implemented + int16x8_t xmm0; + int16_t *llr16; +#endif + + + int i; + unsigned char len_mod4 = 0; + + +#if defined(__x86_64__) || defined(__i386__) + llr32 = (uint32_t*)ulsch_llr; +#elif defined(__arm__) + llr16 = (int16_t*)ulsch_llr; +#endif + +// [hna] This should be uncommented once channel estimation is implemented +// ------------------------------------------------------------ +// #if defined(__x86_64__) || defined(__i386__) +// ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*nb_rb*12)]; +// #elif defined(__arm__) +// ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*nb_rb*12)]; +// #endif +// ------------------------------------------------------------ + + len_mod4 = nb_re&3; + nb_re >>= 2; // length in quad words (4 REs) + nb_re += (len_mod4 == 0 ? 0 : 1); + + temp_channel = _mm_set1_epi16((QAM16_n1 * one_over_sqrt_2)>>(2*15-AMP_SHIFT)); + + for (i=0; i<nb_re; i++) { + +#if defined(__x86_64__) || defined(__i386) + + xmm0 = _mm_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| + + + xmm0 = _mm_subs_epi16(temp_channel,xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + + llr128[0] = _mm_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st and 2nd REs + llr128[1] = _mm_unpackhi_epi32(rxF[i],xmm0); // llr128[1] contains the llrs of the 3rd and 4th REs + + // 1st RE + llr32[0] = _mm_extract_epi32(llr128[0],0); // llr32[0] low 16 bits-> y_R , high 16 bits-> y_I + llr32[1] = _mm_extract_epi32(llr128[0],1); // llr32[1] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 2nd RE + llr32[2] = _mm_extract_epi32(llr128[0],2); // llr32[2] low 16 bits-> y_R , high 16 bits-> y_I + llr32[3] = _mm_extract_epi32(llr128[0],3); // llr32[3] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 3rd RE + llr32[4] = _mm_extract_epi32(llr128[1],0); // llr32[4] low 16 bits-> y_R , high 16 bits-> y_I + llr32[5] = _mm_extract_epi32(llr128[1],1); // llr32[5] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 4th RE + llr32[6] = _mm_extract_epi32(llr128[1],2); // llr32[6] low 16 bits-> y_R , high 16 bits-> y_I + llr32[7] = _mm_extract_epi32(llr128[1],3); // llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + llr32+=8; +#elif defined(__arm__) + xmm0 = vabsq_s16(rxF[i]); + xmm0 = vqsubq_s16((*(__m128i*)&ones[0]),xmm0); + + llr16[0] = vgetq_lane_s16(rxF[i],0); + llr16[1] = vgetq_lane_s16(rxF[i],1); + llr16[2] = vgetq_lane_s16(xmm0,0); + llr16[3] = vgetq_lane_s16(xmm0,1); + llr16[4] = vgetq_lane_s16(rxF[i],2); + llr16[5] = vgetq_lane_s16(rxF[i],3); + llr16[6] = vgetq_lane_s16(xmm0,2); + llr16[7] = vgetq_lane_s16(xmm0,3); + llr16[8] = vgetq_lane_s16(rxF[i],4); + llr16[9] = vgetq_lane_s16(rxF[i],5); + llr16[10] = vgetq_lane_s16(xmm0,4); + llr16[11] = vgetq_lane_s16(xmm0,5); + llr16[12] = vgetq_lane_s16(rxF[i],6); + llr16[13] = vgetq_lane_s16(rxF[i],6); + llr16[14] = vgetq_lane_s16(xmm0,7); + llr16[15] = vgetq_lane_s16(xmm0,7); + llr16+=16; +#endif + + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif +} + +//---------------------------------------------------------------------------------------------- +// 64-QAM +//---------------------------------------------------------------------------------------------- + +void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, + int32_t **ul_ch_mag, + int32_t **ul_ch_magb, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol) +{ +#if defined(__x86_64__) || defined(__i386__) + __m128i *rxF = (__m128i*)rxdataF_comp; + // __m128i *ch_mag,*ch_magb; // [hna] This should be uncommented once channel estimation is implemented + + // [hna] temp_channel and one_over_sqrt_2 are for temporary use until channel estimation is implemented + // else ul_ch_mag and ul_ch_magb should be used after channel estimation has been implemented + __m128i temp_channel[2]; + int16_t one_over_sqrt_2 = 23170; + +#elif defined(__arm__) + int16x8_t *rxF = (int16x8_t*)&rxdataF_comp; + // int16x8_t *ch_mag,*ch_magb; // [hna] This should be uncommented once channel estimation is implemented + int16x8_t xmm1,xmm2; +#endif + + int i; + unsigned char len_mod4; + +// [hna] This should be uncommented once channel estimation is implemented +// ------------------------------------------------------------------------- +// #if defined(__x86_64__) || defined(__i386__) +// ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*frame_parms->N_RB_UL*12)]; +// ch_magb = (__m128i*)&ul_ch_magb[0][(symbol*frame_parms->N_RB_UL*12)]; +// #elif defined(__arm__) +// ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*frame_parms->N_RB_UL*12)]; +// ch_magb = (int16x8_t*)&ul_ch_magb[0][(symbol*frame_parms->N_RB_UL*12)]; +// #endif +// ------------------------------------------------------------------------- + + len_mod4 = nb_re&3; + nb_re = nb_re>>2; // length in quad words (4 REs) + nb_re += ((len_mod4 == 0) ? 0 : 1); + + temp_channel[0] = _mm_set1_epi16((QAM64_n1 * one_over_sqrt_2)>>(2*15-AMP_SHIFT)); + temp_channel[1] = _mm_set1_epi16((QAM64_n2 * one_over_sqrt_2)>>(2*15-AMP_SHIFT)); + + for (i=0; i<nb_re; i++) { + +#if defined(__x86_64__) || defined(__i386__) + xmm1 = _mm_abs_epi16(rxF[i]); + xmm1 = _mm_subs_epi16(temp_channel[0],xmm1); + xmm2 = _mm_abs_epi16(xmm1); + xmm2 = _mm_subs_epi16(temp_channel[1],xmm2); +#elif defined(__arm__) + xmm1 = vabsq_s16(rxF[i]); + xmm1 = vsubq_s16(ch_mag[i],xmm1); + xmm2 = vabsq_s16(xmm1); + xmm2 = vsubq_s16(ch_magb[i],xmm2); +#endif + + // --------------------------------------- + // 1st RE + // --------------------------------------- + ulsch_llr[0] = ((short *)&rxF[i])[0]; + ulsch_llr[1] = ((short *)&rxF[i])[1]; +#if defined(__x86_64__) || defined(__i386__) + ulsch_llr[2] = _mm_extract_epi16(xmm1,0); + ulsch_llr[3] = _mm_extract_epi16(xmm1,1); + ulsch_llr[4] = _mm_extract_epi16(xmm2,0); + ulsch_llr[5] = _mm_extract_epi16(xmm2,1); +#elif defined(__arm__) + ulsch_llr[2] = vgetq_lane_s16(xmm1,0); + ulsch_llr[3] = vgetq_lane_s16(xmm1,1); + ulsch_llr[4] = vgetq_lane_s16(xmm2,0); + ulsch_llr[5] = vgetq_lane_s16(xmm2,1); +#endif + // --------------------------------------- + + ulsch_llr+=6; + + // --------------------------------------- + // 2nd RE + // --------------------------------------- + ulsch_llr[0] = ((short *)&rxF[i])[2]; + ulsch_llr[1] = ((short *)&rxF[i])[3]; +#if defined(__x86_64__) || defined(__i386__) + ulsch_llr[2] = _mm_extract_epi16(xmm1,2); + ulsch_llr[3] = _mm_extract_epi16(xmm1,3); + ulsch_llr[4] = _mm_extract_epi16(xmm2,2); + ulsch_llr[5] = _mm_extract_epi16(xmm2,3); +#elif defined(__arm__) + ulsch_llr[2] = vgetq_lane_s16(xmm1,2); + ulsch_llr[3] = vgetq_lane_s16(xmm1,3); + ulsch_llr[4] = vgetq_lane_s16(xmm2,2); + ulsch_llr[5] = vgetq_lane_s16(xmm2,3); +#endif + // --------------------------------------- + + ulsch_llr+=6; + + // --------------------------------------- + // 3rd RE + // --------------------------------------- + ulsch_llr[0] = ((short *)&rxF[i])[4]; + ulsch_llr[1] = ((short *)&rxF[i])[5]; +#if defined(__x86_64__) || defined(__i386__) + ulsch_llr[2] = _mm_extract_epi16(xmm1,4); + ulsch_llr[3] = _mm_extract_epi16(xmm1,5); + ulsch_llr[4] = _mm_extract_epi16(xmm2,4); + ulsch_llr[5] = _mm_extract_epi16(xmm2,5); +#elif defined(__arm__) + ulsch_llr[2] = vgetq_lane_s16(xmm1,4); + ulsch_llr[3] = vgetq_lane_s16(xmm1,5); + ulsch_llr[4] = vgetq_lane_s16(xmm2,4); + ulsch_llr[5] = vgetq_lane_s16(xmm2,5); +#endif + // --------------------------------------- + + ulsch_llr+=6; + + // --------------------------------------- + // 4th RE + // --------------------------------------- + ulsch_llr[0] = ((short *)&rxF[i])[6]; + ulsch_llr[1] = ((short *)&rxF[i])[7]; +#if defined(__x86_64__) || defined(__i386__) + ulsch_llr[2] = _mm_extract_epi16(xmm1,6); + ulsch_llr[3] = _mm_extract_epi16(xmm1,7); + ulsch_llr[4] = _mm_extract_epi16(xmm2,6); + ulsch_llr[5] = _mm_extract_epi16(xmm2,7); +#elif defined(__arm__) + ulsch_llr[2] = vgetq_lane_s16(xmm1,6); + ulsch_llr[3] = vgetq_lane_s16(xmm1,7); + ulsch_llr[4] = vgetq_lane_s16(xmm2,6); + ulsch_llr[5] = vgetq_lane_s16(xmm2,7); +#endif + // --------------------------------------- + + ulsch_llr+=6; + } + +#if defined(__x86_64__) || defined(__i386__) + _mm_empty(); + _m_empty(); +#endif +} + + +void nr_ulsch_compute_llr(int32_t *rxdataF_comp, + int32_t **ul_ch_mag, + int32_t **ul_ch_magb, + int16_t *ulsch_llr, + uint32_t nb_re, + uint8_t symbol, + uint8_t mod_order) +{ + switch(mod_order){ + case 2: + nr_ulsch_qpsk_llr(rxdataF_comp, + ulsch_llr, + nb_re, + symbol); + break; + case 4: + nr_ulsch_16qam_llr(rxdataF_comp, + ul_ch_mag, + ulsch_llr, + nb_re, + symbol); + break; + case 6: + nr_ulsch_64qam_llr(rxdataF_comp, + ul_ch_mag, + ul_ch_magb, + ulsch_llr, + nb_re, + symbol); + break; + default: + LOG_E(PHY,"nr_ulsch_compute_llr: invalid Qm value, symbol = %d, Qm = %d\n",symbol, mod_order); + break; + } +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/dmrs_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dmrs_nr.c index 1bccda4dc1bb4206d48a26db72987398859dedb7..d976ec5a0484e0d0801efed7cefbe4a26a09d686 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dmrs_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dmrs_nr.c @@ -224,6 +224,52 @@ void lte_gold_new(LTE_DL_FRAME_PARMS *frame_parms, uint32_t lte_gold_table[20][2 #endif } +/******************************************************************* +* +* NAME : get_l0_ul +* +* PARAMETERS : mapping_type : PUSCH mapping type +* dmrs_typeA_position : higher layer parameter +* +* RETURN : demodulation reference signal for PUSCH +* +* DESCRIPTION : see TS 38.211 V15.4.0 Demodulation reference signals for PUSCH +* +*********************************************************************/ + +uint8_t get_l0_ul(uint8_t mapping_type, uint8_t dmrs_typeA_position) { + + return ((mapping_type==typeA)?dmrs_typeA_position:0); + +} + +/******************************************************************* +* +* NAME : get_dmrs_freq_idx_ul +* +* PARAMETERS : n : index of DMRS symbol +* k_prime : k_prime = {0,1} +* delta : given by Tables 6.4.1.1.3-1 and 6.4.1.1.3-2 +* dmrs_type : DMRS configuration type +* +* RETURN : demodulation reference signal for PUSCH +* +* DESCRIPTION : see TS 38.211 V15.4.0 Demodulation reference signals for PUSCH +* +*********************************************************************/ + +uint16_t get_dmrs_freq_idx_ul(uint8_t n, uint8_t k_prime, uint8_t delta, uint8_t dmrs_type) { + + uint16_t dmrs_idx; + + if (dmrs_type == pusch_dmrs_type1) + dmrs_idx = ((n<<2)+(k_prime<<1)+delta); + else + dmrs_idx = (6*n+k_prime+delta); + + return dmrs_idx; +} + /******************************************************************* * * NAME : get_dmrs_pbch diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index d0e383feb36ff6377b487731e656eee5fefc7d00..167d7cfbc5f79803c2d0baa53a3dc5741a0dd0bb 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -964,7 +964,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, break; } if (dlsch1_harq) { - switch (get_Qm(dlsch1_harq->mcs)) { + switch (nr_get_Qm(dlsch1_harq->mcs, 1)) { case 2 : if (rx_type==rx_standard) { nr_dlsch_qpsk_llr(frame_parms, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 6e588acd1d73b014f75aae5b15efb2b44b4c4fb1..b68273718016458587b882d3e9b4b911cca652d1 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -33,7 +33,7 @@ #define __NR_TRANSPORT_PROTO_UE__H__ #include "PHY/defs_nr_UE.h" #include "SCHED_NR_UE/defs.h" -//#include "PHY/LTE_TRANSPORT/transport_common_proto.h" +#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include <math.h> #include "nfapi_interface.h" @@ -1055,12 +1055,24 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS* frame_parms, uint8_t harq_pid); +/*! \brief Fill up NR_UE_ULSCH_t and NR_UL_UE_HARQ_t structs + @param[in] UE, Pointer to PHY_VARS_NR_UE struct + @param[in] thread_id, thread id + @param[in] gNB_id, gNB id + @param[in] harq_pid, harq id +*/ + +int generate_ue_ulsch_params(PHY_VARS_NR_UE *UE, + uint8_t thread_id, + int gNB_id, + unsigned char harq_pid); + /*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 - @param[in] in Pointer to input bits - @param[in] size of input bits - @param[in] Nid cell id - @param[in] n_RNTI CRNTI - @param[out] out the scrambled bits + @param[in] in, Pointer to input bits + @param[in] size, of input bits + @param[in] Nid, cell id + @param[in] n_RNTI, CRNTI + @param[out] out, the scrambled bits */ void nr_pusch_codeword_scrambling(uint8_t *in, @@ -1069,6 +1081,29 @@ void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t n_RNTI, uint32_t* out); +/** \brief Perform the following functionalities: + - encoding + - scrambling + - modulation + - transform precoding +*/ + +uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, + unsigned char harq_pid, + uint8_t slot, + uint8_t thread_id, + int eNB_id); + + +/** \brief This function does IFFT for PUSCH +*/ + +uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, + uint8_t slot, + uint8_t Nl, + NR_DL_FRAME_PARMS *frame_parms); + + uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, @@ -1099,34 +1134,6 @@ uint32_t dlsch_decoding_emul(PHY_VARS_NR_UE *phy_vars_ue, PDSCH_t dlsch_id, uint8_t eNB_id); -/** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs - - RB extraction (signal and channel estimates) - - channel compensation (matched filtering) - - RE extraction (pilot, PBCH, synch. signals) - - antenna combining (MRC, Alamouti, cycling) - - LLR computation - This function supports TM1, 2, 3, 5, and 6. - @param PHY_VARS_NR_UE Pointer to PHY variables - @param type Type of PDSCH (SI_PDSCH,RA_PDSCH,PDSCH,PMCH) - @param eNB_id eNb index (Nid1) 0,1,2 - @param eNB_id_i Interfering eNB index (Nid1) 0,1,2, or 3 in case of MU-MIMO IC receiver - @param subframe Subframe number - @param symbol Symbol on which to act (within sub-frame) - @param first_symbol_flag set to 1 on first DLSCH symbol - @param rx_type. rx_type=RX_IC_single_stream will enable interference cancellation of a second stream when decoding the first stream. In case of TM1, 2, 5, and this can cancel interference from a neighbouring cell given by eNB_id_i. In case of TM5, eNB_id_i should be set to n_connected_eNB to perform multi-user interference cancellation. In case of TM3, eNB_id_i should be set to eNB_id to perform co-channel interference cancellation; this option should be used together with an interference cancellation step [...]. In case of TM3, if rx_type=RX_IC_dual_stream, both streams will be decoded by applying the IC single stream receiver twice. - @param i_mod Modulation order of the interfering stream -*/ -int32_t nr_rx_pdsch(PHY_VARS_NR_UE *phy_vars_ue, - PDSCH_t type, - uint8_t eNB_id, - uint8_t eNB_id_i, - uint32_t frame, - uint8_t subframe, - uint8_t symbol, - uint8_t first_symbol_flag, - RX_type_t rx_type, - uint8_t i_mod, - uint8_t harq_pid); int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, uint32_t frame, @@ -1271,14 +1278,6 @@ uint16_t dci_decoding_procedure_emul(NR_UE_PDCCH **lte_ue_pdcch_vars, DCI_ALLOC_t *dci_alloc_rx, int16_t eNB_id); -/** \brief Compute Q (modulation order) based on I_MCS PDSCH. Implements table 7.1.7.1-1 from 36.213. - @param I_MCS */ -uint8_t get_Qm(uint8_t I_MCS); - -/** \brief Compute Q (modulation order) based on I_MCS for PUSCH. Implements table 8.6.1-1 from 36.213. - @param I_MCS */ -uint8_t get_Qm_ul(uint8_t I_MCS); - /** \brief Compute I_TBS (transport-block size) based on I_MCS for PDSCH. Implements table 7.1.7.1-1 from 36.213. @param I_MCS */ uint8_t get_I_TBS(uint8_t I_MCS); @@ -1327,8 +1326,6 @@ uint8_t get_transmission_mode(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti); */ uint32_t conv_nprb(uint8_t ra_header,uint32_t rb_alloc,int N_RB_DL); -int get_G(NR_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe, uint8_t beamforming_mode); - int adjust_G(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe); int adjust_G2(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol); @@ -1765,6 +1762,24 @@ int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue, uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES], NR_DCI_INFO_EXTRACTED_t *nr_dci_info_extracted); +/** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs + - RB extraction (signal and channel estimates) + - channel compensation (matched filtering) + - RE extraction (pilot, PBCH, synch. signals) + - antenna combining (MRC, Alamouti, cycling) + - LLR computation + This function supports TM1, 2, 3, 5, and 6. + @param ue Pointer to PHY variables + @param type Type of PDSCH (SI_PDSCH,RA_PDSCH,PDSCH,PMCH) + @param eNB_id eNb index (Nid1) 0,1,2 + @param eNB_id_i Interfering eNB index (Nid1) 0,1,2, or 3 in case of MU-MIMO IC receiver + @param frame Frame number + @param nr_tti_rx Subframe number + @param symbol Symbol on which to act (within sub-frame) + @param first_symbol_flag set to 1 on first DLSCH symbol + @param rx_type. rx_type=RX_IC_single_stream will enable interference cancellation of a second stream when decoding the first stream. In case of TM1, 2, 5, and this can cancel interference from a neighbouring cell given by eNB_id_i. In case of TM5, eNB_id_i should be set to n_connected_eNB to perform multi-user interference cancellation. In case of TM3, eNB_id_i should be set to eNB_id to perform co-channel interference cancellation; this option should be used together with an interference cancellation step [...]. In case of TM3, if rx_type=RX_IC_dual_stream, both streams will be decoded by applying the IC single stream receiver twice. + @param i_mod Modulation order of the interfering stream +*/ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, PDSCH_t type, unsigned char eNB_id, @@ -1777,8 +1792,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, unsigned char i_mod, unsigned char harq_pid); -uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16_t length_dmrs, uint8_t Qm, uint8_t Nl) ; - uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, short *dlsch_llr, NR_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index fc303716e9a68933cb42694f11f683b999551a80..e479c7cc34a083e618ff389d81e5371efa0e06e8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -138,10 +138,6 @@ typedef struct { uint32_t sumKr; /// Number of "Filler" bits uint32_t F; - /// Msc_initial, Initial number of subcarriers for ULSCH - uint16_t Msc_initial; - /// Nsymb_initial, Initial number of symbols for ULSCH - uint8_t Nsymb_initial; /// n_DMRS for cyclic shift of DMRS uint8_t n_DMRS; /// n_DMRS2 for cyclic shift of DMRS @@ -152,11 +148,12 @@ typedef struct { // int calibration_flag; /// Number of soft channel bits uint32_t G; - // number of symbols - uint8_t nb_symbols; - // first symbol in the slot + // Number of modulated symbols carrying data + uint32_t num_of_mod_symbols; + // This is "L" in TS 38.214 V15.4.0 subclause 6.1.2.1 + uint8_t number_of_symbols; + // This is "S" in TS 38.214 V15.4.0 subclause 6.1.2.1 uint8_t start_symbol; - // decode phich uint8_t decode_phich; } NR_UL_UE_HARQ_t; @@ -164,8 +161,12 @@ typedef struct { typedef struct { /// Current Number of Symbols uint8_t Nsymb_pusch; + /// Nsc_pusch, number of allocated subcarriers for ULSCH + uint16_t Nsc_pusch; /// number of DMRS resource elements uint8_t nb_re_dmrs; + /// DMRS length + uint8_t length_dmrs; /// SRS active flag uint8_t srs_active; //#if defined(UPGRADE_RAT_NR) @@ -201,9 +202,9 @@ typedef struct { /// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14) uint8_t b_tilde[MAX_NUM_NR_CHANNEL_BITS]; /// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14) - int32_t d[MAX_NUM_NR_RE]; - /// Transform-coded "z"-sequences (for definition see 36-211 V8.6 2009-03, p.14-15) - int32_t z[MAX_NUM_NR_RE]; + uint32_t d_mod[MAX_NUM_NR_RE]; + /// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4) + uint32_t y[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); /* /// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27) uint8_t q[MAX_CQI_PAYLOAD]; @@ -231,6 +232,8 @@ typedef struct { uint16_t rnti; /// RNTI type uint8_t rnti_type; + /// Cell ID + int Nid_cell; /// f_PUSCH parameter for PUSCH power control int16_t f_pusch; /// Po_PUSCH - target output power for PUSCH diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 95ca86959f92eeaef39620731114150aeb25d10b..5c8493c3709197a43207a5c83c410801985e8bbb 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -39,7 +39,6 @@ #include "PHY/CODING/nrLDPC_encoder/defs.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include "PHY/NR_TRANSPORT/nr_dlsch.h" @@ -205,7 +204,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, uint32_t *pz; uint8_t mod_order; uint16_t Kr,r,r_offset; - //uint8_t *d_tmp[MAX_NUM_DLSCH_SEGMENTS]; uint8_t BG; uint32_t E; uint8_t Ilbrm; @@ -224,7 +222,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, crc = 1; harq_process = ulsch->harq_processes[harq_pid]; nb_rb = harq_process->nb_rb; - nb_symb_sch = harq_process->nb_symbols; + nb_symb_sch = harq_process->number_of_symbols; A = harq_process->TBS; pz = &Z; mod_order = nr_get_Qm(harq_process->mcs,1); @@ -250,12 +248,12 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - printf("ulsch coding nb_rb %d nb_symb_sch %d nb_re_dmrs %d, length_dmrs %d\n", nb_rb,nb_symb_sch, nb_re_dmrs,length_dmrs); + LOG_D(PHY,"ulsch coding nb_rb %d nb_symb_sch %d nb_re_dmrs %d, length_dmrs %d\n", nb_rb,nb_symb_sch, nb_re_dmrs,length_dmrs); G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,harq_process->Nl); LOG_D(PHY,"ulsch coding A %d G %d mod_order %d\n", A,G, mod_order); - printf("ulsch coding A %d G %d mod_order %d\n", A,G, mod_order); + Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); @@ -327,7 +325,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, //start_meas(te_stats); for (r=0; r<harq_process->C; r++) { - //d_tmp[r] = &harq_process->d[r][0]; //channel_input[r] = &harq_process->d[r][0]; #ifdef DEBUG_DLSCH_CODING printf("Encoder: B %d F %d \n",harq_process->B, harq_process->F); @@ -354,7 +351,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, } printf("\n");*/ - //ldpc_encoder_optim_8seg(harq_process->c,d_tmp,Kr,BG,harq_process->C,NULL,NULL,NULL,NULL); ldpc_encoder_optim_8seg(harq_process->c,harq_process->d,Kr,BG,harq_process->C,NULL,NULL,NULL,NULL); //stop_meas(te_stats); @@ -446,7 +442,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, } - memcpy(ulsch->g,harq_process->f,G>>3); // g is the concatenated code block + memcpy(ulsch->g,harq_process->f,G); // g is the concatenated code block VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c new file mode 100644 index 0000000000000000000000000000000000000000..25b395bdf7a663bd42f319a756611a7f3bdc7eda --- /dev/null +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -0,0 +1,412 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_UE_TRANSPORT/nr_ulsch.c +* \brief Top-level routines for transmission of the PUSCH TS 38.211 v 15.4.0 +* \author Khalid Ahmed +* \date 2019 +* \version 0.1 +* \company Fraunhofer IIS +* \email: khalid.ahmed@iis.fraunhofer.de +* \note +* \warning +*/ +#include <stdint.h> +#include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" +#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" +#include "PHY/MODULATION/nr_modulation.h" +#include "PHY/MODULATION/modulation_common.h" +#include "common/utils/assertions.h" +#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" +#include "PHY/defs_nr_common.h" +#include "PHY/TOOLS/tools_defs.h" + +//#define DEBUG_SCFDMA + + +int generate_ue_ulsch_params(PHY_VARS_NR_UE *UE, + uint8_t thread_id, + int gNB_id, + unsigned char harq_pid){ + + int N_PRB_oh, N_RE_prime, cwd_idx, length_dmrs, Nid_cell; + int nb_rb, Nsymb_pusch, first_rb, nb_codewords; + uint16_t n_rnti; + + fapi_nr_dci_pdu_rel15_t *ul_dci_pdu; + NR_UE_ULSCH_t *ulsch_ue; + NR_UL_UE_HARQ_t *harq_process_ul_ue; + + ul_dci_pdu = &UE->dci_ind.dci_list[0].dci; + + //--------------------------Temporary configuration-----------------------------// + length_dmrs = 1; + n_rnti = 0x1234; + Nid_cell = 0; + nb_rb = 50; + first_rb = 30; + Nsymb_pusch = 12; + nb_codewords = (ul_dci_pdu->precod_nbr_layers>4)?2:1; + //------------------------------------------------------------------------------// + + for (cwd_idx = 0; cwd_idx < nb_codewords; cwd_idx++) { + + ulsch_ue = UE->ulsch[thread_id][gNB_id][cwd_idx]; + harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; + + ulsch_ue->length_dmrs = length_dmrs; + ulsch_ue->rnti = n_rnti; + ulsch_ue->Nid_cell = Nid_cell; + ulsch_ue->Nsc_pusch = nb_rb*NR_NB_SC_PER_RB; + ulsch_ue->Nsymb_pusch = Nsymb_pusch; + ulsch_ue->nb_re_dmrs = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4; + + + N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig + N_RE_prime = NR_NB_SC_PER_RB*Nsymb_pusch - ulsch_ue->nb_re_dmrs - N_PRB_oh; + + if (harq_process_ul_ue) { + + harq_process_ul_ue->mcs = ul_dci_pdu->mcs; + harq_process_ul_ue->Nl = ul_dci_pdu->precod_nbr_layers; + harq_process_ul_ue->nb_rb = nb_rb; + harq_process_ul_ue->first_rb = first_rb; + harq_process_ul_ue->number_of_symbols = Nsymb_pusch; + harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb*nb_codewords; + harq_process_ul_ue->rvidx = ul_dci_pdu->rv; + harq_process_ul_ue->TBS = nr_compute_tbs(ul_dci_pdu->mcs, + nb_rb, + Nsymb_pusch, + ulsch_ue->nb_re_dmrs, + length_dmrs, + ul_dci_pdu->precod_nbr_layers); + + } + + } + + return 0; +} + + + +void nr_pusch_codeword_scrambling(uint8_t *in, + uint16_t size, + uint32_t Nid, + uint32_t n_RNTI, + uint32_t* out) { + + uint8_t reset, b_idx; + uint32_t x1, x2, s=0, temp_out; + + reset = 1; + x2 = (n_RNTI<<15) + Nid; + + for (int i=0; i<size; i++) { + b_idx = i&0x1f; + if (b_idx==0) { + s = lte_gold_generic(&x1, &x2, reset); + reset = 0; + if (i) + out++; + } + if (in[i]==NR_PUSCH_x) + *out ^= 1<<b_idx; + else if (in[i]==NR_PUSCH_y){ + if (b_idx!=0) + *out ^= (*out & (1<<(b_idx-1)))<<1; + else{ + + temp_out = *(out-1); + *out ^= temp_out>>31; + + } + } + else + *out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx; + //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out); + } + +} + +uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, + unsigned char harq_pid, + uint8_t slot, + uint8_t thread_id, + int eNB_id) { + + unsigned int available_bits; + uint8_t mod_order, cwd_index, num_of_codewords; + uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; + int32_t *mod_symbols[MAX_NUM_NR_RE]; + uint32_t ***pusch_dmrs; + int16_t **tx_layers; + int32_t **txdataF; + uint16_t start_sc, start_rb; + int8_t Wf[2], Wt[2], l0, l_prime[2], delta; + uint16_t n_dmrs; + uint8_t dmrs_type; + uint8_t mapping_type; + int ap, start_symbol, i; + int sample_offsetF; + + NR_UE_ULSCH_t *ulsch_ue; + NR_UL_UE_HARQ_t *harq_process_ul_ue; + NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; + NR_UE_PUSCH *pusch_ue = UE->pusch_vars[thread_id][eNB_id]; + + num_of_codewords = 1; // tmp assumption + + for (cwd_index = 0;cwd_index < num_of_codewords; cwd_index++) { + + ulsch_ue = UE->ulsch[thread_id][eNB_id][cwd_index]; + harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; + + /////////////////////////ULSCH coding///////////////////////// + /////////// + + nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid); + + /////////// + //////////////////////////////////////////////////////////////////// + + /////////////////////////ULSCH scrambling///////////////////////// + /////////// + + mod_order = nr_get_Qm(harq_process_ul_ue->mcs, 1); + + available_bits = nr_get_G(harq_process_ul_ue->nb_rb, + ulsch_ue->Nsymb_pusch, + ulsch_ue->nb_re_dmrs, + ulsch_ue->length_dmrs, + mod_order, + 1); + + memset(scrambled_output[cwd_index], 0, ((available_bits>>5)+1)*sizeof(uint32_t)); + + nr_pusch_codeword_scrambling(ulsch_ue->g, + available_bits, + ulsch_ue->Nid_cell, + ulsch_ue->rnti, + scrambled_output[cwd_index]); // assume one codeword for the moment + + + ///////////// + ////////////////////////////////////////////////////////////////////////// + + /////////////////////////ULSCH modulation///////////////////////// + /////////// + + nr_modulation(scrambled_output[cwd_index], // assume one codeword for the moment + available_bits, + mod_order, + (int16_t *)ulsch_ue->d_mod); + + // pusch_transform_precoding(ulsch_ue, frame_parms, harq_pid); + + /////////// + //////////////////////////////////////////////////////////////////////// + + mod_symbols[cwd_index] = (int32_t *)malloc16((NR_MAX_PUSCH_ENCODED_LENGTH)*sizeof(int32_t*)); + + memcpy(mod_symbols[cwd_index],ulsch_ue->d_mod,(available_bits/mod_order)*sizeof(int32_t)); + + } + + start_symbol = 14 - ulsch_ue->Nsymb_pusch; + + /////////////////////////DMRS Modulation///////////////////////// + /////////// + + pusch_dmrs = UE->nr_gold_pusch_dmrs[slot]; + n_dmrs = (harq_process_ul_ue->nb_rb*ulsch_ue->nb_re_dmrs); + int16_t mod_dmrs[n_dmrs<<1]; + dmrs_type = UE->dmrs_UplinkConfig.pusch_dmrs_type; + mapping_type = UE->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; + + l0 = get_l0_ul(mapping_type, 2); + nr_modulation(pusch_dmrs[l0][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + + + /////////// + //////////////////////////////////////////////////////////////////////// + + /////////////////////////ULSCH layer mapping///////////////////////// + /////////// + + tx_layers = (int16_t **)pusch_ue->txdataF_layers; + + nr_layer_mapping((int16_t **)mod_symbols, + harq_process_ul_ue->Nl, + available_bits/mod_order, + tx_layers); + + for (uint32_t i = 0; i < 2*available_bits/mod_order; i++) + tx_layers[0][i] = (tx_layers[0][i] * AMP) >> 15; + + /////////// + //////////////////////////////////////////////////////////////////////// + + + //////////////////////// ULSCH transform precoding //////////////////////// + /////////// + + l_prime[0] = 0; // single symbol ap 0 + uint8_t dmrs_symbol = l0+l_prime[0], l; // Assuming dmrs-AdditionalPosition = 0 + +#ifdef NR_SC_FDMA + uint32_t nb_re_pusch, nb_re_dmrs_per_rb; + uint32_t y_offset = 0; + + for (l = start_symbol; l < start_symbol + ulsch_ue->Nsymb_pusch; l++) { + + if(l == dmrs_symbol) + nb_re_dmrs_per_rb = ulsch_ue->nb_re_dmrs; // [hna] ulsch_ue->nb_re_dmrs = 6 in this configuration + else + nb_re_dmrs_per_rb = 0; + + nb_re_pusch = harq_process_ul_ue->nb_rb * (NR_NB_SC_PER_RB - nb_re_dmrs_per_rb); + + nr_dft(&ulsch_ue->y[y_offset], &((int32_t*)tx_layers[0])[y_offset], nb_re_pusch); + + y_offset = y_offset + nb_re_pusch; + } +#else + memcpy(ulsch_ue->y, tx_layers[0], (available_bits/mod_order)*sizeof(int32_t)); +#endif + + /////////// + //////////////////////////////////////////////////////////////////////// + + + + /////////////////////////ULSCH RE mapping///////////////////////// + /////////// + + txdataF = UE->common_vars.txdataF; + + start_rb = harq_process_ul_ue->first_rb; + start_sc = frame_parms->first_carrier_offset + start_rb*NR_NB_SC_PER_RB; + + if (start_sc >= frame_parms->ofdm_symbol_size) + start_sc -= frame_parms->ofdm_symbol_size; + + for (ap=0; ap<harq_process_ul_ue->Nl; ap++) { + + // DMRS params for this ap + get_Wt(Wt, ap, dmrs_type); + get_Wf(Wf, ap, dmrs_type); + delta = get_delta(ap, dmrs_type); + + + uint8_t k_prime=0; + uint16_t m=0, n=0, dmrs_idx=0, k=0; + + for (l=start_symbol; l<start_symbol+ulsch_ue->Nsymb_pusch; l++) { + + k = start_sc; + + for (i=0; i<harq_process_ul_ue->nb_rb*NR_NB_SC_PER_RB; i++) { + + sample_offsetF = l*frame_parms->ofdm_symbol_size + k; + + if ((l == dmrs_symbol) && (k == ((start_sc+get_dmrs_freq_idx_ul(n, k_prime, delta, dmrs_type))%(frame_parms->ofdm_symbol_size)))) { + + ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[dmrs_idx<<1]) >> 15; + ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*AMP*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + + #ifdef DEBUG_PUSCH_MAPPING + printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n", + dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1], + ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1]); + #endif + + dmrs_idx++; + k_prime++; + k_prime&=1; + n+=(k_prime)?0:1; + } + + else { + + ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = ((int16_t *) ulsch_ue->y)[m<<1]; + ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = ((int16_t *) ulsch_ue->y)[(m<<1) + 1]; + + #ifdef DEBUG_PUSCH_MAPPING + printf("m %d\t l %d \t k %d \t txdataF: %d %d\n", + m, l, k, ((int16_t*)txdataF[ap])[(sample_offsetF)<<1], + ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1]); + #endif + + m++; + } + + if (++k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; + } + } + } + + /////////// + //////////////////////////////////////////////////////////////////////// + + return 0; +} + + +uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, + uint8_t slot, + uint8_t Nl, + NR_DL_FRAME_PARMS *frame_parms) { + + int tx_offset, ap; + int32_t **txdata; + int32_t **txdataF; + + /////////////////////////IFFT/////////////////////// + /////////// + + tx_offset = slot*frame_parms->samples_per_slot; + txdata = UE->common_vars.txdata; + txdataF = UE->common_vars.txdataF; + + for (ap = 0; ap < Nl; ap++) { + if (frame_parms->Ncp == 1) { // extended cyclic prefix + PHY_ofdm_mod(txdataF[ap], + &txdata[ap][tx_offset], + frame_parms->ofdm_symbol_size, + 12, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } else { // normal cyclic prefix + nr_normal_prefix_mod(txdataF[ap], + &txdata[ap][tx_offset], + 14, + frame_parms); + } + } + + /////////// + //////////////////////////////////////////////////// + return 0; +} diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c index 13f37c4c8dbe9de6362a63abe6bd0f174321c9ef..83bcb7b76452dde39ee9bcb6ace8ceeef6685bbf 100644 --- a/openair1/PHY/TOOLS/signal_energy.c +++ b/openair1/PHY/TOOLS/signal_energy.c @@ -20,7 +20,7 @@ */ #include "tools_defs.h" - +#include "PHY/impl_defs_top.h" #include "PHY/sse_intrin.h" // Compute Energy of a complex signal vector, removing the DC component! @@ -97,6 +97,7 @@ int32_t signal_energy(int32_t *input,uint32_t length) temp/=length; temp<<=shift; // this is the average of x^2 + // now remove the DC component @@ -114,6 +115,52 @@ int32_t signal_energy(int32_t *input,uint32_t length) return((temp>0)?temp:1); } +int32_t signal_energy_amp_shift(int32_t *input,uint32_t length) +{ + + int32_t i; + int32_t temp,temp2; + register __m64 mm0,mm1,mm2,mm3; + __m64 *in = (__m64 *)input; + + mm0 = _mm_setzero_si64(); + mm3 = _mm_setzero_si64(); + + for (i=0; i<length>>1; i++) { + + mm1 = in[i]; + mm2 = mm1; + mm1 = _m_pmaddwd(mm1,mm1); + mm1 = _m_psradi(mm1,AMP_SHIFT);// shift any 32 bits blocs of the word by the value shift_p9 + mm0 = _m_paddd(mm0,mm1);// add the two 64 bits words 4 bytes by 4 bytes + mm3 = _m_paddw(mm3,mm2);// add the two 64 bits words 2 bytes by 2 bytes + } + + mm1 = mm0; + mm0 = _m_psrlqi(mm0,32); + mm0 = _m_paddd(mm0,mm1); + temp = _m_to_int(mm0); + temp/=length; // this is the average of x^2 + + + // now remove the DC component + + + mm2 = _m_psrlqi(mm3,32); + mm2 = _m_paddw(mm2,mm3); + mm2 = _m_pmaddwd(mm2,mm2); + mm2 = _m_psradi(mm2,AMP_SHIFT); // fixed point representation of elements + temp2 = _m_to_int(mm2); + temp2/=(length*length); + + temp -= temp2; + + _mm_empty(); + _m_empty(); + + return((temp>0)?temp:1); +} + int32_t signal_energy_nodc(int32_t *input,uint32_t length) { diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 8ba2ac0d4088da02730872a132826f01613dc5da..3c1a395d0dc096c38c07bcf92df1c68bfb86c3dd 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -295,6 +295,13 @@ void mmxcopy(void *dest,void *src,int size); */ int32_t signal_energy(int32_t *,uint32_t); +/*!\fn int32_t signal_energy_fixed_p9(int *input, uint32_t length); +\brief Computes the signal energy per subcarrier +\ the input signal has a fixed point representation of AMP_SHIFT bits +\ the ouput energy has a fixed point representation of AMP_SHIFT bits +*/ +int32_t signal_energy_amp_shift(int32_t *input, uint32_t length); + #ifdef LOCALIZATION /*!\fn int32_t signal_energy(int *,uint32_t); \brief Computes the signal energy per subcarrier diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 8c6c11df9c42758fa6e275508a5ede10e9d89824..5d618b60c78cb1eb97be5ef8ac9c02df292a680c 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -234,8 +234,6 @@ typedef struct { int16_t e[MAX_NUM_NR_DLSCH_SEGMENTS][3*8448]; /// Number of bits in each code block after rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) uint32_t E; - /// Number of soft channel bits after code block concatenation (38.212 V15.4.0 section 5.5) - uint32_t G; ////////////////////////////////////////////////////////////// @@ -354,6 +352,45 @@ typedef struct { } NR_gNB_COMMON; +typedef struct { + /// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format. + /// - first index: rx antenna id [0..nb_antennas_rx[ + /// - second index: ? [0..2*ofdm_symbol_size[ + int32_t **rxdataF_ext; + /// \brief Holds the received data in the frequency domain for the allocated RBs in normal format. + /// - first index: rx antenna id [0..nb_antennas_rx[ + /// - second index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ + int32_t **rxdataF_ext2; + /// \brief Offset for calculating the index of rxdataF_ext for the current symbol + uint32_t rxdataF_ext_offset; + /// \brief Hold the channel estimates in time domain based on DRS. + /// - first index: rx antenna id [0..nb_antennas_rx[ + /// - second index: ? [0..4*ofdm_symbol_size[ + int32_t **drs_ch_estimates_time; + /// \brief Hold the channel estimates in frequency domain based on DRS. + /// - first index: rx antenna id [0..nb_antennas_rx[ + /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ + int32_t **drs_ch_estimates; + /// \brief Holds the compensated signal. + /// - first index: rx antenna id [0..nb_antennas_rx[ + /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ + int32_t **rxdataF_comp; + /// \brief Magnitude of the UL channel estimates. Used for 2nd-bit level thresholds in LLR computation + /// - first index: rx antenna id [0..nb_antennas_rx[ + /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ + int32_t **ul_ch_mag; + /// \brief Magnitude of the UL channel estimates scaled for 3rd bit level thresholds in LLR computation + /// - first index: rx antenna id [0..nb_antennas_rx[ + /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ + int32_t **ul_ch_magb; + /// measured RX power based on DRS + int ulsch_power[2]; + /// \brief llr values. + /// - first index: ? [0..1179743] (hard coded) + int16_t *llr; +} NR_gNB_PUSCH; + + /// Context data structure for RX/TX portion of slot processing typedef struct { /// Component Carrier index @@ -569,13 +606,13 @@ typedef struct PHY_VARS_gNB_s { Sched_Rsp_t Sched_INFO; NR_gNB_PDCCH pdcch_vars; NR_gNB_PBCH pbch; - LTE_eNB_PHICH phich_vars[2]; + // LTE_eNB_PHICH phich_vars[2]; NR_gNB_COMMON common_vars; /* LTE_eNB_UCI uci_vars[NUMBER_OF_UE_MAX]; LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; - LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX]; LTE_eNB_PRACH prach_vars;*/ + NR_gNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX]; NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2]; // Nusers times two spatial streams NR_gNB_ULSCH_t *ulsch[NUMBER_OF_NR_ULSCH_MAX+1][2]; // [Nusers times + number of RA][2 codewords], index 0 in [NUMBER_OF_UE_MAX+1] is for RA // LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index a0ad37bfe5036167585a4e7fcff732407da23faf..dceeaa79ceb4c80a27ee3cfc01a321c1d2bc7297 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -277,6 +277,11 @@ typedef struct { } NR_UE_COMMON_PER_THREAD; +typedef struct { + /// TX buffers for multiple layers + int32_t *txdataF_layers[NR_MAX_NB_LAYERS]; + } NR_UE_PUSCH; + typedef struct { /// \brief Holds the transmit data in time domain. /// For IFFT_FPGA this points to the same memory as PHY_vars->tx_vars[a].TX_DMA_BUFFER. @@ -943,6 +948,7 @@ typedef struct { NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; NR_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX]; NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX]; + NR_UE_PUSCH *pusch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX]; NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads NR_UE_ULSCH_t *ulsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two code words NR_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX]; @@ -983,6 +989,9 @@ typedef struct { /// PDCCH DMRS uint32_t nr_gold_pdcch[7][20][3][52]; + /// PUSCH DMRS sequence + uint32_t ****nr_gold_pusch_dmrs; + uint32_t X_u[64][839]; uint32_t high_speed_flag; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 591d6094547c44011dc8b92e2b1342d6ea7501be..3c3cb6ff417953f15be48b9e01edadde6f0dd9bc 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -42,6 +42,11 @@ #define nr_subframe_t lte_subframe_t #define nr_slot_t lte_subframe_t +// [hna] This enables SC-FDMA transmission in Uplink. If disabled, then OFDMA is used in UPLINK. +#ifndef NR_SC_FDMA +// #define NR_SC_FDMA +#endif + #define MAX_NUM_SUBCARRIER_SPACING 5 #define NR_MAX_NB_RB 275 @@ -74,9 +79,12 @@ /*used for the resource mapping*/ #define NR_MAX_PDCCH_DMRS_LENGTH 576 // 16(L)*2(QPSK)*3(3 DMRS symbs per REG)*6(REG per CCE) -#define NR_MAX_PDSCH_DMRS_LENGTH 3300 //275*6(k)*2(QPSK) +#define NR_MAX_PDSCH_DMRS_LENGTH 3300 //275*6(k)*2(QPSK real+imag) #define NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD 104 // ceil(NR_MAX_PDSCH_DMRS_LENGTH/32) +#define NR_MAX_PUSCH_DMRS_LENGTH NR_MAX_PDSCH_DMRS_LENGTH +#define NR_MAX_PUSCH_DMRS_INIT_LENGTH_DWORD NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD + #define NR_MAX_DCI_PAYLOAD_SIZE 64 #define NR_MAX_DCI_SIZE 1728 //16(L)*2(QPSK)*9(12 RE per REG - 3(DMRS))*6(REG per CCE) #define NR_MAX_DCI_SIZE_DWORD 54 // ceil(NR_MAX_DCI_SIZE/32) @@ -91,6 +99,7 @@ #define NR_MAX_NB_CODEWORDS 2 #define NR_MAX_NB_HARQ_PROCESSES 16 #define NR_MAX_PDSCH_ENCODED_LENGTH NR_MAX_NB_RB*NR_SYMBOLS_PER_SLOT*NR_NB_SC_PER_RB*8*NR_MAX_NB_LAYERS // 8 is the maximum modulation order (it was 950984 before !!) +#define NR_MAX_PUSCH_ENCODED_LENGTH NR_MAX_PDSCH_ENCODED_LENGTH #define NR_MAX_PDSCH_TBS 3824 typedef enum { diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index f8b871c5450d83e52fc71859f1bfcda9730af445..90645e2c11a0c5ed83d114129a8cf5f0b1879175 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -243,11 +243,13 @@ //#define CHBCH_RSSI_MIN -75 #ifdef BIT8_TX -#define AMP 128 +#define AMP_SHIFT 7 #else -#define AMP 512//1024 //4096 +#define AMP_SHIFT 9 #endif +#define AMP ((1)<<AMP_SHIFT) + #define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15) #define AMP_OVER_2 (AMP>>1) diff --git a/openair1/PHY/thread_NR_UE.h b/openair1/PHY/thread_NR_UE.h index c5db3e14d76089bc0391c38c3457670010fb83bf..b18ff3d5b7df24ab78c902f04ecfd50f65f727b1 100644 --- a/openair1/PHY/thread_NR_UE.h +++ b/openair1/PHY/thread_NR_UE.h @@ -15,6 +15,10 @@ typedef struct { int nr_tti_tx; /// NR TTI index within subframe_rx [0 .. ttis_per_subframe - 1] to act upon for reception int nr_tti_rx; + /// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission + int nr_slot_tx; + /// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission + int nr_slot_rx; //#endif /// subframe to act upon for transmission int subframe_tx; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 53c6f3acc0cf8310c2a6f52aa1dc9abac174f610..fdd8baea92a5e81d0f51094388221166e40265e5 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -23,7 +23,9 @@ #include "PHY/defs_gNB.h" #include "sched_nr.h" #include "PHY/NR_TRANSPORT/nr_transport.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "SCHED/sched_eNB.h" #include "SCHED/sched_common_extern.h" #include "nfapi_interface.h" @@ -31,7 +33,7 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "PHY/INIT/phy_init.h" - +#include "PHY/MODULATION/nr_modulation.h" #include "T.h" #include "assertions.h" @@ -166,10 +168,12 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, memset(gNB->common_vars.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t)); } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,1); if (nfapi_mode == 0 || nfapi_mode == 1) { if (!(frame%ssb_frame_periodicity)) // generate SSB only for given frames according to SSB periodicity nr_common_signal_procedures(gNB,frame, slot); } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,0); num_dci = gNB->pdcch_vars.num_dci; num_pdsch_rnti = gNB->pdcch_vars.num_pdsch_rnti; @@ -188,11 +192,11 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, if (num_pdsch_rnti) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); LOG_D(PHY, "PDSCH generation started (%d)\n", num_pdsch_rnti); - nr_generate_pdsch(*gNB->dlsch[0][0], - gNB->pdcch_vars.dci_alloc[0], + nr_generate_pdsch(gNB->dlsch[0][0], + &gNB->pdcch_vars.dci_alloc[0], gNB->nr_gold_pdsch_dmrs[slot], gNB->common_vars.txdataF, - AMP, frame,slot, *fp, *cfg); + AMP, frame, slot, fp, cfg); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); } } @@ -200,3 +204,78 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0); } + + +void nr_ulsch_procedures(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int UE_id, uint8_t harq_pid) { + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->ulsch_pdu; + nfapi_nr_ul_config_ulsch_pdu_rel15_t *nfapi_ulsch_pdu_rel15 = &rel15_ul->ulsch_pdu_rel15; + + uint8_t ret; + uint32_t G; + int Nid_cell = 0; // [hna] shouldn't be a local variable (should be signaled) + + G = nr_get_G(nfapi_ulsch_pdu_rel15->number_rbs, nfapi_ulsch_pdu_rel15->number_symbols, nfapi_ulsch_pdu_rel15->nb_re_dmrs, nfapi_ulsch_pdu_rel15->length_dmrs, nfapi_ulsch_pdu_rel15->Qm, nfapi_ulsch_pdu_rel15->n_layers); + + //---------------------------------------------------------- + //------------------- ULSCH unscrambling ------------------- + //---------------------------------------------------------- + + nr_ulsch_unscrambling(gNB->pusch_vars[UE_id]->llr, G, 0, Nid_cell, rel15_ul->rnti); + + + //---------------------------------------------------------- + //--------------------- ULSCH decoding --------------------- + //---------------------------------------------------------- + + ret = nr_ulsch_decoding(gNB, UE_id, gNB->pusch_vars[UE_id]->llr, frame_parms, proc->frame_rx, + nfapi_ulsch_pdu_rel15->number_symbols, proc->slot_rx, harq_pid, 0); + + // if (ret > ulsch_gNB->max_ldpc_iterations) + // n_errors++; + +} + + +void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc) { + + uint8_t symbol; + unsigned char aa; + + for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) { + // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0); + for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { + nr_slot_fep_ul(&gNB->frame_parms, + gNB->common_vars.rxdata[aa], + gNB->common_vars.rxdataF[aa], + symbol, + proc->slot_rx, + 0, + 0); + } + } + +} + + +void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, uint8_t symbol_start, uint8_t symbol_end) { + + uint8_t UE_id; + uint8_t symbol; + uint8_t harq_pid = 0; // [hna] Previously in LTE, the harq_pid was obtained from the subframe number (Synchronous HARQ) + // In NR, this should be signaled through uplink scheduling dci (i.e, DCI 0_0, 0_1) (Asynchronous HARQ) + + for (UE_id = 0; UE_id < NUMBER_OF_NR_UE_MAX; UE_id++) { + + for(symbol = symbol_start; symbol < symbol_end; symbol++) { + + nr_rx_pusch(gNB, UE_id, proc->frame_rx, proc->slot_rx, symbol, harq_pid); + + } + + nr_ulsch_procedures(gNB, proc, UE_id, harq_pid); + + } + +} diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index e145fc585546adfde6fa915fd726d915843183ed..b6b4b6ca1c36126a6ab1bee35e67d800798a1d58 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -36,7 +36,9 @@ nr_slot_t nr_slot_select (nfapi_nr_config_request_t *cfg, unsigned char slot); void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_t *cfg, NR_DL_FRAME_PARMS *fp); -void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx,int slot_tx, int do_meas); +void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx, int slot_tx, int do_meas); +void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc); +void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, uint8_t symbol_start, uint8_t symbol_end); void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot); void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx); diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index ad065437188663467bc27f97be96e58584a8418a..28bb2c506457cbea281d7a66dc66ec02f36da3fd 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -112,7 +112,7 @@ int phy_procedures_RN_UE_RX(unsigned char last_slot, unsigned char next_slot, re @param mode calib/normal mode @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying */ -void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type); +void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id, uint8_t thread_id); /*! \brief Scheduling for UE RX procedures in normal subframes. @param last_slot Index of last slot (0-19) @param phy_vars_ue Pointer to UE variables on which to act diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 0432ded427be5699c8f21ac3ed7434b342f9eeed..6ee8fbfaa6f8442003ecb81e55f053fdd14b74ea 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -142,7 +142,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ uint8_t current_harq_pid = pusch_config_pdu->harq_process_nbr; ulsch0->harq_processes[current_harq_pid]->nb_rb = pusch_config_pdu->number_rbs; ulsch0->harq_processes[current_harq_pid]->first_rb = pusch_config_pdu->start_rb; - ulsch0->harq_processes[current_harq_pid]->nb_symbols = pusch_config_pdu->number_symbols; + ulsch0->harq_processes[current_harq_pid]->number_of_symbols = pusch_config_pdu->number_symbols; ulsch0->harq_processes[current_harq_pid]->start_symbol = pusch_config_pdu->start_symbol; ulsch0->harq_processes[current_harq_pid]->mcs = pusch_config_pdu->mcs; ulsch0->harq_processes[current_harq_pid]->DCINdi = pusch_config_pdu->ndi; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b86b9381738820c65ae9d2cbe8555fdd69a762de..6b3bbb56c7ac9a88b6daa41ed55090b77d56ec80 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2460,131 +2460,78 @@ void ue_pucch_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_ } +#endif + -void phy_procedures_UE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode,relaying_type_t r_type) { +void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id, uint8_t thread_id) { NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; + fapi_nr_dci_pdu_rel15_t *ul_dci_pdu; + NR_UE_ULSCH_t *ulsch_ue; + NR_UL_UE_HARQ_t *harq_process_ul_ue; //int32_t ulsch_start=0; - int nr_tti_tx = proc->nr_tti_tx; + int slot_tx = proc->nr_tti_tx; int frame_tx = proc->frame_tx; - unsigned int aa; - uint8_t isSubframeSRS; - - /* - uint8_t next1_thread_id = ue->current_thread_id[proc->nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[proc->nr_tti_rx]+1); - uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); - */ + int harq_pid, i, TBS; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); - LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, nr_tti_tx); -#if T_TRACER - T(T_UE_PHY_UL_TICK, T_INT(ue->Mod_id), T_INT(frame_tx%1024), T_INT(nr_tti_tx)); -#endif + LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); - ue->generate_ul_signal[eNB_id] = 0; #if UE_TIMING_TRACE start_meas(&ue->phy_proc_tx); #endif -#ifdef EMOS - //phy_procedures_emos_UE_TX(next_slot); -#endif + ul_dci_pdu = &ue->dci_ind.dci_list[0].dci; - ue->tx_power_dBm[nr_tti_tx]=-127; + harq_pid = 0; //temporary implementation - if (abstraction_flag==0) { - for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { - memset(&ue->common_vars.txdataF[aa][nr_tti_tx*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti], - 0, - frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti*sizeof(int32_t)); - } - } - if (ue->UE_mode[eNB_id] != PRACH) { - // check cell srs nr_tti_rx and ue srs nr_tti_rx. This has an impact on pusch encoding - isSubframeSRS = nr_is_srs_occasion_common(&ue->frame_parms,proc->frame_tx,proc->nr_tti_tx); + generate_ue_ulsch_params(ue, + 0, + gNB_id, + harq_pid); - ue_compute_srs_occasion(ue,proc,eNB_id,isSubframeSRS); + ulsch_ue = ue->ulsch[thread_id][gNB_id][0]; // cwd_index = 0 + harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; - ue_ulsch_uespec_procedures(ue,proc,eNB_id,abstraction_flag); - } + TBS = nr_compute_tbs(ul_dci_pdu->mcs, harq_process_ul_ue->nb_rb, ulsch_ue->Nsymb_pusch, ulsch_ue->nb_re_dmrs, ulsch_ue->length_dmrs, ul_dci_pdu->precod_nbr_layers); + +//-----------------------------------------------------// + // to be removed later when MAC is ready + for (i = 0; i < TBS / 8; i++) + harq_process_ul_ue->a[i] = (unsigned char) rand(); + +//-----------------------------------------------------// + + nr_ue_ulsch_procedures(ue, + harq_pid, + slot_tx, + 0, + gNB_id); + + +/* if (ue->UE_mode[eNB_id] == PUSCH) { // check if we need to use PUCCH 1a/1b ue_pucch_procedures(ue,proc,eNB_id,abstraction_flag); // check if we need to use SRS ue_srs_procedures(ue,proc,eNB_id,abstraction_flag); } // UE_mode==PUSCH +*/ -#ifdef CBA - - if ((ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag >= 1) && - (ue->ulsch[eNB_id]->harq_processes[harq_pid]->status == CBA_ACTIVE)) { - ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag=0; //-=1 - // ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; - first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb; - nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb; - //cba_mcs=ue->ulsch[eNB_id]->harq_processes[harq_pid]->mcs; - input_buffer_length = ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/8; - access_mode=CBA_ACCESS; - - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: CBA num dci %d\n", - Mod_id,frame_tx,nr_tti_tx, - ue->ulsch[eNB_id]->num_cba_dci[nr_tti_tx]); - - /*mac_xface->ue_get_sdu(Mod_id, - CC_id, - frame_tx, - proc->subframe_tx, - nr_tti_tx%(ue->frame_parms.ttis_per_subframe), - eNB_id, - ulsch_input_buffer, - input_buffer_length, - &access_mode);*/ - - ue->ulsch[eNB_id]->num_cba_dci[nr_tti_tx]=0; - - if (access_mode > UNKNOWN_ACCESS) { - - if (abstraction_flag==0) { - if (ulsch_encoding(ulsch_input_buffer, - ue, - harq_pid, - eNB_id, - proc->nr_tti_rx, - ue->transmission_mode[eNB_id],0, - 0)!=0) { // Nbundled, to be updated!!!! - LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n"); - return; - } - } - -#ifdef PHY_ABSTRACTION - else { - ulsch_encoding_emul(ulsch_input_buffer,ue,eNB_id,proc->nr_tti_rx,harq_pid,0); - } - -#endif - } else { - ue->ulsch[eNB_id]->harq_processes[harq_pid]->status= IDLE; - //reset_cba_uci(ue->ulsch[eNB_id]->o); - LOG_N(PHY,"[UE %d] Frame %d, nr_tti_rx %d: CBA transmission cancelled or postponed\n", - Mod_id, frame_tx,nr_tti_tx); - } - } - -#endif // end CBA - - if (abstraction_flag == 0) { - ulsch_common_procedures(ue,proc, (ue->generate_ul_signal[eNB_id] == 0)); - } // mode != PRACH + nr_ue_pusch_common_procedures(ue, + slot_tx, + ul_dci_pdu->precod_nbr_layers, + &ue->frame_parms); +/* if ((ue->UE_mode[eNB_id] == PRACH) && (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) { @@ -2598,54 +2545,19 @@ void phy_procedures_UE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB else { ue->generate_prach=0; } +*/ - // reset DL ACK/NACK status - uint8_t N_bundled = 0; - if (ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0] != NULL) - { - nr_reset_ack(&ue->frame_parms, - ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][eNB_id][0]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - ue->ulsch[eNB_id]->o_ACK, - &N_bundled, - 0); - /* - nr_reset_ack(&ue->frame_parms, - ue->dlsch[next1_thread_id][eNB_id][0]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - ue->ulsch[eNB_id]->o_ACK, - &N_bundled, - 0); - nr_reset_ack(&ue->frame_parms, - ue->dlsch[next2_thread_id][eNB_id][0]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - ue->ulsch[eNB_id]->o_ACK, - &N_bundled, - 0); - */ - } - - if (ue->dlsch_SI[eNB_id] != NULL) - nr_reset_ack(&ue->frame_parms, - ue->dlsch_SI[eNB_id]->harq_ack, - nr_tti_tx, - proc->nr_tti_rx, - ue->ulsch[eNB_id]->o_ACK, - &N_bundled, - 0); - - - LOG_D(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, nr_tti_tx); + LOG_D(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE stop_meas(&ue->phy_proc_tx); #endif + } + +/* void phy_procedures_UE_S_TX(PHY_VARS_NR_UE *ue,uint8_t eNB_id,uint8_t abstraction_flag,relaying_type_t r_type) { int aa;//i,aa; @@ -2669,7 +2581,7 @@ void phy_procedures_UE_S_TX(PHY_VARS_NR_UE *ue,uint8_t eNB_id,uint8_t abstractio } } -#endif +*/ void nr_ue_measurement_procedures(uint16_t l, // symbol index of each slot [0..6] PHY_VARS_NR_UE *ue, diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index ec5ed6d91d30fb3044179ae1feffd9bf82b09d69..93059c00e07bf872ad42bec1415034cc8bc39e2d 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -38,6 +38,7 @@ #include "PHY/defs_nr_UE.h" #include <openair1/SCHED/sched_common.h> #include <openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h> +#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" #ifndef NO_RAT_NR @@ -50,7 +51,8 @@ #endif -int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); + + uint8_t is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); uint8_t is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t gNB_id); /* @@ -111,7 +113,6 @@ void nr_generate_pucch3_4(int32_t **txdataF, //extern uint8_t is_cqi_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id); //extern uint8_t is_ri_TXOp(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id); - /******************************************************************* * * NAME : pucch_procedures_ue_nr diff --git a/openair1/SIMULATION/ETH_TRANSPORT/defs.h b/openair1/SIMULATION/ETH_TRANSPORT/defs.h index 5cd961b61a2cb6479622355617ba6f613be40f0e..a7b2351b905c3d14f479fed7996d76c82c384fe6 100644 --- a/openair1/SIMULATION/ETH_TRANSPORT/defs.h +++ b/openair1/SIMULATION/ETH_TRANSPORT/defs.h @@ -32,6 +32,9 @@ # define __BYPASS_SESSION_LAYER_DEFS_H__ //----------------------------------------------------------------------------- //#include "openair_defs.h" +#include "targets/COMMON/openairinterface5g_limits.h" +#include "PHY/defs_common.h" +#include "PHY/LTE_TRANSPORT/uci_common.h" typedef enum emu_transport_info_e { EMU_TRANSPORT_INFO_ERROR = 0x0, diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index bc1ca15dca72147ffbafe8799d321481d433f538..fc83c6ea5fcfba67e6b579b5867deaebc2a91851 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -43,6 +43,7 @@ #include "PHY/INIT/phy_init.h" #include "PHY/NR_TRANSPORT/nr_transport.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" +#include "PHY/phy_vars.h" #include "SCHED_NR/sched_nr.h" #include "SCHED_NR/fapi_nr_l1.h" @@ -104,7 +105,10 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) -{return(0);} +{ + return 0; +} + int rlc_module_init (void) {return(0);} void pdcp_layer_init(void) {} int rrc_init_nr_global_param(void){return(0);} @@ -121,8 +125,6 @@ void config_common(int Mod_idP, // needed for some functions -PHY_VARS_NR_UE ***PHY_vars_UE_g; -short conjugate[8]__attribute__((aligned(32))) = {-1,1,-1,1,-1,1,-1,1}; openair0_config_t openair0_cfg[MAX_CARDS]; int main(int argc, char **argv) diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 11195277b7e991da6d94225bc04fe0d365c5d22b..e1f6ce8f5c8cd01e496bc11d6d792732552f6731 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -44,6 +44,7 @@ #include "PHY/NR_TRANSPORT/nr_transport.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" +#include "PHY/phy_vars.h" #include "SCHED_NR/sched_nr.h" @@ -79,7 +80,6 @@ void exit_function(const char* file, const char* function, const int line,const } // needed for some functions -PHY_VARS_NR_UE * PHY_vars_UE_g[1][1]={{NULL}}; openair0_config_t openair0_cfg[MAX_CARDS]; int main(int argc, char **argv) diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 502bc8eeb6eeb9d17bf47bd0bab3d713a8f48cef..22a4258f379937d59e7956dbaf73ee6bf4d4bb31 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -103,45 +103,30 @@ char quantize(double D, double x, unsigned char B) { int main(int argc, char **argv) { char c; - int i,sf; //,j,l,aa; + int i,sf; double SNR, SNR_lin, snr0 = -2.0, snr1 = 2.0; double snr_step = 0.1; uint8_t snr1set = 0; - int **txdata; - double **s_re, **s_im, **r_re, **r_im; - // int sync_pos, sync_pos_slot; - // FILE *rx_frame_file; FILE *output_fd = NULL; //uint8_t write_output_file = 0; - // int subframe_offset; - // char fname[40], vname[40]; int trial, n_trials = 1, n_errors = 0, n_false_positive = 0; - uint8_t n_tx = 1, n_rx = 1; + uint8_t n_tx = 1, n_rx = 1, nb_codewords = 1; //uint8_t transmission_mode = 1; uint16_t Nid_cell = 0; channel_desc_t *gNB2UE; uint8_t extended_prefix_flag = 0; //int8_t interf1 = -21, interf2 = -21; - FILE *input_fd = NULL, *pbch_file_fd = NULL; - //char input_val_str[50],input_val_str2[50]; - //uint16_t NB_RB=25; + FILE *input_fd = NULL; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; //unsigned char frame_type = 0; //unsigned char pbch_phase = 0; int frame = 0, subframe = 0; - int frame_length_complex_samples; - //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; - //nfapi_nr_config_request_t *gNB_config; - // uint8_t Kmimo = 0; - uint32_t Nsoft = 0; double sigma; unsigned char qbits = 8; int ret; - //int run_initial_sync=0; int loglvl = OAILOG_WARNING; - float target_error_rate = 0.01; uint64_t SSB_positions=0x01; uint16_t nb_symb_sch = 12; uint16_t nb_rb = 50; @@ -383,7 +368,6 @@ int main(int argc, char **argv) { RC.gNB[0] = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); RC.gNB[0][0] = malloc(sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0][0]; - //gNB_config = &gNB->gNB_config; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; @@ -397,46 +381,7 @@ int main(int argc, char **argv) { nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions); phy_init_nr_gNB(gNB, 0, 0); - //init_eNB_afterRU(); - frame_length_complex_samples = frame_parms->samples_per_subframe; - //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; - s_re = malloc(2 * sizeof(double *)); - s_im = malloc(2 * sizeof(double *)); - r_re = malloc(2 * sizeof(double *)); - r_im = malloc(2 * sizeof(double *)); - txdata = malloc(2 * sizeof(int * )); - - for (i = 0; i < 2; i++) { - s_re[i] = malloc(frame_length_complex_samples * sizeof(double)); - bzero(s_re[i], frame_length_complex_samples * sizeof(double)); - s_im[i] = malloc(frame_length_complex_samples * sizeof(double)); - bzero(s_im[i], frame_length_complex_samples * sizeof(double)); - r_re[i] = malloc(frame_length_complex_samples * sizeof(double)); - bzero(r_re[i], frame_length_complex_samples * sizeof(double)); - r_im[i] = malloc(frame_length_complex_samples * sizeof(double)); - bzero(r_im[i], frame_length_complex_samples * sizeof(double)); - txdata[i] = malloc(frame_length_complex_samples * sizeof(int)); - bzero(r_re[i], frame_length_complex_samples * sizeof(int)); // [hna] r_re should be txdata - } - - if (pbch_file_fd != NULL) { - load_pbch_desc(pbch_file_fd); - } - - /* for (int k=0; k<2; k++) { - // Create transport channel structures for 2 transport blocks (MIMO) - for (i=0; i<2; i++) { - gNB->dlsch[k][i] = new_gNB_dlsch(Kmimo,8,Nsoft,0,frame_parms,gNB_config); - - if (!gNB->dlsch[k][i]) { - printf("Can't get eNB dlsch structures\n"); - exit(-1); - } - gNB->dlsch[k][i]->Nsoft = 10; - gNB->dlsch[k][i]->rnti = n_rnti+k; - } - }*/ //configure UE UE = malloc(sizeof(PHY_VARS_NR_UE)); memcpy(&UE->frame_parms, frame_parms, sizeof(NR_DL_FRAME_PARMS)); @@ -447,8 +392,6 @@ int main(int argc, char **argv) { exit(-1); } - //nr_init_frame_parms_ue(&UE->frame_parms); - //init_nr_ue_transport(UE, 0); for (sf = 0; sf < 2; sf++) { for (i = 0; i < 2; i++) { @@ -462,31 +405,28 @@ int main(int argc, char **argv) { } } - UE->dlsch_SI[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0); - UE->dlsch_ra[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0); - - unsigned char harq_pid = 0; //dlsch->harq_ids[subframe]; - //time_stats_t *rm_stats, *te_stats, *i_stats; - uint8_t is_crnti = 0, llr8_flag = 0; + unsigned char harq_pid = 0; + uint8_t is_crnti = 0; unsigned int TBS = 8424; unsigned int available_bits; uint8_t nb_re_dmrs = 6; - uint16_t length_dmrs = 1; + uint8_t length_dmrs = 1; + uint8_t N_PRB_oh; + uint16_t N_RE_prime; unsigned char mod_order; uint8_t Nl = 1; uint8_t rvidx = 0; - uint8_t UE_id = 1; + uint8_t UE_id = 0; - NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id][0]; + NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id+1][0]; nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15; NR_UE_ULSCH_t *ulsch_ue = UE->ulsch[0][0][0]; - ulsch_ue->nb_re_dmrs = nb_re_dmrs; //[adk] A HOT FIX until cearting nfapi_nr_ul_config_ulsch_pdu_rel15_t - mod_order = nr_get_Qm(Imcs, 1); available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1); TBS = nr_compute_tbs(Imcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, Nl); + printf("\n"); printf("available bits %d TBS %d mod_order %d\n", available_bits, TBS, mod_order); /////////// setting rel15_ul parameters /////////// @@ -496,19 +436,19 @@ int main(int argc, char **argv) { rel15_ul->mcs = Imcs; rel15_ul->rv = rvidx; rel15_ul->n_layers = Nl; + rel15_ul->nb_re_dmrs = nb_re_dmrs; + rel15_ul->length_dmrs = length_dmrs; /////////////////////////////////////////////////// double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); // [hna] 16 segments, 68*Zc short *channel_output_fixed = malloc16(sizeof(short) * 16 * 68 * 384); short *channel_output_uncoded = malloc16(sizeof(unsigned short) * 16 * 68 * 384); unsigned int errors_bit_uncoded = 0; - // unsigned char *estimated_output; unsigned char *estimated_output_bit; unsigned char *test_input_bit; unsigned int errors_bit = 0; test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); - // estimated_output = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); unsigned char *test_input; @@ -517,18 +457,29 @@ int main(int argc, char **argv) { for (i = 0; i < TBS / 8; i++) test_input[i] = (unsigned char) rand(); - // estimated_output = ulsch_gNB->harq_processes[harq_pid]->b; + + /////////////////////////[adk] preparing NR_UE_ULSCH_t parameters///////////////////////// A HOT FIX until creating nfapi_nr_ul_config_ulsch_pdu_rel15_t + /////////// + ulsch_ue->nb_re_dmrs = nb_re_dmrs; + ulsch_ue->length_dmrs = length_dmrs; + ulsch_ue->rnti = n_rnti; + /////////// + //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////[adk] preparing UL harq_process parameters///////////////////////// /////////// NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; + N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig + N_RE_prime = NR_NB_SC_PER_RB*nb_symb_sch - nb_re_dmrs - N_PRB_oh; + if (harq_process_ul_ue) { harq_process_ul_ue->mcs = Imcs; harq_process_ul_ue->Nl = Nl; harq_process_ul_ue->nb_rb = nb_rb; - harq_process_ul_ue->nb_symbols = nb_symb_sch; + harq_process_ul_ue->number_of_symbols = nb_symb_sch; + harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb*nb_codewords; harq_process_ul_ue->rvidx = rvidx; harq_process_ul_ue->TBS = TBS; harq_process_ul_ue->a = &test_input[0]; @@ -541,23 +492,18 @@ int main(int argc, char **argv) { for (i = 0; i < TBS / 8; i++) printf("test_input[i]=%d \n",test_input[i]); #endif - /*for (int i=0; i<TBS/8; i++) - printf("test input[%d]=%d \n",i,test_input[i]);*/ - - //printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32)); - // generate signal - - /////////////////////////[adk] ULSCH coding///////////////////////// + /////////////////////////ULSCH coding///////////////////////// /////////// if (input_fd == NULL) { nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid); } + + printf("\n"); /////////// //////////////////////////////////////////////////////////////////// - for (SNR = snr0; SNR < snr1; SNR += snr_step) { n_errors = 0; n_false_positive = 0; @@ -574,22 +520,20 @@ int main(int argc, char **argv) { #endif /* if (i<16){ - printf("dlsch_encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]); printf("ulsch_encoder output f[%d] = %d\n",i,ulsch_ue->harq_processes[0]->f[i]); } */ - if (ulsch_ue->harq_processes[0]->f[i] == 0) + if (ulsch_ue->g[i] == 0) modulated_input[i] = 1.0; ///sqrt(2); //QPSK else modulated_input[i] = -1.0; ///sqrt(2); //if (i<16) printf("modulated_input[%d] = %d\n",i,modulated_input[i]); - //SNR =10; SNR_lin = pow(10, SNR / 10.0); sigma = 1.0 / sqrt(2 * SNR_lin); -#if 1 +#if 0 channel_output_fixed[i] = (short) quantize(sigma / 4.0 / 4.0, modulated_input[i] + sigma * gaussdouble(0.0, 1.0), qbits); @@ -597,13 +541,8 @@ int main(int argc, char **argv) { channel_output_fixed[i] = (short) quantize(0.01, modulated_input[i], qbits); #endif //channel_output_fixed[i] = (char)quantize8bit(sigma/4.0,(2.0*modulated_input[i]) - 1.0 + sigma*gaussdouble(0.0,1.0)); - //printf("llr[%d]=%d\n",i,channel_output_fixed[i]); //printf("channel_output_fixed[%d]: %d\n",i,channel_output_fixed[i]); - //channel_output_fixed[i] = (char)quantize(1,channel_output_fixed[i],qbits); - - //if (i<16) printf("channel_output_fixed[%d] = %d\n",i,channel_output_fixed[i]); - //Uncoded BER if (channel_output_fixed[i] < 0) channel_output_uncoded[i] = 1; //QPSK demod @@ -614,16 +553,15 @@ int main(int argc, char **argv) { errors_bit_uncoded = errors_bit_uncoded + 1; } - //if (errors_bit_uncoded>10) printf("errors bits uncoded %u\n", errors_bit_uncoded); - + printf("\n"); #ifdef DEBUG_CODER printf("\n"); exit(-1); #endif ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, - frame, nb_symb_sch, subframe, harq_pid, is_crnti, llr8_flag); + frame, nb_symb_sch, subframe, harq_pid, is_crnti); if (ret > ulsch_gNB->max_ldpc_iterations) n_errors++; @@ -637,7 +575,6 @@ int main(int argc, char **argv) { if (estimated_output_bit[i] != test_input_bit[i]) { errors_bit++; - //printf("estimated bits error occurs @%d ",i); } } @@ -646,6 +583,7 @@ int main(int argc, char **argv) { if (n_trials == 1) printf("errors_bit %d (trial %d)\n", errors_bit, trial); } + printf("\n"); } printf("*****************************************\n"); @@ -653,46 +591,16 @@ int main(int argc, char **argv) { (float) n_errors / (float) n_trials, (float) n_false_positive / (float) n_trials); printf("*****************************************\n"); + printf("\n"); - if ((float) n_errors / (float) n_trials < target_error_rate) { + if (errors_bit == 0) { printf("PUSCH test OK\n"); + printf("\n"); break; } + printf("\n"); } - /*LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1);*/ - - //TODO: loop over slots - /*for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) { - if (gNB_config->subframe_config.dl_cyclic_prefix_type.value == 1) { - PHY_ofdm_mod(gNB->common_vars.txdataF[aa], - txdata[aa], - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { - nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], - txdata[aa], - 14, - frame_parms); - } - } - - LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1); - - - for (i=0; i<frame_length_complex_samples; i++) { - for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { - r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); - r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); - } - }*/ - for (i = 0; i < 2; i++) { printf("----------------------\n"); @@ -703,9 +611,9 @@ int main(int argc, char **argv) { free_gNB_ulsch(gNB->ulsch[0][i]); - printf("gNB ulsch[%d][%d]\n",UE_id, i); + printf("gNB ulsch[%d][%d]\n",UE_id+1, i); - free_gNB_ulsch(gNB->ulsch[UE_id][i]); + free_gNB_ulsch(gNB->ulsch[UE_id+1][i]); for (sf = 0; sf < 2; sf++) { @@ -718,20 +626,6 @@ int main(int argc, char **argv) { printf("\n"); } - for (i = 0; i < 2; i++) { - free(s_re[i]); - free(s_im[i]); - free(r_re[i]); - free(r_im[i]); - free(txdata[i]); - } - - free(s_re); - free(s_im); - free(r_re); - free(r_im); - free(txdata); - if (output_fd) fclose(output_fd); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c new file mode 100644 index 0000000000000000000000000000000000000000..2895a5272eafef620058761b73c59091032f8dbd --- /dev/null +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -0,0 +1,630 @@ +/* +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org +*/ + +#include <string.h> +#include <math.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#include "common/config/config_userapi.h" +#include "common/utils/LOG/log.h" +#include "common/ran_context.h" + +#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" + +#include "SIMULATION/TOOLS/sim.h" +#include "SIMULATION/RF/rf.h" + +#include "PHY/types.h" +#include "PHY/defs_nr_common.h" +#include "PHY/defs_nr_UE.h" +#include "PHY/defs_gNB.h" +#include "PHY/INIT/phy_init.h" +#include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_REFSIG/nr_mod_table.h" +#include "PHY/MODULATION/nr_modulation.h" +#include "PHY/MODULATION/modulation_UE.h" +#include "PHY/NR_TRANSPORT/nr_transport.h" +#include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "PHY/NR_TRANSPORT/nr_ulsch.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" +#include "SCHED_NR/sched_nr.h" +#include "SCHED_NR_UE/defs.h" +#include "PHY/TOOLS/tools_defs.h" +#include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" +#include "PHY/phy_vars.h" + +//#include "PHY/MODULATION/modulation_common.h" +//#include "common/config/config_load_configmodule.h" +//#include "UTIL/LISTS/list.h" +//#include "common/ran_context.h" + +//#define DEBUG_ULSIM +PHY_VARS_gNB *gNB; +PHY_VARS_NR_UE *UE; +RAN_CONTEXT_t RC; + + + +double cpuf; + +// dummy functions +int nfapi_mode = 0; +int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { + return (0); +} +int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { + return (0); +} + +int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { + return (0); +} + +int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { + return (0); +} + +int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) { + return (0); +} + +uint32_t from_nrarfcn(int nr_bandP, uint32_t dl_earfcn) { + return (0); +} +int32_t get_uldl_offset(int eutra_bandP) { + return (0); +} + +NR_IF_Module_t * +NR_IF_Module_init(int Mod_id) { + return (NULL); +} + +void exit_function(const char *file, const char *function, const int line, const char *s) { + const char *msg = s == NULL ? "no comment" : s; + printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg); + exit(-1); +} + +int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, + const int CC_id, + const uint8_t gNB_index, + const int8_t channel, + const uint8_t* pduP, + const sdu_size_t pdu_len) +{ + return 0; +} + +// needed for some functions +uint16_t n_rnti = 0x1234; +openair0_config_t openair0_cfg[MAX_CARDS]; + +char quantize(double D, double x, unsigned char B) { + double qxd; + short maxlev; + qxd = floor(x / D); + maxlev = 1 << (B - 1); //(char)(pow(2,B-1)); + + //printf("x=%f,qxd=%f,maxlev=%d\n",x,qxd, maxlev); + + if (qxd <= -maxlev) + qxd = -maxlev; + else if (qxd >= maxlev) + qxd = maxlev - 1; + + return ((char) qxd); +} + +int main(int argc, char **argv) { + + char c; + int i,sf; + double SNR, snr0 = -2.0, snr1 = 2.0; + double sigma, sigma_dB; + double snr_step = 0.1; + uint8_t snr1set = 0; + int slot = 0; + FILE *output_fd = NULL; + //uint8_t write_output_file = 0; + int trial, n_trials = 1, n_errors = 0, n_false_positive = 0; + uint8_t n_tx = 1, n_rx = 1; + //uint8_t transmission_mode = 1; + uint16_t Nid_cell = 0; + channel_desc_t *gNB2UE; + uint8_t extended_prefix_flag = 0; + //int8_t interf1 = -21, interf2 = -21; + FILE *input_fd = NULL; + SCM_t channel_model = AWGN; //Rayleigh1_anticorr; + uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; + //unsigned char frame_type = 0; + int frame = 0; + int frame_length_complex_samples; + NR_DL_FRAME_PARMS *frame_parms; + int loglvl = OAILOG_WARNING; + uint64_t SSB_positions=0x01; + uint16_t nb_symb_sch = 12; + int start_symbol = NR_SYMBOLS_PER_SLOT - nb_symb_sch; + uint16_t nb_rb = 50; + uint8_t Imcs = 9; + int gNB_id = 0; + int ap; + int tx_offset; + double txlev_float; + int32_t txlev; + int start_rb = 30; + int UE_id =0; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault) + + + cpuf = get_cpu_freq_GHz(); + + + fapi_nr_dci_pdu_rel15_t *ul_dci_pdu; + UE_nr_rxtx_proc_t UE_proc; + + + if (load_configmodule(argc, argv) == 0) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + + //logInit(); + randominit(0); + + while ((c = getopt(argc, argv, "df:hpg:i:j:n:l:m:r:s:S:y:z:M:N:F:R:P:")) != -1) { + switch (c) { + /*case 'f': + write_output_file = 1; + output_fd = fopen(optarg, "w"); + + if (output_fd == NULL) { + printf("Error opening %s\n", optarg); + exit(-1); + } + + break;*/ + + /*case 'd': + frame_type = 1; + break;*/ + + case 'g': + switch ((char) *optarg) { + case 'A': + channel_model = SCM_A; + break; + + case 'B': + channel_model = SCM_B; + break; + + case 'C': + channel_model = SCM_C; + break; + + case 'D': + channel_model = SCM_D; + break; + + case 'E': + channel_model = EPA; + break; + + case 'F': + channel_model = EVA; + break; + + case 'G': + channel_model = ETU; + break; + + default: + msg("Unsupported channel model!\n"); + exit(-1); + } + + break; + + /*case 'i': + interf1 = atoi(optarg); + break; + + case 'j': + interf2 = atoi(optarg); + break;*/ + + case 'n': + n_trials = atoi(optarg); + break; + + case 's': + snr0 = atof(optarg); + msg("Setting SNR0 to %f\n", snr0); + break; + + case 'S': + snr1 = atof(optarg); + snr1set = 1; + msg("Setting SNR1 to %f\n", snr1); + break; + + case 'p': + extended_prefix_flag = 1; + break; + + /* + case 'r': + ricean_factor = pow(10,-.1*atof(optarg)); + if (ricean_factor>1) { + printf("Ricean factor must be between 0 and 1\n"); + exit(-1); + } + break; + */ + + case 'y': + n_tx = atoi(optarg); + + if ((n_tx == 0) || (n_tx > 2)) { + msg("Unsupported number of tx antennas %d\n", n_tx); + exit(-1); + } + + break; + + case 'z': + n_rx = atoi(optarg); + + if ((n_rx == 0) || (n_rx > 2)) { + msg("Unsupported number of rx antennas %d\n", n_rx); + exit(-1); + } + + break; + + case 'M': + SSB_positions = atoi(optarg); + break; + + case 'N': + Nid_cell = atoi(optarg); + break; + + case 'R': + N_RB_DL = atoi(optarg); + N_RB_UL = N_RB_DL; + break; + + case 'F': + input_fd = fopen(optarg, "r"); + + if (input_fd == NULL) { + printf("Problem with filename %s\n", optarg); + exit(-1); + } + + break; + + case 'm': + Imcs = atoi(optarg); + break; + + case 'l': + nb_symb_sch = atoi(optarg); + break; + + case 'r': + nb_rb = atoi(optarg); + break; + + /*case 'x': + transmission_mode = atoi(optarg); + break;*/ + + default: + case 'h': + printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]); + printf("-h This message\n"); + printf("-p Use extended prefix mode\n"); + //printf("-d Use TDD\n"); + printf("-n Number of frames to simulate\n"); + printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n"); + printf("-S Ending SNR, runs from SNR0 to SNR1\n"); + printf("-t Delay spread for multipath channel\n"); + printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); + //printf("-x Transmission mode (1,2,6 for the moment)\n"); + printf("-y Number of TX antennas used in eNB\n"); + printf("-z Number of RX antennas used in UE\n"); + //printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n"); + //printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n"); + printf("-M Multiple SSB positions in burst\n"); + printf("-N Nid_cell\n"); + printf("-R N_RB_DL\n"); + printf("-O oversampling factor (1,2,4,8,16)\n"); + printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n"); + //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n"); + //printf("-f Output filename (.txt format) for Pe/SNR results\n"); + printf("-F Input filename (.txt format) for RX conformance testing\n"); + exit(-1); + break; + } + } + + logInit(); + set_glog(loglvl); + T_stdout = 1; + + if (snr1set == 0) + snr1 = snr0 + 10; + + gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, + 61.44e6, //N_RB2sampling_rate(N_RB_DL), + 40e6, //N_RB2channel_bandwidth(N_RB_DL), + 0, 0, 0); + + if (gNB2UE == NULL) { + msg("Problem generating channel model. Exiting.\n"); + exit(-1); + } + + RC.gNB = (PHY_VARS_gNB ** *) malloc(sizeof(PHY_VARS_gNB **)); + RC.gNB[0] = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); + RC.gNB[0][0] = malloc(sizeof(PHY_VARS_gNB)); + gNB = RC.gNB[0][0]; + //gNB_config = &gNB->gNB_config; + gNB_L1_rxtx_proc_t gNB_proc; + + gNB_proc.frame_rx = frame; + gNB_proc.slot_rx = slot; + + UE_proc.nr_tti_tx = slot; + UE_proc.frame_tx = frame; + + frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) + frame_parms->nb_antennas_tx = n_tx; + frame_parms->nb_antennas_rx = n_rx; + frame_parms->N_RB_DL = N_RB_DL; + frame_parms->N_RB_UL = N_RB_UL; + frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; + + crcTableInit(); + + nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions); + + phy_init_nr_gNB(gNB, 0, 0); + //init_eNB_afterRU(); + + frame_length_complex_samples = frame_parms->samples_per_subframe; + //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; + + //configure UE + UE = malloc(sizeof(PHY_VARS_NR_UE)); + memcpy(&UE->frame_parms, frame_parms, sizeof(NR_DL_FRAME_PARMS)); + + //phy_init_nr_top(frame_parms); + if (init_nr_ue_signal(UE, 1, 0) != 0) { + printf("Error at UE NR initialisation\n"); + exit(-1); + } + + //nr_init_frame_parms_ue(&UE->frame_parms); + //init_nr_ue_transport(UE, 0); + for (sf = 0; sf < 2; sf++) { + for (i = 0; i < 2; i++) { + + UE->ulsch[sf][0][i] = new_nr_ue_ulsch(N_RB_UL, 8, 0); + + if (!UE->ulsch[sf][0][i]) { + printf("Can't get ue ulsch structures\n"); + exit(-1); + } + + } + } + + ul_dci_pdu = &UE->dci_ind.dci_list[0].dci; + + ul_dci_pdu->mcs = Imcs; + ul_dci_pdu->rv = 0; + ul_dci_pdu->precod_nbr_layers = 1; + + unsigned char harq_pid = 0; + unsigned int TBS = 8424; + unsigned int available_bits; + uint8_t nb_re_dmrs = UE->dmrs_UplinkConfig.pusch_maxLength*(UE->dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)?6:4; + uint8_t length_dmrs = 1; + unsigned char mod_order; + + mod_order = nr_get_Qm(Imcs, 1); + available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, 1); + TBS = nr_compute_tbs(Imcs, nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, ul_dci_pdu->precod_nbr_layers); + + NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id+1][0]; + nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu; + + NR_UE_ULSCH_t **ulsch_ue = UE->ulsch[0][0]; + + // --------- setting rel15_ul parameters ---------- + rel15_ul->rnti = n_rnti; + rel15_ul->ulsch_pdu_rel15.start_rb = start_rb; + rel15_ul->ulsch_pdu_rel15.number_rbs = nb_rb; + rel15_ul->ulsch_pdu_rel15.start_symbol = start_symbol; + rel15_ul->ulsch_pdu_rel15.number_symbols = nb_symb_sch; + rel15_ul->ulsch_pdu_rel15.nb_re_dmrs = nb_re_dmrs; + rel15_ul->ulsch_pdu_rel15.length_dmrs = length_dmrs; + rel15_ul->ulsch_pdu_rel15.Qm = mod_order; + rel15_ul->ulsch_pdu_rel15.mcs = Imcs; + rel15_ul->ulsch_pdu_rel15.rv = 0; + rel15_ul->ulsch_pdu_rel15.n_layers = ul_dci_pdu->precod_nbr_layers; + /////////////////////////////////////////////////// + + unsigned char *estimated_output_bit; + unsigned char *test_input_bit; + unsigned int errors_bit = 0; + uint32_t errors_scrambling = 0; + + test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); + estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); + + /////////////////////////phy_procedures_nr_ue_TX/////////////////////// + /////////// + + phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id, 0); + + /////////// + //////////////////////////////////////////////////// + tx_offset = slot*frame_parms->samples_per_slot; + + txlev = signal_energy_amp_shift(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); + + txlev_float = (double)txlev/(double)AMP; // output of signal_energy is fixed point representation + + + + printf("\n"); + + for (SNR = snr0; SNR < snr1; SNR += snr_step) { + + n_errors = 0; + n_false_positive = 0; + + //AWGN + sigma_dB = 10*log10(txlev_float)-SNR; + sigma = pow(10,sigma_dB/10); + + for (trial = 0; trial < n_trials; trial++) { + + errors_scrambling = 0; + errors_bit = 0; + + for (i=0; i<frame_length_complex_samples; i++) { + for (ap=0; ap<frame_parms->nb_antennas_rx; ap++) { + // [hna] doesn't work with noise in case of mod_order = 6 + ((short*) gNB->common_vars.rxdata[ap])[2*i] = (((int16_t *)UE->common_vars.txdata[ap])[(i<<1)])+ (int16_t)(sqrt(sigma/2)*gaussdouble(0.0,1.0)*(double)AMP); // convert to fixed point + ((short*) gNB->common_vars.rxdata[ap])[2*i+1] = (((int16_t *)UE->common_vars.txdata[ap])[(i<<1)+1])+ (int16_t)(sqrt(sigma/2)*gaussdouble(0.0,1.0)*(double)AMP); + } + } + + + phy_procedures_gNB_common_RX(gNB, &gNB_proc); + + phy_procedures_gNB_uespec_RX(gNB, &gNB_proc, rel15_ul->ulsch_pdu_rel15.start_symbol, rel15_ul->ulsch_pdu_rel15.start_symbol + rel15_ul->ulsch_pdu_rel15.number_symbols); + + + //---------------------------------------------------------- + //---------------------- count errors ---------------------- + //---------------------------------------------------------- + + for (i = 0; i < available_bits; i++) { + + if(((ulsch_ue[0]->g[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) || + ((ulsch_ue[0]->g[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0))) + { + if(errors_scrambling == 0) { + printf("\n"); + printf("First bit in error in unscrambling = %d\n",i); + } + errors_scrambling++; + } + + } + + for (i = 0; i < TBS; i++) { + + estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); + test_input_bit[i] = (ulsch_ue[0]->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + + if (estimated_output_bit[i] != test_input_bit[i]) { + if(errors_bit == 0) + printf("First bit in error in decoding = %d\n",i); + errors_bit++; + } + + } + + //////////////////////////////////////////////////////////// + + if (errors_scrambling > 0) { + if (n_trials == 1) + printf("errors_scrambling = %d (trial %d)\n", errors_scrambling, trial); + } + + if (errors_bit > 0) { + n_false_positive++; + if (n_trials == 1) + printf("errors_bit = %d (trial %d)\n", errors_bit, trial); + } + printf("\n"); + } // [hna] for (trial = 0; trial < n_trials; trial++) + + printf("*****************************************\n"); + printf("SNR %f, (false positive %f)\n", SNR, + (float) n_false_positive / (float) n_trials); + printf("*****************************************\n"); + printf("\n"); + + if (errors_bit == 0) { + printf("PUSCH test OK\n"); + printf("\n"); + break; + } + printf("\n"); + } // [hna] for (SNR = snr0; SNR < snr1; SNR += snr_step) + + + for (i = 0; i < 2; i++) { + + printf("----------------------\n"); + printf("freeing codeword %d\n", i); + printf("----------------------\n"); + + printf("gNB ulsch[0][%d]\n", i); // [hna] ulsch[0] is for RA + + free_gNB_ulsch(gNB->ulsch[0][i]); + + printf("gNB ulsch[%d][%d]\n",UE_id+1, i); + + free_gNB_ulsch(gNB->ulsch[UE_id+1][i]); // "+1" because first element in ulsch is for RA + + for (sf = 0; sf < 2; sf++) { + + printf("UE ulsch[%d][0][%d]\n", sf, i); + + if (UE->ulsch[sf][0][i]) + free_nr_ue_ulsch(UE->ulsch[sf][0][i]); + } + + printf("\n"); + } + + if (output_fd) + fclose(output_fd); + + if (input_fd) + fclose(input_fd); + + return (n_errors); +} diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index c338920397764f6554e07702ed6a58c4a0c09097..80503cb93eb06a2d4af1c0e8a5d474e21d042ce2 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -114,6 +114,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler( uint32_t ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, rnti_t rnti, sub_frame_t subframe); +int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fapi_nr_dci_pdu_rel15_t *dci, uint16_t rnti, uint32_t dci_format); @@ -123,6 +124,7 @@ uint32_t get_ssb_slot(uint32_t ssb_index); uint32_t mr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); + void nr_ue_process_mac_pdu( module_id_t module_idP, uint8_t CC_id, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 05e88e3ed9d254746908f8eb9ed0421e19ee843c..da2da96c502bd1ecb3d435f3bfae13401bcb75e5 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2012,7 +2012,6 @@ int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t e } - void nr_ue_process_mac_pdu( module_id_t module_idP, uint8_t CC_id, diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index ec65c3b4f80e59fcefdb0bf31f67725281c51838..493e78a8ab85422dfec0e12649a5dde5a3ce1f77 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -96,8 +96,14 @@ int set_transport(openair0_device *device) { } } typedef int(*devfunc_t)(openair0_device *, openair0_config_t *, eth_params_t *); +//loader_shlibfunc_t shlib_fdesc[2]; + /* look for the interface library and load it */ -int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *cfg, uint8_t flag) { +int load_lib(openair0_device *device, + openair0_config_t *openair0_cfg, + eth_params_t *cfg, + uint8_t flag) +{ loader_shlibfunc_t shlib_fdesc[1]; int ret=0; char *libname; @@ -113,6 +119,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param else libname=OAI_RF_LIBNAME; shlib_fdesc[0].fname="device_init"; + //shlib_fdesc[1].fname="uhd_set_thread_priority"; } else { libname=OAI_TP_LIBNAME; shlib_fdesc[0].fname="transport_init"; @@ -123,12 +130,32 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param LOG_E(HW,"Library %s couldn't be loaded\n",libname); } else { ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg); - } - +//uhd_set_thread_priority_fun = (set_prio_func_t)shlib_fdesc[1].fptr; + } return ret; } +void uhd_set_thread_prio(void) { + + loader_shlibfunc_t shlib_fdesc[1]; + int ret = 0; + + char *libname; + if (getenv("RFSIMULATOR") != NULL) + libname="rfsimulator"; + else + libname=OAI_RF_LIBNAME; + shlib_fdesc[0].fname="uhd_set_thread_priority"; + ret=load_module_shlib(libname,shlib_fdesc,1,NULL); + if (ret < 0) { + LOG_E(HW,"Library %s couldn't be loaded\n",libname); + } else { + (set_prio_func_t)shlib_fdesc[0].fptr(); + } + return ret; + +} int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 8094b15cc8f1f98304852ab65be798d7d07156e1..3aa4f714acaab1173f950f38e309a58026bd5376 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -411,7 +411,7 @@ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_ #define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) -#define sample_t uint32_t // 2*16 bits complex number +#define sample_t struct complex16 // 2*16 bits complex number typedef struct { uint64_t magic; // Magic value (see defines above) @@ -452,6 +452,10 @@ int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *open #define gettid() syscall(__NR_gettid) /*@}*/ + void uhd_set_thread_prio(void); + typedef void(*set_prio_func_t)(void); + set_prio_func_t uhd_set_thread_priority_fun; + #ifdef __cplusplus } #endif diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 9579b4d093a371772bafb4262c8a9ddfaa3c31d8..c6f22f97e62b0c9c7f24a476b830ecb3f22d7ebf 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -1473,5 +1473,10 @@ extern "C" { #endif return 0; } + + void uhd_set_thread_priority(void) { + uhd::set_thread_priority_safe(1.0); + } + } /*@}*/ diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index 10f0afd6d386abc2d99ec29a16b9882546acccd1..786591a281f4ec089f078d9470a22b6eb40899c3 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -3,7 +3,7 @@ This is a RF simulator that allows to test OAI without a RF board. It replaces a actual RF board driver. -As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound) +As much as possible, it works like a RF board, but not in realtime: It can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound) ## build @@ -19,7 +19,7 @@ Then, you can use it freely # Usage Setting the env variable RFSIMULATOR enables the RF board simulator -It should the set to "enb" in the eNB +It should the set to "server" in the eNB or gNB ## 4G case @@ -29,7 +29,7 @@ example: ```bash sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 --rfsim ``` -For the eNodeB, use a valid configuration file setup for USRP board tests and start the softmodem as usual, but adding the `--rfsim` option. +For the eNodeB, use a valid configuration file setup for USRP board tests and start the softmodem as usual, **but** adding the `--rfsim` option. ```bash sudo RFSIMULATOR=enb ./lte-softmodem -O <config file> --rfsim @@ -65,9 +65,27 @@ sudo RFSIMULATOR=enb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000 ``` -Of course, set the gNB machine IP address if the UE and the gNB are not on the same machine +Of course, set the gNB machine IP address if the UE and the gNB are not on the same machine. + In UE, you can add "-d" to get the softscope -## Caveats +### Channel simulation +The RF channel simulator is called. +In current version all channel paramters are hard coded in the call to: + +```bash +new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, + AWGN, + bridge->sample_rate, + bridge->tx_bw, + 0.0, // forgetting_factor + 0, // maybe used for TA + 0); // path_loss in dB +``` + +Only the input noise can be changed on command line with -s parameter. -Still issues in power control: txgain, rxgain are not used +With path loss = 0 set "-s 5" to see a little noise. + +## Caveats +Still issues in power control: txgain, rxgain are not used \ No newline at end of file diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index b1a6644e5ede48722718c3e9f3ae46ab7ae49b95..d5f77acc9186abbaa049d3b317200a9a2db5e1d2 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -3,7 +3,7 @@ copyleft: OpenAirInterface Software Alliance and it's licence */ -/* +/* * Open issues and limitations * The read and write should be called in the same thread, that is not new USRP UHD design * When the opposite side switch from passive reading to active R+Write, the synchro is not fully deterministic @@ -27,14 +27,23 @@ #include "common_lib.h" #include <openair1/PHY/defs_eNB.h> #include "openair1/PHY/defs_UE.h" +#include <openair1/SIMULATION/TOOLS/sim.h> #define PORT 4043 //TCP port for this simulator #define CirSize 3072000 // 100ms is enough -#define sample_t uint32_t // 2*16 bits complex number #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) -#define sample_t uint32_t //2*16 bits complex number +#define MAX_SIMULATION_CONNECTED_NODES 5 +#define GENERATE_CHANNEL 10 //each frame in DL + +// Fixme: datamodel, external variables in .h files, ... +#include <common/ran_context.h> +extern double snr_dB; +extern RAN_CONTEXT_t RC; +// + +pthread_mutex_t Sockmutex; typedef struct buffer_s { int conn_sock; @@ -46,6 +55,7 @@ typedef struct buffer_s { uint64_t remainToTransfer; char *circularBufEnd; sample_t *circularBuf; + channel_desc_t *channel_model; } buffer_t; typedef struct { @@ -55,8 +65,92 @@ typedef struct { char *ip; int saveIQfile; buffer_t buf[FD_SETSIZE]; + int rx_num_channels; + int tx_num_channels; + double sample_rate; + double tx_bw; } rfsimulator_state_t; +/* + Legacy study: + The parameters are: + gain&loss (decay, signal power, ...) + either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average + => don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE + will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop) + lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas); + a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain + + multi_path (auto convolution, ISI, ...) + either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes + legacy: we regenerate each sub frame in UL, and each frame only in DL +*/ +void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig, + int rxAnt, + channel_desc_t *channelDesc, + int nbSamples, + uint64_t TS + ) { + // channelDesc->path_loss_dB should contain the total path gain + // so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...) + // UE and NB gain control to be added + // Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...) + const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0); + // Energy in one sample to calibrate input noise + //Fixme: modified the N0W computation, not understand the origin value + const double KT=1.38e-23*290; //Boltzman*temperature + // sampling rate is linked to acquisition band (the input pass band filter) + const double noise_figure_watt = KT*channelDesc->sampling_rate; + // Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ? + // the parameter "-s" is declared as SNR, but the input power is not well defined + // −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise) + const double rxGain= 132.24 - snr_dB; + const double noise_per_sample = sqrt(0.5*noise_figure_watt) * pow(10,rxGain/20); + // Fixme: we don't fill the offset length samples at begining ? + // anyway, in today code, channel_offset=0 + const int dd = abs(channelDesc->channel_offset); + const int nbTx=channelDesc->nb_tx; + + for (int i=0; i<((int)nbSamples-dd); i++) { + struct complex16 *out_ptr=after_channel_sig+dd+i; + struct complex rx_tmp= {0}; + + for (int txAnt=0; txAnt < nbTx; txAnt++) { + const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)]; + + //const struct complex *channelModelEnd=channelModel+channelDesc->channel_length; + for (int l = 0; l<(int)channelDesc->channel_length; l++) { + // let's assume TS+i >= l + // fixme: the rfsimulator current structure is interleaved antennas + // this has been designed to not have to wait a full block transmission + // but it is not very usefull + // it would be better to split out each antenna in a separate flow + // that will allow to mix ru antennas freely + struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize]; + rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y; + rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y; + } //l + } + + out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0)); + /* + printf("in: %d, out %d= %f*%f + %f*%f\n", + input_sig[((TS+i)*nbTx)%CirSize].r, out_ptr->r , rx_tmp.x, + pathLossLinear, noise_per_sample,gaussdouble(0.0,1.0)); + */ + out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0)); + out_ptr++; + } + + if ( (TS*nbTx)%CirSize+nbSamples <= CirSize ) + // Cast to a wrong type for compatibility ! + LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n", + 10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)), + 10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)), + channelDesc->path_loss_dB, + 10*log10(noise_per_sample)); +} + void allocCirBuf(rfsimulator_state_t *bridge, int sock) { buffer_t *ptr=&bridge->buf[sock]; AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, ""); @@ -73,12 +167,35 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ev.events = EPOLLIN | EPOLLRDHUP; ev.data.fd = sock; AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, ""); + // create channel simulation model for this mode reception + // snr_dB is pure global, coming from configuration paramter "-s" + // Fixme: referenceSignalPower should come from the right place + // but the datamodel is inconsistant + // legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower + // (must not come from ru[]->frame_parms as it doesn't belong to ru !!!) + // Legacy sets it as: + // ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower; + // we use directly the paramter passed on the command line ("-s") + // the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value) + // Legacy changes directlty the variable channel_model->path_loss_dB place to place + // while calling new_channel_desc_scm() with path losses = 0 + ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, + AWGN, + bridge->sample_rate, + bridge->tx_bw, + 0.0, // forgetting_factor + 0, // maybe used for TA + 0); // path_loss in dB + random_channel(ptr->channel_model,false); } void removeCirBuf(rfsimulator_state_t *bridge, int sock) { AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, ""); close(sock); free(bridge->buf[sock].circularBuf); + // Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented + // a lot of mem leaks + free(bridge->buf[sock].channel_model); memset(&bridge->buf[sock], 0, sizeof(buffer_t)); bridge->buf[sock].conn_sock=-1; } @@ -126,8 +243,7 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { } AssertFatal(fd>=0 && _buf && count >0 && t, - "Bug: %d/%p/%zd/%p", fd, _buf, count, t); - + "Bug: %d/%p/%zd/%p", fd, _buf, count, t); char *buf = _buf; ssize_t l; setblocking(fd, notBlocking); @@ -140,8 +256,8 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { continue; if(errno==EAGAIN) { - // The opposite side is saturated - // we read incoming sockets meawhile waiting + // The opposite side is saturated + // we read incoming sockets meawhile waiting flushInput(t, 5); continue; } else @@ -234,12 +350,15 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); } } + lastW=timestamp; LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n", nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) ); // Let's verify we don't have incoming data // This is mandatory when the opposite side don't transmit + // This is mandatory when the opposite side don't transmit flushInput(t, 0); + pthread_mutex_unlock(&Sockmutex); return nsamps; } @@ -250,9 +369,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout); if ( nfds==-1 ) { - if ( errno==EINTR || errno==EAGAIN ) + if ( errno==EINTR || errno==EAGAIN ) { return false; - else + } else AssertFatal(false,"error in epoll_wait\n"); } @@ -314,27 +433,31 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { if ( b->lastReceivedTS != b->th.timestamp) { int nbAnt= b->th.nbAnt; - for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) - for (int a=0; a < nbAnt; a++) - b->circularBuf[(index*nbAnt+a)%CirSize]=0; + for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { + for (int a=0; a < nbAnt; a++) { + b->circularBuf[(index*nbAnt+a)%CirSize].r=0; + b->circularBuf[(index*nbAnt+a)%CirSize].i=0; + } + } LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); } b->lastReceivedTS=b->th.timestamp; - AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize), - "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS); + AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize), + "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS); b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); } if ( b->headerMode==false ) { - LOG_D(HW,"Set b->lastReceivedTS %ld\n", b->lastReceivedTS); + LOG_D(HW,"Set b->lastReceivedTS %ld\n", b->lastReceivedTS); b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt); - // First block in UE, resync with the eNB current TS - if ( t->nextTimestamp == 0 ) - t->nextTimestamp=b->lastReceivedTS-b->th.size; - + + // First block in UE, resync with the eNB current TS + if ( t->nextTimestamp == 0 ) + t->nextTimestamp=b->lastReceivedTS-b->th.size; + if ( b->remainToTransfer==0) { LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS); b->headerMode=true; @@ -351,10 +474,10 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { if (nbAnt != 1) { - LOG_E(HW, "rfsimulator: only 1 antenna tested\n"); - exit(1); + LOG_W(HW, "rfsimulator: only 1 antenna tested\n"); } + pthread_mutex_lock(&Sockmutex); rfsimulator_state_t *t = device->priv; LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld\n", nsamps, t->nextTimestamp+nsamps); // deliver data from received data @@ -374,6 +497,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo t->nextTimestamp+=nsamps; LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); *ptimestamp = t->nextTimestamp-nsamps; + pthread_mutex_unlock(&Sockmutex); return nsamps; } } else { @@ -384,11 +508,11 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo for ( int sock=0; sock<FD_SETSIZE; sock++) { if ( t->buf[sock].circularBuf && t->buf[sock].alreadyRead ) - if ( t->buf[sock].lastReceivedTS == 0 || - (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { - have_to_wait=true; - break; - } + if ( t->buf[sock].lastReceivedTS == 0 || + (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { + have_to_wait=true; + break; + } } if (have_to_wait) @@ -404,17 +528,25 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo for (int a=0; a<nbAnt; a++) memset(samplesVoid[a],0,sampleToByte(nsamps,1)); - // Add all input signal in the output buffer + // Add all input nodes signal in the output buffer for (int sock=0; sock<FD_SETSIZE; sock++) { buffer_t *ptr=&t->buf[sock]; if ( ptr->circularBuf && ptr->alreadyRead ) { - for (int a=0; a<nbAnt; a++) { - sample_t *out=(sample_t *)samplesVoid[a]; - - for ( int i=0; i < nsamps; i++ ) - out[i]+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1; - } + bool reGenerateChannel=false; + + //fixme: when do we regenerate + // it seems legacy behavior is: never in UL, each frame in DL + if (reGenerateChannel) + random_channel(ptr->channel_model,0); + + for (int a=0; a<nbAnt; a++) + rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a], + a, + ptr->channel_model, + nsamps, + t->nextTimestamp + ); } } @@ -424,10 +556,9 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo nsamps, *ptimestamp, t->nextTimestamp, signal_energy(samplesVoid[0], nsamps)); + pthread_mutex_unlock(&Sockmutex); return nsamps; } - - int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; @@ -452,12 +583,11 @@ int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cf int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { return 0; } - - __attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { - //set_log(HW,OAILOG_DEBUG); - //set_log(PHY,OAILOG_DEBUG); + // to change the log level, use this on command line + // --log_config.hw_log_level debug + // (for phy layer, replace "hw" by "phy" rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) { @@ -465,12 +595,14 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { exit(1); } + pthread_mutex_init(&Sockmutex, NULL); + if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || strncasecmp(rfsimulator->ip,"server",3) == 0 ) rfsimulator->typeStamp = ENB_MAGICDL_FDD; else rfsimulator->typeStamp = UE_MAGICDL_FDD; - + LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE"); char *saveF; @@ -504,5 +636,12 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->buf[i].conn_sock=-1; AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,""); + // initialize channel simulation + rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels; + rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels; + rfsimulator->sample_rate=openair0_cfg->sample_rate; + rfsimulator->tx_bw=openair0_cfg->tx_bw; + randominit(0); + set_taus_seed(0); return 0; } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index f22abf31120bc2d869343d087de76d08263fc83a..ad88a0b89fe36768df998acfb5056773c762660d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -254,7 +254,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,mgmt_addr=192.168.100.8,clock_source=external,time_source=external"; + sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,mgmt_addr=192.168.10.2,clock_source=external,time_source=external"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf index be98106d1e176417d116e53b7a8ea9efdcc9dd65..8b896fc58ac9adfeb545bd940a2a04f3c0787965 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf @@ -254,7 +254,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - sdr_addrs = "addr=192.168.30.2"; + sdr_addrs = "type=x300"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf index dbd937d61ae8e2acb879f0be109091929b898ce5..06c52e1aff80b34c3197e8e6f9ecfb87c4b88536 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -254,7 +254,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.100.8"; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2"; clock_src = "external"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf index 51910091f7348811048e48bc7e714252562e2cd4..73f2214baf684154dccf9d075de50d0165934f62 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf @@ -254,7 +254,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - sdr_addrs = "addr=192.168.30.2"; + sdr_addrs = "type=x300"; } );