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 d94fe73a7de2e077fe1d221edd66a579fcc9e1e0..3b18c28f874b01a34684c05a1d5e09350b6854a1 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -1,4 +1,3 @@ -# dummy commit #/* # * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more # * contributor license agreements. See the NOTICE file distributed with @@ -337,7 +336,7 @@ class SSHConnection(): self.command('mkdir -p log', '\$', 5) self.command('chmod 777 log', '\$', 5) # no need to remove in log (git clean did the trick) - self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee -a compile_oai_enb.log', 'Bypassing the Tests', 600) + self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee -a compile_oai_enb.log', 'Bypassing the Tests|build have failed', 600) self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) self.command('mv compile_oai_enb.log ' + 'build_log_' + self.testCase_id, '\$', 5) @@ -599,6 +598,10 @@ class SSHConnection(): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': Usage() sys.exit('Insufficient Parameter') + if self.air_interface == 'lte': + UE_prefix = '' + else: + UE_prefix = 'NR ' #initialize_OAI_UE_flag = True #pStatus = self.CheckOAIUEProcessExist(initialize_OAI_UE_flag) #if (pStatus < 0): @@ -608,7 +611,7 @@ class SSHConnection(): self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) # b2xx_fx3_utils reset procedure self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 30) - result = re.search('type: n3xx', str(self.ssh.before)) + result = re.search('type: b200', str(self.ssh.before)) if result is not None: pass logging.debug('Found a B2xx device --> resetting it') @@ -624,10 +627,6 @@ class SSHConnection(): self.command('echo "ulimit -c unlimited && ./'+ self.air_interface +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - #to use daemon on CentOS we need to source the function - #linux_distro = platform.linux_distribution()[0] - #if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE): - #self.command('source /etc/init.d/functions', '\$', 5) #use nohup instead of daemon self.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) #self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) @@ -641,7 +640,7 @@ class SSHConnection(): if (loopCounter == 0): self.close() doLoop = False - logging.error('\u001B[1;37;41m UE logging system did not show got sync! \u001B[0m') + logging.error('\u001B[1;37;41m ' + UE_prefix + 'UE logging system did not show got sync! \u001B[0m') self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') self.CreateHtmlTabFooter(False) sys.exit(1) @@ -656,7 +655,7 @@ class SSHConnection(): else: doLoop = False self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') - logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') + logging.debug('\u001B[1m Initialize OAI ' + UE_prefix + 'UE Completed\u001B[0m') self.close() def InitializeOAIeNB(self): @@ -671,6 +670,10 @@ class SSHConnection(): # sys.exit(1) self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) self.command('cd ' + self.eNBSourceCodePath, '\$', 5) + if self.air_interface == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' # Initialize_OAI_eNB_args usually start with -C and followed by the location in repository #full_config_file = self.Initialize_OAI_eNB_args.replace('-O ','') #extIdx = full_config_file.find('.conf') @@ -697,15 +700,10 @@ class SSHConnection(): # Launch eNB with the modified config file self.command('source oaienv', '\$', 5) self.command('cd cmake_targets/ran_build/build', '\$', 5) - #self.command('echo "ulimit -c unlimited && ./' + self.air_interface + '-softmodem ' + self.Initialize_OAI_eNB_args + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) self.eNBLogFile = 'enb_' + self.testCase_id + '.log' - self.command('echo "ulimit -c unlimited && ./' + self.air_interface + '-softmodem ' + self.Initialize_OAI_eNB_args + '|& tee ' + self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('echo "ulimit -c unlimited && ./' + self.air_interface + '-softmodem ' + self.Initialize_OAI_eNB_args + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) self.command('echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log', '\$', 5) - #to use daemon on CentOS we need to source the function - #linux_distro = platform.linux_distribution()[0] - #if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE): - #self.command('source /etc/init.d/functions', '\$', 5) #use nohup instead of daemon self.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh' + ' > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log' + ' 2>&1 &', self.eNBUserName, 5) #self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets/ran_build/build -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) @@ -713,7 +711,6 @@ class SSHConnection(): self.command('cd ../..', '\$', 5) doLoop = True loopCounter = 10 - print('gNB log file: ' + self.eNBLogFile) while (doLoop): loopCounter = loopCounter - 1 if (loopCounter == 0): @@ -723,7 +720,7 @@ class SSHConnection(): # self.command('killall --signal SIGKILL record', '\$', 5) self.close() doLoop = False - logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') + logging.error('\u001B[1;37;41m ' + nodeB_prefix + 'NB logging system did not show got sync! \u001B[0m') self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'KO', ALL_PROCESSES_OK, 'OAI eNB') self.CreateHtmlTabFooter(False) ## In case of T tracer recording, we need to kill tshark on EPC side @@ -740,18 +737,14 @@ class SSHConnection(): # self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.') sys.exit(1) else: - #print('current directory: ' + os.getcwd()) - #self.command('pwd', '\$', 4) - #print('self.command pwd: ' + str(self.ssh.before)) self.command('stdbuf -o0 cat ' + self.eNBLogFile + ' | egrep --text --color=never -i "wait|sync"', '\$', 30) - #print(self.ssh.before) result = re.search('got sync', str(self.ssh.before)) if result is None: time.sleep(11) else: doLoop = False self.CreateHtmlTestRow(self.Initialize_OAI_eNB_args, 'OK', ALL_PROCESSES_OK, 'OAI eNB') - logging.debug('\u001B[1m Initialize OAI eNB Completed\u001B[0m') + logging.debug('\u001B[1m Initialize OAI ' + nodeB_prefix + 'NB Completed\u001B[0m') self.close() def checkDevTTYisUnlocked(self): @@ -2091,38 +2084,42 @@ class SSHConnection(): rachCanceledProcedure += 1 enb_log_file.close() self.htmleNBFailureMsg = '' + if self.air_interface == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' if uciStatMsgCount > 0: - statMsg = 'eNB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') self.htmleNBFailureMsg += statMsg + '\n' if pdcpFailure > 0: - statMsg = 'eNB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' + statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') self.htmleNBFailureMsg += statMsg + '\n' if ulschFailure > 0: - statMsg = 'eNB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)' + statMsg = nodeB_prefix + 'NB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') self.htmleNBFailureMsg += statMsg + '\n' if rrcSetupRequest > 0 or rrcSetupComplete > 0: - rrcMsg = 'eNB requested ' + str(rrcSetupRequest) + ' RRC Connection Setup(s)' + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcSetupRequest) + ' RRC Connection Setup(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' if rrcReleaseRequest > 0: - rrcMsg = 'eNB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: - rrcMsg = 'eNB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: - rrcMsg = 'eNB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' @@ -2132,22 +2129,22 @@ class SSHConnection(): logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' if rachCanceledProcedure > 0: - rachMsg = 'eNB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' + rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') self.htmleNBFailureMsg += rachMsg + '\n' if foundSegFault: - logging.debug('\u001B[1;37;41m eNB ended with a Segmentation Fault! \u001B[0m') + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') return ENB_PROCESS_SEG_FAULT if foundAssertion: - logging.debug('\u001B[1;37;41m eNB ended with an assertion! \u001B[0m') + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') self.htmleNBFailureMsg += msgAssertion return ENB_PROCESS_ASSERTION if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m eNB faced real time issues! \u001B[0m') - self.htmleNBFailureMsg += 'eNB faced real time issues!\n' + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') + self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' #return ENB_PROCESS_REALTIME_ISSUE if rlcDiscardBuffer > 0: - rlcMsg = 'eNB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' + rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rlcMsg + '\n' return ENB_PROCESS_REALTIME_ISSUE @@ -2170,8 +2167,25 @@ class SSHConnection(): no_cell_sync_found = False mib_found = False frequency_found = False + nrUEFlag = False + nrDecodeMib = 0 + nrFoundDCI = 0 + nrCRCOK = 0 self.htmlUEFailureMsg = '' for line in ue_log_file.readlines(): + result = re.search('nr_synchro_time', str(line)) + if result is not None: + nrUEFlag = True + if nrUEFlag: + result = re.search('decode mib', str(line)) + if result is not None: + nrDecodeMib += 1 + result = re.search('found 1 DCIs', str(line)) + if result is not None: + nrFoundDCI += 1 + result = re.search('CRC OK', str(line)) + if result is not None: + nrCRCOK += 1 result = re.search('[Ss]egmentation [Ff]ault', str(line)) if result is not None: foundSegFault = True @@ -2262,6 +2276,19 @@ class SSHConnection(): except Exception as e: logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') ue_log_file.close() + if nrUEFlag: + if nrDecodeMib > 0: + statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if nrFoundDCI > 0: + statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if nrCRCOK > 0: + statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' if uciStatMsgCount > 0: statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') @@ -2306,10 +2333,10 @@ class SSHConnection(): def TerminateeNB(self): self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - #to use daemon on CentOS we need to source the function - #linux_distro = platform.linux_distribution()[0] - #if re.match('(.*)CentOS(.*)', linux_distro, re.IGNORECASE): - #self.command('source /etc/init.d/functions', '\$', 5) + if self.air_interface == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' #use nohup instead of daemon self.command('echo ' + self.eNBPassword + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) @@ -2354,12 +2381,12 @@ class SSHConnection(): if result is not None: copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile, '.') if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m') - self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!' + logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') + self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBLogFile = '' return - logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m') + logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m') logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFile) if (logStatus < 0): self.CreateHtmlTestRow('N/A', 'KO', logStatus) @@ -2485,16 +2512,16 @@ class SSHConnection(): optionsMsg += self.htmlUEFailureMsg optionsMsg += '</pre>' self.CreateHtmlTestRow(optionsMsg, 'KO', logStatus, 'UE') - self.CreateHtmlTabFooter(False) - sys.exit(1) + # for NR-UE at the moment keep running + if self.air_interface == 'lte': + self.CreateHtmlTabFooter(False) + sys.exit(1) else: optionsMsg = '<pre style="background-color:white"><b>Sniffing Successful</b>\n' optionsMsg += self.htmlUEFailureMsg optionsMsg += '</pre>' self.CreateHtmlTestRow(optionsMsg, 'OK', ALL_PROCESSES_OK) self.UELogFile = '' - else: - self.CreateHtmlTestRow('<pre style="background-color:white">No Log File to analyze</pre>', 'OK', ALL_PROCESSES_OK) def AutoTerminateUEandeNB(self): self.testCase_id = 'AUTO-KILL-UE' @@ -2638,6 +2665,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: @@ -2648,11 +2686,23 @@ class SSHConnection(): if result is not None: self.UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + self.UhdVersion) + 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) - 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) + 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: @@ -2795,9 +2845,7 @@ class SSHConnection(): self.GetAllUEDevices(terminate_ue_flag) self.GetAllCatMDevices(terminate_ue_flag) else: - self.UEDevices.append('doughq9rehg') - self.UEDevices.append('dnsgiuahgia') - self.UEDevices.append('uehgieng9') + self.UEDevices.append('OAI-UE') self.htmlUEConnected = len(self.UEDevices) i = 0 @@ -2840,7 +2888,7 @@ class SSHConnection(): self.htmlFile.write(' <td><span class="label label-default">' + self.KernelVersion + '</span></td>\n') self.htmlFile.write(' <td>UHD Version</td>\n') self.htmlFile.write(' <td><span class="label label-default">' + self.UhdVersion + '</span></td>\n') - self.htmlFile.write(' <td>USRP Board</td>\n') + self.htmlFile.write(' <td>USRP Board(s)</td>\n') self.htmlFile.write(' <td><span class="label label-default">' + self.UsrpBoard + '</span></td>\n') self.htmlFile.write(' </tr>\n') self.htmlFile.write(' <tr>\n') @@ -3317,7 +3365,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': Usage() sys.exit('Insufficient Parameter') - if (SSH.EPCIPAddress != ''): + if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") else: diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool index f5ede896a78d244e18012732a8ef3cbcf37c5b00..b21dde721489119c33d7a9d502cdbf496b346de9 100755 --- a/ci-scripts/oai-ci-vm-tool +++ b/ci-scripts/oai-ci-vm-tool @@ -252,7 +252,7 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=11 + NB_PATTERN_FILES=12 BUILD_OPTIONS="--phy_simulators" VM_MEMORY=8192 RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b" @@ -331,7 +331,7 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=11 + 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 d523c25baa282397d44e68b147451e931ddf3177..889ac5747544df0bfba49027db4b163db0f166ba 100755 --- a/ci-scripts/reportBuildLocally.sh +++ b/ci-scripts/reportBuildLocally.sh @@ -396,24 +396,44 @@ function report_build { summary_table_footer summary_table_header "OAI Build Physical simulators option" - 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_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_row4.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_row5.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_row6.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_row7.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 "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 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/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index f9d068c5b2e377fd369d0047b399d5775b1d13a5..12d06ac45618c5292e6bcd3ed5f7b510085afb5b 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -25,7 +25,7 @@ <htmlTabName>run OAI gNB and OAI NR UE USRP</htmlTabName> <htmlTabIcon>tasks</htmlTabIcon> <TestCaseRequestedList> -090101 000001 090102 000001 090108 090109 +090101 000001 090102 000002 090108 090109 </TestCaseRequestedList> <TestCaseExclusionList></TestCaseExclusionList> @@ -42,6 +42,12 @@ <idle_sleep_time_in_sec>5</idle_sleep_time_in_sec> </testCase> + <testCase id="000002"> + <class>IdleSleep</class> + <desc>Waiting for NR UE to synchronize w/ gNB</desc> + <idle_sleep_time_in_sec>180</idle_sleep_time_in_sec> + </testCase> + <testCase id="090102"> <class>Initialize_OAI_UE</class> <desc>Initialize NR UE USRP</desc> diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 77ea3963b4545ba5be934ead0d09fefbeb8bc6f2..34bf2af293378eee32bcff1d57cb29bbe26ff366 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -619,8 +619,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") @@ -1220,6 +1218,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 @@ -1278,6 +1277,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 @@ -1287,9 +1287,12 @@ 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_prach.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 @@ -1306,12 +1309,13 @@ set(PHY_SRC_UE ${PHY_POLARSRC} ${PHY_SMALLBLOCKSRC} ${PHY_LDPCSRC} - ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c # added by prasanth + ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c ) 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 @@ -1324,12 +1328,14 @@ set(PHY_SRC_UE ${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_prach_common.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 @@ -2136,6 +2142,12 @@ add_library(gnbScope MODULE ) target_link_libraries(gnbScope forms) +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 @@ -2603,6 +2615,13 @@ add_executable(nr_ulschsim ${T_SOURCE}) target_link_libraries(nr_ulschsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_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 + ${OPENAIR_DIR}/common/utils/nr/nr_common.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/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 792e46cec630622fd3ebdb926487b862a5e9ce97..f5cb0ae1834a23eae7a8e0315f5c8c9f1ce17860 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1160,6 +1160,29 @@ <nruns>3</nruns> </testCase> + <testCase id="015109"> + <class>execution</class> + <desc>nr_nr_pucchsim Test cases. (Test1: Format 0 ACK miss 106 PRB), + (Test2: Format 1 ACK miss 106 PRB), + (Test3: Format 1 ACK miss 273 PRB), + (Test4: Format 1 NACKtoACK 106 PRB)</desc> + <pre_compile_prog></pre_compile_prog> + <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog> + <compile_prog_args> --phy_simulators -c </compile_prog_args> + <pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash</pre_exec> + <pre_exec_args></pre_exec_args> + <main_exec> $OPENAIR_DIR/targets/bin/nr_pucchsim.Rel15</main_exec> + <main_exec_args>-R 106 -i 1 -P 0 -b 1 -s3 -n100 + -R 106 -i 14 -P 1 -b 1 -s-6 -n 100 + -R 273 -i 14 -P 1 -b 1 -s-6 -n100 + -R 106 -i 14 -P 1 -b 1 -s-6 -T 0.001 -n1000</main_exec_args> + <tags>nr_pucchsim.test1 nr_pucchsim.test2 nr_pucchsim.test3 nr_pucchsim.test4</tags> + <search_expr_true>PUCCH test OK</search_expr_true> + <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false> + <nruns>3</nruns> + </testCase> + + <testCase id="015110"> <class>execution</class> <desc>dlsim_tm4 test cases (Test 1: 10 MHz, R2.FDD (MCS 5), EVA5, -1dB), diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 355bf090f3efffeed33a9b548f9045e6d53450ff..f37aad4f8a267a71b77b1bf2d9c942e22f1037f2 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -684,7 +684,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_prachsim nr_pucchsim dlsim ulsim polartest ldpctest smallblocktest nr_pbchsim nr_dlschsim nr_dlsim nr_ulschsim " + simlist="nr_prachsim 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 12971c3761ba9e7ca11a05877e4d227a4b9ebd2f..884e296c721dd783b116d45e44677b16d7e6f725 100644 --- a/common/utils/LOG/vcd_signal_dumper.c +++ b/common/utils/LOG/vcd_signal_dumper.c @@ -313,6 +313,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 7b439d4dd5555a131f5d3cc85dafb915a18fa9f9..d437880c1b5bd379bf33283e3a41a71378f85882 100644 --- a/common/utils/LOG/vcd_signal_dumper.h +++ b/common/utils/LOG/vcd_signal_dumper.h @@ -292,6 +292,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 5300237178115a3e46147bf9a758c24700b3a4c9..f7ec8dfbe7f941ff717a1bb06ec2a63900cbeb58 100644 --- a/common/utils/T/T_defs.h +++ b/common/utils/T/T_defs.h @@ -41,7 +41,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//190 +#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 136//128 diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 10dc5fb07cccb3db8b1806749bf38b4a3e6faad5..c5aae75826aea55e2b35592d8a27162694948667 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -2249,6 +2249,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 new file mode 100644 index 0000000000000000000000000000000000000000..5742118c7ae8a369f75a939c508175626bb0803d --- /dev/null +++ b/doc/FEATURE_SET.md @@ -0,0 +1,255 @@ +**Table of Contents** + +1. [OpenAirInterface eNB Feature Set](#openairinterface-enb-feature-set) + 1. [eNB PHY Layer](#enb-phy-layer) + 2. [eNB MAC Layer](#enb-mac-layer) + 3. [eNB RLC Layer](#enb-rlc-layer) + 4. [eNB PDCP Layer](#enb-pdcp-layer) + 5. [eNB RRC Layer](#enb-rrc-layer) + 6. [eNB X2AP](#enb-x2ap) + 7. [eNB Advanced Features](#enb-advanced-features) +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 # + +## eNB PHY Layer ## + +The Physical layer implements **3GPP 36.211**, **36.212**, **36.213** and provides the following features: + +- LTE release 8.6 compliant, and implements a subset of release 10 +- FDD and TDD configurations: 1 (experimental) and 3 +- Bandwidth: 5, 10, and 20 MHz +- Transmission modes: 1, 2 (stable), 3, 4, 5, 6, 7 (experimental) +- Max number of antennas: 2 +- CQI/PMI reporting: aperiodic, feedback mode 3 - 0 and 3 - 1 +- PRACH preamble format 0 +- All downlink (DL) channels are supported: PSS, SSS, PBCH, PCFICH, PHICH, PDCCH, PDSCH, PMCH +- All uplink (UL) channels are supported: PRACH, PUSCH, PUCCH (format 1/1a/1b), SRS, DRS +- HARQ support (UL and DL) +- Highly optimized base band processing (including turbo decoder) + +### Performances ### + +**Transmission Mode, Bandwidth** | **Expected Throughput** | **Measured Throughput** | **Measurement Conditions** +-------------------------------- | ----------------------- | ------------------------| ----------------: +FDD DL: 5 MHz, 25 PRBS/ MCS 28 | 16 - 17 Mbit/s | TM1: 17.0 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +FDD DL: 10 MHz, 50 PRBS/ MCS 28 | 34 - 35 Mbit/s | TM1: 32.8 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +FDD DL: 20 MHz, 100 PRBS/ MCS 28 | 70 Mbit/s | TM1: 69.9 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) + | | | +FDD UL: 5 MHz, 25 PRBS/ MCS 20 | 9 Mbit/s | TM1: 8.28 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +FDD UL: 10 MHz, 50 PRBS/ MCS 20 | 17 Mbit/s | TM1: 15.2 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +FDD UL: 20 MHz, 100 PRBS/ MCS 20 | 35 Mbit/s | TM1: 18.6 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) + | | +TDD DL: 5 MHz, 25 PRBS/ MCS **XX** | **TBC** Mbit/s | 3.33 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +TDD DL: 10 MHz, 50 PRBS/ MCS **XX** | **TBC** Mbit/s | 8.90 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +TDD DL: 20 MHz, 100 PRBS/ MCS **XX** | **TBC** Mbit/s | N/A | COTS-UE Cat 4 (150/50 Mbps) + | | | +TDD UL: 5 MHz, 25 PRBS/ MCS **XX** | **TBC** Mbit/s | 1.66 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +TDD UL: 10 MHz, 50 PRBS/ MCS **XX** | **TBC** Mbit/s | 1.89 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) +TDD UL: 20 MHz, 100 PRBS/ MCS **XX** | **TBC** Mbit/s | N/A | COTS-UE Cat 4 (150/50 Mbps) + +- Number of supported UEs: **To Be Completed** + +## eNB MAC Layer ## + +The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support of BCH, DLSCH, RACH, and ULSCH channels. + +- RRC interface for CCCH, DCCH, and DTCH +- Proportional fair scheduler (round robin scheduler soon) +- DCI generation +- HARQ Support +- RA procedures and RNTI management +- RLC interface (AM, UM) +- UL power control +- Link adaptation + +## eNB RLC Layer ## + +The RLC layer implements a full specification of the 3GPP 36.322 release v9.3. + +- RLC TM (mainly used for BCCH and CCCH) + * Neither segment nor concatenate RLC SDUs + * Do not include a RLC header in the RLC PDU + * Delivery of received RLC PDUs to upper layers +- RLC UM (mainly used for DTCH) + * Segment or concatenate RLC SDUs according to the TB size selected by MAC + * Include a RLC header in the RLC PDU + * Duplication detection + * PDU reordering and reassembly +- RLC AM, compatible with 9.3 + * Segmentation, re-segmentation, concatenation, and reassembly + * Padding + * Data transfer to the user + * RLC PDU retransmission in support of error control and correction + * Generation of data/control PDUs + +## eNB PDCP Layer ## + +The current PDCP layer is header compliant with **3GPP 36.323** Rel 10.1.0 and implements the following functions: + +- User and control data transfer +- Sequence number management +- RB association with PDCP entity +- PDCP entity association with one or two RLC entities +- Integrity check and encryption using the AES and Snow3G algorithms + +## eNB RRC Layer ## + +The RRC layer is based on **3GPP 36.331** v14.3.0 and implements the following functions: + +- System Information broadcast (SIB 1, 2, 3, and 13) + * SIB1: Up to 6 PLMN IDs broadcast +- RRC connection establishment +- RRC connection reconfiguration (addition and removal of radio bearers, connection release) +- RRC connection release +- RRC connection re-establishment +- Inter-frequency measurement collection and reporting (experimental) +- eMBMS for multicast and broadcast (experimental) +- Handover (experimental) +- Paging (soon) + +## eNB X2AP ## + +The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following functions: + + - X2 Setup Request + - X2 Setup Response + +## eNB Advanced Features ## + +**To be completed** + +# OpenAirInterface UE Feature Set # + +## LTE UE PHY Layer ## + +The Physical layer implements **3GPP 36.211**, **36.212**, **36.213** and provides the following features: + +- LTE release 8.6 compliant, and implements a subset of release 10 +- FDD and TDD configurations: 1 (experimental) and 3 +- Bandwidth: 5, 10, and 20 MHz +- Transmission modes: 1, 2 (stable) +- Max number of antennas: 2 +- CQI/PMI reporting: aperiodic, feedback mode 3 - 0 and 3 - 1 +- PRACH preamble format 0 +- All downlink (DL) channels are supported: PSS, SSS, PBCH, PCFICH, PHICH, PDCCH, PDSCH, PMCH +- All uplink (UL) channels are supported: PRACH, PUSCH, PUCCH (format 1/1a/1b), SRS, DRS + +## LTE UE MAC Layer ## + +The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support of BCH, DLSCH, RACH, and ULSCH channels. + +- RRC interface for CCCH, DCCH, and DTCH +- HARQ Support +- RA procedures and RNTI management +- RLC interface (AM, UM) +- UL power control +- Link adaptation + +## LTE UE RLC Layer ## + +The RLC layer implements a full specification of the 3GPP 36.322 release v9.3. + +## LTE UE PDCP Layer ## + +The current PDCP layer is header compliant with **3GPP 36.323** Rel 10.1.0. + +## LTE UE RRC Layer ## + +The RRC layer is based on **3GPP 36.331** v14.3.0 and implements the following functions: + +- System Information decoding +- RRC connection establishment + +# 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) + + 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 745cc03565426385fcd856603b8865e0e93996ff..81955a683352820690417d4ed8e8c1d337228358 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -415,9 +415,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; @@ -489,10 +486,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); @@ -529,7 +522,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++) { @@ -551,9 +543,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 93166ef5ff13a12a64c5001c37fe83b647186d3b..5ff6236984e669b0fece955e1c4c395f08363d15 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1067,10 +1067,18 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->rx_bw = 40e6; } } else if(N_RB == 106) { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 20e6; - cfg->rx_bw = 20e6; + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } } else { AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } @@ -1203,6 +1211,13 @@ static void *ru_thread_tx( void *param ) { wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); printf( "ru_thread_tx ready\n"); + + if(ru->rfdevice.uhd_set_thread_priority != NULL) + { + LOG_I(PHY,"set ru_thread_tx uhd priority \n"); + ru->rfdevice.uhd_set_thread_priority(); + } + while (!oai_exit) { if (oai_exit) break; diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h new file mode 100644 index 0000000000000000000000000000000000000000..3f27a48168fd659b1602333a79f12d1bfdc5ed18 --- /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 361f23204624fe4ff3ac0f3d736bc5a684025bc7..b21aa2e60413cf2d8d1027876d26584e920d0dda 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -139,6 +139,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 b01d92e6edd5ef10cb0a766a09df74a1e42fb42a..588bcce118952b7afab6b0d11be0036c50f85d15 100644 --- a/executables/nr-softmodem.h +++ b/executables/nr-softmodem.h @@ -1,93 +1,11 @@ #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 - -/* 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 @@ -98,25 +16,6 @@ /* 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 @@ -150,27 +49,10 @@ {"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 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 typedef struct { @@ -183,33 +65,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; diff --git a/executables/nr-ue.c b/executables/nr-ue.c index ab3b6cd7e04e9291a02d883e3f76d349a4012f2b..d28ae117a143dc4624450603416596114bc7de15 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -350,39 +350,42 @@ static void UE_synch(void *arg) { } void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { + + nr_dcireq_t dcireq; + nr_scheduled_response_t scheduled_response; + // Process Rx data for one sub-frame - if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_DOWNLINK_SLOT) { - //clean previous FAPI MESSAGE - UE->rx_ind.number_pdus = 0; - UE->dci_ind.number_of_dcis = 0; - //clean previous FAPI MESSAGE - // call L2 for DL_CONFIG (DCI) - UE->dcireq.module_id = UE->Mod_id; - UE->dcireq.gNB_index = 0; - UE->dcireq.cc_id = 0; - UE->dcireq.frame = proc->frame_rx; - UE->dcireq.slot = proc->nr_tti_rx; - nr_ue_dcireq(&UE->dcireq); //to be replaced with function pointer later - NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); - UE_mac->scheduled_response.dl_config = &UE->dcireq.dl_config_req; - UE_mac->scheduled_response.ul_config = NULL; - UE_mac->scheduled_response.tx_request = NULL; - UE_mac->scheduled_response.module_id = UE->Mod_id; - UE_mac->scheduled_response.CC_id = 0; - UE_mac->scheduled_response.frame = proc->frame_rx; - UE_mac->scheduled_response.slot = proc->nr_tti_rx; - nr_ue_scheduled_response(&UE_mac->scheduled_response); - //write_output("uerxdata_frame.m", "uerxdata_frame", UE->common_vars.rxdata[0], UE->frame_parms.samples_per_frame, 1, 1); + if (nr_slot_select(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_DOWNLINK_SLOT) { + //TODO: all of this has to be moved to the MAC!!! + dcireq.module_id = UE->Mod_id; + dcireq.gNB_index = 0; + dcireq.cc_id = 0; + dcireq.frame = proc->frame_rx; + dcireq.slot = proc->nr_tti_rx; + nr_ue_dcireq(&dcireq); //to be replaced with function pointer later + + scheduled_response.dl_config = &dcireq.dl_config_req; + scheduled_response.ul_config = NULL; + scheduled_response.tx_request = NULL; + scheduled_response.module_id = UE->Mod_id; + scheduled_response.CC_id = 0; + scheduled_response.frame = proc->frame_rx; + scheduled_response.slot = proc->nr_tti_rx; + nr_ue_scheduled_response(&scheduled_response); + #ifdef UE_SLOT_PARALLELISATION phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); #else uint64_t a=rdtsc(); - phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode, UE_mac->scheduled_response.dl_config); + phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode, scheduled_response.dl_config); LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500); //printf(">>> nr_ue_pdcch_procedures ended\n"); #endif } + + // no UL for now + /* if (UE->mac_enabled==1) { // trigger L2 to run ue_scheduler thru IF module // [TODO] mapping right after NR initial sync @@ -395,6 +398,7 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { UE->if_inst->ul_indication(&UE->ul_indication); } } + */ } /*! @@ -627,8 +631,9 @@ void *UE_thread(void *arg) { processingData_t *curMsg=(processingData_t *)NotifiedFifoData(msgToPush); curMsg->UE=UE; // update thread index for received subframe - curMsg->proc.nr_tti_rx= slot_nr; curMsg->UE->current_thread_id[slot_nr] = thread_idx; + curMsg->proc.CC_id = 0; + curMsg->proc.nr_tti_rx= slot_nr; curMsg->proc.subframe_rx=table_sf_slot[slot_nr]; curMsg->proc.nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame; curMsg->proc.subframe_tx=curMsg->proc.nr_tti_rx; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index c8143879b1c492ae92ac1ac2b580f1b030361dc4..98d8fc88e63af7809441a7989c6065c97fb57e11 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; @@ -540,8 +542,27 @@ void init_openair0(void) { for (card=0; card<MAX_CARDS; card++) { openair0_cfg[card].configFilename = NULL; + openair0_cfg[card].threequarter_fs = frame_parms[0]->threequarter_fs; - if(frame_parms[0]->N_RB_DL == 106) { + if(frame_parms[0]->N_RB_DL == 217) { + if (numerology==1) { + if (frame_parms[0]->threequarter_fs) { + openair0_cfg[card].sample_rate=92.16e6; + openair0_cfg[card].samples_per_frame = 921600; + openair0_cfg[card].tx_bw = 40e6; + openair0_cfg[card].rx_bw = 40e6; + } + else { + openair0_cfg[card].sample_rate=122.88e6; + openair0_cfg[card].samples_per_frame = 1228800; + openair0_cfg[card].tx_bw = 40e6; + openair0_cfg[card].rx_bw = 40e6; + } + } else { + LOG_E(PHY,"Unsupported numerology!\n"); + exit(-1); + } + }else if(frame_parms[0]->N_RB_DL == 106) { if (numerology==0) { if (frame_parms[0]->threequarter_fs) { openair0_cfg[card].sample_rate=23.04e6; @@ -554,14 +575,22 @@ void init_openair0(void) { openair0_cfg[card].tx_bw = 10e6; openair0_cfg[card].rx_bw = 10e6; } - } else if (numerology==1) { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 307200; - openair0_cfg[card].tx_bw = 20e6; - openair0_cfg[card].rx_bw = 20e6; + } else if (numerology==1) { + if (frame_parms[0]->threequarter_fs) { + openair0_cfg[card].sample_rate=46.08e6; + openair0_cfg[card].samples_per_frame = 480800; + openair0_cfg[card].tx_bw = 20e6; + openair0_cfg[card].rx_bw = 20e6; + } + else { + openair0_cfg[card].sample_rate=61.44e6; + openair0_cfg[card].samples_per_frame = 614400; + openair0_cfg[card].tx_bw = 20e6; + openair0_cfg[card].rx_bw = 20e6; + } } else if (numerology==2) { openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 307200; + openair0_cfg[card].samples_per_frame = 1228800; openair0_cfg[card].tx_bw = 40e6; openair0_cfg[card].rx_bw = 40e6; } else { @@ -584,6 +613,10 @@ void init_openair0(void) { openair0_cfg[card].tx_bw = 1.5e6; openair0_cfg[card].rx_bw = 1.5e6; } + else { + LOG_E(PHY,"Unknown NB_RB %d!\n",frame_parms[0]->N_RB_DL); + exit(-1); + } if (frame_parms[0]->frame_type==TDD) openair0_cfg[card].duplex_mode = duplex_mode_TDD; @@ -696,6 +729,7 @@ int main( int argc, char **argv ) { frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx; frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx; frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later + frame_parms[CC_id]->threequarter_fs = threequarter_fs; LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx); get_band(downlink_frequency[CC_id][0], &frame_parms[CC_id]->eutra_band, &uplink_frequency_offset[CC_id][0], &frame_parms[CC_id]->frame_type); } diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 4d45e08722efbfcb9563f0c31dad473919527a1d..a68bcf2d50b5de50e556de0164023efb20fcfc22 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 */ @@ -174,27 +84,10 @@ {"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 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 extern int T_port; @@ -203,35 +96,6 @@ 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_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg); extern void fill_ue_band_info(void); diff --git a/maketags b/maketags index eb7c474a38b3ce208a97cda0c6fdae41443af086..5c7232320a0abea10d81e4484aeffbdd2eccd623 100755 --- a/maketags +++ b/maketags @@ -1,4 +1,4 @@ #!/bin/sh echo "building ctags for openair1 and openair2 ..." -ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi +ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi executables 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 834f9a5b5a9d75467b27b14c8b177bb4d25d12e0..d41afdadd6860aa847da5b9a7092affbe5caaa68 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -711,12 +711,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 2d0661728e945ec31d88f681531e07bde995d4aa..15f739046e1e980d10cc5d284db669462f13a611 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -72,10 +72,10 @@ 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_PRACH *const prach_vars = &gNB->prach_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; @@ -149,12 +149,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], @@ -188,39 +190,38 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, prach_vars->rxsigF = (int16_t *)malloc16_clear( 1024*2*sizeof(int16_t) ); prach_vars->prach_ifft = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t)); -/* + for (int ulsch_id=0; ulsch_id<NUMBER_OF_NR_ULSCH_MAX; ulsch_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]->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 *) ); + //FIXME + pusch_vars[ulsch_id] = (NR_gNB_PUSCH *)malloc16_clear( sizeof(NR_gNB_PUSCH) ); + pusch_vars[ulsch_id]->rxdataF_ext = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[ulsch_id]->rxdataF_ext2 = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[ulsch_id]->drs_ch_estimates = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[ulsch_id]->drs_ch_estimates_time = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[ulsch_id]->rxdataF_comp = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[ulsch_id]->ul_ch_mag = (int32_t **)malloc16( 2*sizeof(int32_t *) ); + pusch_vars[ulsch_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]->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[ulsch_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[ulsch_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[ulsch_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[ulsch_id]->drs_ch_estimates_time[i] = (int32_t *)malloc16_clear( 2*sizeof(int32_t)*fp->ofdm_symbol_size ); + pusch_vars[ulsch_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[ulsch_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[ulsch_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) ); - } //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 + pusch_vars[ulsch_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 + } //ulsch_id +/* + for (ulsch_id=0; ulsch_id<NUMBER_OF_UE_MAX; ulsch_id++) + gNB->UE_stats_ptr[ulsch_id] = &gNB->UE_stats[ulsch_id]; */ + gNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration return (0); } /* @@ -271,8 +272,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; @@ -442,13 +443,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); }*/ + } + } + + for (i=0; i<NUMBER_OF_NR_UE_MAX; i++) { - ///////////////////////// Initializing gNB ULSCH ///////////////////////// - LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",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"); @@ -457,7 +462,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"); @@ -473,7 +478,7 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { 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; //fp->pucch_config_common.deltaPUCCH_Shift = 1; diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 6ad844b99b8d4ce793f6a0b29172a6063b70613f..35e02dacf400447c9cf153b6cc0289ffa8237eb6 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -36,7 +36,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}; @@ -644,6 +645,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) @@ -655,18 +669,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; @@ -698,6 +716,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; @@ -711,7 +782,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 @@ -723,7 +794,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) ); } } } @@ -895,6 +966,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..c00fef592994b2b0065e534ea359889905769d82 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" @@ -88,6 +89,10 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, dft = dft2048; break; + case 3072: + dft = dft3072; + break; + case 4096: dft = dft4096; break; @@ -97,8 +102,8 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, break; default: - dft = dft512; - break; + printf("unsupported ofdm symbol size \n"); + assert(0); } if (no_prefix) { @@ -198,3 +203,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 47665814e7a8fcc2a680f6b3970944bc5894e99b..278b0613767fe0f423339fc301ceeb62f4a4ce19 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, @@ -218,9 +218,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 @@ -265,7 +265,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 f04345f3b1beac130b4bbc6affc61da2d625ea97..5567e1f95ffe386f7aea2e65487fbb4d9873e5f6 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); @@ -291,12 +167,16 @@ for (int l=0; l<rel15->nb_layers; l++) //to be moved to init phase potentially, for now tx_layers 1-8 are mapped on antenna ports 1000-1007 /// DMRS QPSK modulation + int nb_re_dmrs = rel15->dmrs_Type==1?6:4; uint16_t n_dmrs = (rel15->n_prb*nb_re_dmrs)<<1; int16_t mod_dmrs[n_dmrs<<1]; uint8_t dmrs_type = rel15->dmrs_Type; - 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 mapping_type = rel15->mapping_type; + + 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++) { @@ -307,13 +187,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", @@ -338,13 +218,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++; @@ -354,17 +234,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 580a10a27aa63d34e8b449f7b892bceda5bcee6b..50738c2c82697c3e71674a3e83c686d6878f203a 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,6 +53,7 @@ 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); @@ -63,42 +65,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); @@ -116,3 +97,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 7cfdaea0e19384a516b9edb911de2f2ef25ae618..54ef276a7390d442ec40ebc5b9eed95b5a5abaf3 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_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index ead8e3cda5757eea1ee3cb71fc54b32af3f88a51..bb114fa3900c6017b1caf00d3f30f7c33bc8b194 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -239,7 +239,7 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, uint8_t nushift; uint32_t unscrambling_mask; uint64_t a_reversed=0; - LOG_I(PHY, "PBCH generation started\n"); + LOG_D(PHY, "PBCH generation started\n"); ///Payload generation memset((void *)pbch, 0, sizeof(NR_gNB_PBCH)); pbch->pbch_a=0; @@ -267,7 +267,7 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, else pbch->pbch_a |= ((config->sch_config.ssb_subcarrier_offset.value>>4)&1)<<29; //MSB of k_SSB (bit index 4) - LOG_I(PHY,"After extra byte: pbch_a = 0x%08x\n",pbch->pbch_a); + LOG_D(PHY,"After extra byte: pbch_a = 0x%08x\n",pbch->pbch_a); // Payload interleaving 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 7c36ad0d55f3bc1a6bc7ac0ccd3888d87084b8ff..6060a046586c3f3938a8855b7398bb1f3613c7ba 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" static inline uint8_t is_codeword_disabled(uint8_t format, uint8_t Imcs, uint8_t rv) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index 5d859e71f5394dab2d2bdc7649514690ff003643..018e36ce4ecef8fe7672d2a8076f14e1a44e9789 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_transport_proto_common.h -* \brief Prototypes of functions common to gNB and NR UE +/*! \file PHY/NR_TRANSPORT/nr_transport_common_proto.h +* \brief Some support routines * \author * \date 2019 * \version 0.1 @@ -34,16 +34,26 @@ #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 -// Functions below implement minor procedures from 38-214 -/** \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); +#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 PUSCH. Implements Table 6.1.4.1-1 from 38.214. - @param I_MCS */ -uint8_t get_nr_Qm_ul(uint8_t I_MCS); +/** \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); + +/** \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); + +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_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 3513c198cbc87325556560cea23beffc1c9d3687..b74b078dfd6ffcd63faa97b59314335405e0f546 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -21,7 +21,7 @@ void nr_decode_pucch0( int32_t **rxdataF, pucch_GroupHopping_t pucch_GroupHopping, uint32_t n_id, // hoppingID higher layer parameter - uint8_t *payload, + uint64_t *payload, NR_DL_FRAME_PARMS *frame_parms, int16_t amp, int nr_tti_tx, @@ -86,7 +86,7 @@ void nr_decode_pucch0( int32_t **rxdataF, // if ((PUCCH_Frequency_Hopping == 1)&&(l == (nrofSymbols-1))) n_hop = 1; nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v); // calculating u and v value alpha = nr_cyclic_shift_hopping(n_id,m0,mcs[i],l,startingSymbolIndex,nr_tti_tx); - #ifdef DEBUG_NR_PUCCH_TX + #ifdef DEBUG_NR_PUCCH_RX printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u,v,alpha,l); #endif for (n=0; n<12; n++){ @@ -94,7 +94,7 @@ void nr_decode_pucch0( int32_t **rxdataF, - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)))>>15); // Re part of base sequence shifted by alpha x_n_im[i][(12*l)+n] =(int16_t)((int32_t)(amp)* (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)))>>15); // Im part of base sequence shifted by alpha - #ifdef DEBUG_NR_PUCCH_TX + #ifdef DEBUG_NR_PUCCH_RX printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n", u,v,alpha,l,n,x_n_re[(12*l)+n],x_n_im[(12*l)+n]); #endif @@ -129,7 +129,7 @@ void nr_decode_pucch0( int32_t **rxdataF, } r_re[(12*l)+n]=((int16_t *)&rxdataF[0][re_offset])[0]; r_im[(12*l)+n]=((int16_t *)&rxdataF[0][re_offset])[1]; - #ifdef DEBUG_NR_PUCCH_TX + #ifdef DEBUG_NR_PUCCH_RX printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,re_offset, l,n,((int16_t *)&rxdataF[0][re_offset])[0],((int16_t *)&rxdataF[0][re_offset])[1]); @@ -158,6 +158,486 @@ void nr_decode_pucch0( int32_t **rxdataF, max_corr=corr[i]; } } - *payload=(uint8_t)index; // payload bits 00..b3b2b0, b0 is the SR bit and b3b2 are HARQ bits + *payload=(uint64_t)index; // payload bits 00..b3b2b0, b0 is the SR bit and b3b2 are HARQ bits +} + + + + + +void nr_decode_pucch1( int32_t **rxdataF, + pucch_GroupHopping_t pucch_GroupHopping, + uint32_t n_id, // hoppingID higher layer parameter + uint64_t *payload, + NR_DL_FRAME_PARMS *frame_parms, + int16_t amp, + int nr_tti_tx, + uint8_t m0, + uint8_t nrofSymbols, + uint8_t startingSymbolIndex, + uint16_t startingPRB, + uint16_t startingPRB_intraSlotHopping, + uint8_t timeDomainOCC, + uint8_t nr_bit) { +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%d m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", + nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); +#endif + /* + * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation + * + */ + // complex-valued symbol d_re, d_im containing complex-valued symbol d(0): + int16_t d_re=0, d_im=0,d1_re=0,d1_im=0; +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im); +#endif + /* + * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 + */ + // alpha is cyclic shift + double alpha; + // lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission + //uint8_t lnormal = 0 ; + // lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213] + uint8_t lprime = startingSymbolIndex; + // mcs = 0 except for PUCCH format 0 + uint8_t mcs=0; + // r_u_v_alpha_delta_re and r_u_v_alpha_delta_im tables containing the sequence y(n) for the PUCCH, when they are multiplied by d(0) + // r_u_v_alpha_delta_dmrs_re and r_u_v_alpha_delta_dmrs_im tables containing the sequence for the DM-RS. + int16_t r_u_v_alpha_delta_re[12],r_u_v_alpha_delta_im[12],r_u_v_alpha_delta_dmrs_re[12],r_u_v_alpha_delta_dmrs_im[12]; + /* + * in TS 38.213 Subclause 9.2.1 it is said that: + * for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift + * is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift + */ + /* + * the complex-valued symbol d_0 shall be multiplied with a sequence r_u_v_alpha_delta(n): y(n) = d_0 * r_u_v_alpha_delta(n) + */ + // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1 + uint8_t u=0,v=0;//,delta=0; + // if frequency hopping is disabled, intraSlotFrequencyHopping is not provided + // n_hop = 0 + // if frequency hopping is enabled, intraSlotFrequencyHopping is provided + // n_hop = 0 for first hop + // n_hop = 1 for second hop + uint8_t n_hop = 0; + // Intra-slot frequency hopping shall be assumed when the higher-layer parameter intraSlotFrequencyHopping is provided, + // regardless of whether the frequency-hop distance is zero or not, + // otherwise no intra-slot frequency hopping shall be assumed + //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers + uint8_t intraSlotFrequencyHopping = 0; + + if (startingPRB != startingPRB_intraSlotHopping) { + intraSlotFrequencyHopping=1; + } + +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping); +#endif + /* + * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources + */ + //int32_t *txptr; + uint32_t re_offset=0; + int i=0; +#define MAX_SIZE_Z 168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n + int16_t z_re_rx[MAX_SIZE_Z],z_im_rx[MAX_SIZE_Z],z_re_temp,z_im_temp; + int16_t z_dmrs_re_rx[MAX_SIZE_Z],z_dmrs_im_rx[MAX_SIZE_Z],z_dmrs_re_temp,z_dmrs_im_temp; + memset(z_re_rx,0,MAX_SIZE_Z*sizeof(int16_t)); + memset(z_im_rx,0,MAX_SIZE_Z*sizeof(int16_t)); + memset(z_dmrs_re_rx,0,MAX_SIZE_Z*sizeof(int16_t)); + memset(z_dmrs_im_rx,0,MAX_SIZE_Z*sizeof(int16_t)); + int l=0; + for(l=0;l<nrofSymbols;l++){ //extracting data and dmrs from rxdataF + if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB + startingPRB = startingPRB + startingPRB_intraSlotHopping; + } + + if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band + re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; + } + + if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band + re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))); + } + + if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is lower band + re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; + } + + if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band + re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6; + } + + if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC + re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset; + } + + //txptr = &txdataF[0][re_offset]; + for (int n=0; n<12; n++) { + if ((n==6) && (startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { + // if number RBs in bandwidth is odd and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB) + re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size); + } + + if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1 + z_re_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[0]; + z_im_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[1]; +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif + } + + if (l%2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1 + z_dmrs_re_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[0]; + z_dmrs_im_rx[i+n] = ((int16_t *)&rxdataF[0][re_offset])[1]; +// printf("%d\t%d\t%d\n",l,z_dmrs_re_rx[i+n],z_dmrs_im_rx[i+n]); +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n", + amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif +// printf("l=%d\ti=%d\tre_offset=%d\treceived dmrs re=%d\tim=%d\n",l,i,re_offset,z_dmrs_re_rx[i+n],z_dmrs_im_rx[i+n]); + } + + re_offset++; + } + if (l%2 == 1) i+=12; + } + int16_t y_n_re[12],y_n_im[12],y1_n_re[12],y1_n_im[12]; + memset(y_n_re,0,12*sizeof(int16_t)); + memset(y_n_im,0,12*sizeof(int16_t)); + memset(y1_n_re,0,12*sizeof(int16_t)); + memset(y1_n_im,0,12*sizeof(int16_t)); + //generating transmitted sequence and dmrs + for (l=0; l<nrofSymbols; l++) { +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n", + l,lprime); +#endif + // y_n contains the complex value d multiplied by the sequence r_u_v + if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop + +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n", + n_hop,nr_tti_tx); +#endif + nr_group_sequence_hopping(pucch_GroupHopping,n_id,n_hop,nr_tti_tx,&u,&v); // calculating u and v value + alpha = nr_cyclic_shift_hopping(n_id,m0,mcs,l,lprime,nr_tti_tx); + + for (int n=0; n<12; n++) { // generating low papr sequences + if(l%2==1){ + r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) + - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha + r_u_v_alpha_delta_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) + + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha + } + else{ + r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15) + - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of DMRS base sequence shifted by alpha + r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15) + + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of DMRS base sequence shifted by alpha + r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_re[n]))>>15); + r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_im[n]))>>15); + } +// printf("symbol=%d\tr_u_rx_re=%d\tr_u_rx_im=%d\n",l,r_u_v_alpha_delta_dmrs_re[n], r_u_v_alpha_delta_dmrs_im[n]); + // PUCCH sequence = DM-RS sequence multiplied by d(0) +/* y_n_re[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15) + - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n) + y_n_im[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15) + + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) */ +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n", + u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]); +#endif + } + /* + * The block of complex-valued symbols y(n) shall be block-wise spread with the orthogonal sequence wi(m) + * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im) + * z(mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n)=wi(m)*y(n) + * + * The block of complex-valued symbols r_u_v_alpha_dmrs_delta(n) for DM-RS shall be block-wise spread with the orthogonal sequence wi(m) + * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im) + * z(mprime*12*table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n)=wi(m)*y(n) + * + */ + // the orthogonal sequence index for wi(m) defined in TS 38.213 Subclause 9.2.1 + // the index of the orthogonal cover code is from a set determined as described in [4, TS 38.211] + // and is indicated by higher layer parameter PUCCH-F1-time-domain-OCC + // In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field + uint8_t w_index = timeDomainOCC; + // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled) + uint8_t N_SF_mprime_PUCCH_1; + // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled) + uint8_t N_SF_mprime_PUCCH_DMRS_1; + // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled) + uint8_t N_SF_mprime0_PUCCH_1; + // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled) + uint8_t N_SF_mprime0_PUCCH_DMRS_1; + // mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping + uint8_t mprime = 0; + + if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n", + intraSlotFrequencyHopping); +#endif + N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (PUCCH) + N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (DM-RS) + N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (PUCCH) + N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (DM-RS) +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n", + w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); +#endif + if(l%2==1){ + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)){ + for (int n=0; n<12 ; n++) { + z_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]=z_re_temp; + z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]=z_im_temp; +// printf("symbol=%d\tz_re_rx=%d\tz_im_rx=%d\t",l,(int)z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif + // multiplying with conjugate of low papr sequence + z_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + + (((int32_t)(r_u_v_alpha_delta_im[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + - (((int32_t)(r_u_v_alpha_delta_im[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_re_temp; + z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_im_temp; +/* if(z_re_temp<0){ + printf("\nBug detection %d\t%d\t%d\t%d\n",r_u_v_alpha_delta_re[n],z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(((int32_t)(r_u_v_alpha_delta_re[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15),(((int32_t)(r_u_v_alpha_delta_im[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)); + } + printf("z1_re_rx=%d\tz1_im_rx=%d\n",(int)z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); */ + } + } + } + } + + else{ + for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)){ + for (int n=0; n<12 ; n++) { + z_dmrs_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); + z_dmrs_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); + z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp; + z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp; +// printf("symbol=%d\tz_dmrs_re_rx=%d\tz_dmrs_im_rx=%d\t",l,(int)z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif + //finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and z_dmrs_im_rx arrays + z_dmrs_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + + (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); + z_dmrs_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + - (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); +/* if(z_dmrs_re_temp<0){ + printf("\nBug detection %d\t%d\t%d\t%d\n",r_u_v_alpha_delta_dmrs_re[n],z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15),(((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15)); + }*/ + z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp; + z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp; +// printf("z1_dmrs_re_rx=%d\tz1_dmrs_im_rx=%d\n",(int)z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],(int)z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); + /* z_dmrs_re_rx[(int)(l/2)*12+n]=z_dmrs_re_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_re[n]; + z_dmrs_im_rx[(int)(l/2)*12+n]=z_dmrs_im_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_im[n]; */ + } + } + } + } + } + + if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n", + intraSlotFrequencyHopping); +#endif + N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) + N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) + N_SF_mprime0_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH) + N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS) +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n", + w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); +#endif + + for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1} + if(l%2==1){ + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)){ + for (int n=0; n<12 ; n++) { + z_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_re_temp; + z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_im_temp; +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif + z_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + + (((int32_t)(r_u_v_alpha_delta_im[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15) + - (((int32_t)(r_u_v_alpha_delta_im[n])*z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n])>>15))>>1); + z_re_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_re_temp; + z_im_rx[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = z_im_temp; + } + } + } + } + + else{ + for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + if(floor(l/2)*12==(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)){ + for (int n=0; n<12 ; n++) { + z_dmrs_re_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); + z_dmrs_im_temp = (int16_t)(((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); + z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp; + z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp; +#ifdef DEBUG_NR_PUCCH_RX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif + //finding channel coeffcients by dividing received dmrs with actual dmrs and storing them in z_dmrs_re_rx and z_dmrs_im_rx arrays + z_dmrs_re_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + + (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); + z_dmrs_im_temp = (int16_t)(((((int32_t)(r_u_v_alpha_delta_dmrs_re[n])*z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15) + - (((int32_t)(r_u_v_alpha_delta_dmrs_im[n])*z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n])>>15))>>1); + z_dmrs_re_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_re_temp; + z_dmrs_im_rx[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = z_dmrs_im_temp; + + /* z_dmrs_re_rx[(int)(l/2)*12+n]=z_dmrs_re_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_re[n]; + z_dmrs_im_rx[(int)(l/2)*12+n]=z_dmrs_im_rx[(int)(l/2)*12+n]/r_u_v_alpha_delta_dmrs_im[n]; */ + } + } + } + } + + N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) + N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) + } + } + } + int16_t H_re[12],H_im[12],H1_re[12],H1_im[12]; + memset(H_re,0,12*sizeof(int16_t)); + memset(H_im,0,12*sizeof(int16_t)); + memset(H1_re,0,12*sizeof(int16_t)); + memset(H1_im,0,12*sizeof(int16_t)); + //averaging channel coefficients + for(l=0;l<=ceil(nrofSymbols/2);l++){ + if(intraSlotFrequencyHopping==0){ + for(int n=0;n<12;n++){ + H_re[n]=round(z_dmrs_re_rx[l*12+n]/ceil(nrofSymbols/2))+H_re[n]; + H_im[n]=round(z_dmrs_im_rx[l*12+n]/ceil(nrofSymbols/2))+H_im[n]; + } + } + else{ + if(l<round(nrofSymbols/4)){ + for(int n=0;n<12;n++){ + H_re[n]=round(z_dmrs_re_rx[l*12+n]/round(nrofSymbols/4))+H_re[n]; + H_im[n]=round(z_dmrs_im_rx[l*12+n]/round(nrofSymbols/4))+H_im[n]; + } + } + else{ + for(int n=0;n<12;n++){ + H1_re[n]=round(z_dmrs_re_rx[l*12+n]/(ceil(nrofSymbols/2)-round(nrofSymbols/4)))+H1_re[n]; + H1_im[n]=round(z_dmrs_im_rx[l*12+n]/(ceil(nrofSymbols/2))-round(nrofSymbols/4))+H1_im[n]; + } + } + } + } + //averaging information sequences + for(l=0;l<floor(nrofSymbols/2);l++){ + if(intraSlotFrequencyHopping==0){ + for(int n=0;n<12;n++){ + y_n_re[n]=round(z_re_rx[l*12+n]/floor(nrofSymbols/2))+y_n_re[n]; + y_n_im[n]=round(z_im_rx[l*12+n]/floor(nrofSymbols/2))+y_n_im[n]; + } + } + else{ + if(l<floor(nrofSymbols/4)){ + for(int n=0;n<12;n++){ + y_n_re[n]=round(z_re_rx[l*12+n]/floor(nrofSymbols/4))+y_n_re[n]; + y_n_im[n]=round(z_im_rx[l*12+n]/floor(nrofSymbols/4))+y_n_im[n]; + } + } + else{ + for(int n=0;n<12;n++){ + y1_n_re[n]=round(z_re_rx[l*12+n]/round(nrofSymbols/4))+y1_n_re[n]; + y1_n_im[n]=round(z_im_rx[l*12+n]/round(nrofSymbols/4))+y1_n_im[n]; + } + } + } + } + // mrc combining to obtain z_re and z_im + if(intraSlotFrequencyHopping==0){ + for(int n=0;n<12;n++){ + d_re = round(((int16_t)(((((int32_t)(H_re[n])*y_n_re[n])>>15) + (((int32_t)(H_im[n])*y_n_im[n])>>15))>>1))/12)+d_re; + d_im = round(((int16_t)(((((int32_t)(H_re[n])*y_n_im[n])>>15) - (((int32_t)(H_im[n])*y_n_re[n])>>15))>>1))/12)+d_im; + } + } + else{ + for(int n=0;n<12;n++){ + d_re = round(((int16_t)(((((int32_t)(H_re[n])*y_n_re[n])>>15) + (((int32_t)(H_im[n])*y_n_im[n])>>15))>>1))/12)+d_re; + d_im = round(((int16_t)(((((int32_t)(H_re[n])*y_n_im[n])>>15) - (((int32_t)(H_im[n])*y_n_re[n])>>15))>>1))/12)+d_im; + d1_re = round(((int16_t)(((((int32_t)(H1_re[n])*y1_n_re[n])>>15) + (((int32_t)(H1_im[n])*y1_n_im[n])>>15))>>1))/12)+d1_re; + d1_im = round(((int16_t)(((((int32_t)(H1_re[n])*y1_n_im[n])>>15) - (((int32_t)(H1_im[n])*y1_n_re[n])>>15))>>1))/12)+d1_im; + } + d_re=round(d_re/2); + d_im=round(d_im/2); + d1_re=round(d1_re/2); + d1_im=round(d1_im/2); + d_re=d_re+d1_re; + d_im=d_im+d1_im; + } + //Decoding QPSK or BPSK symbols to obtain payload bits + if(nr_bit==1){ + if((d_re+d_im)>0){ + *payload=0; + } + else{ + *payload=1; + } + } + else if(nr_bit==2){ + if((d_re>0)&&(d_im>0)){ + *payload=0; + } + else if((d_re<0)&&(d_im>0)){ + *payload=1; + } + else if((d_re>0)&&(d_im<0)){ + *payload=2; + } + else{ + *payload=3; + } + } } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 1728d93b695930ab280c2216b0502e465d41b4dd..6df9e0c20e32dbedf075b250dc0256e194857c94 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -98,7 +98,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, #endif pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -113,7 +114,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, #endif pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; current_ssb->c_re +=ch[0]; @@ -124,7 +126,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, #endif pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt+=3) { @@ -135,7 +138,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, // in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS) if (dmrss == 1 && pilot_cnt == 12) { pilot_cnt=48; - re_offset = (re_offset+144)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+144)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 144) : (re_offset+144); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; } ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -149,7 +153,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, #endif pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -163,7 +168,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -178,7 +184,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, #endif pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; } @@ -303,7 +310,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 16); pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; //for (int i= 0; i<8; i++) @@ -321,7 +329,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 16); pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -336,7 +345,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 16); pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; dl_ch+=24; @@ -348,7 +358,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, // in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS) if (dmrss == 1 && pilot_cnt == 12) { pilot_cnt=48; - re_offset = (re_offset+144)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+144)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 144) : (re_offset+144); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; dl_ch += 288; } @@ -367,7 +378,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -382,7 +394,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 16); pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -398,7 +411,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 16); pil+=2; - re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 4) : (re_offset+4); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; dl_ch+=24; @@ -611,9 +625,17 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, idft = idft2048; break; - default: - idft = idft512; + case 3072: + idft = idft3072; + break; + + case 4096: + idft = idft4096; break; + + default: + printf("unsupported ofdm symbol size \n"); + assert(0); } if( (Ns== 1) && (symbol == 0)) @@ -623,7 +645,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, for (p=0; p<ue->frame_parms.nb_antenna_ports_eNB; p++) { if (ue->pdcch_vars[ue->current_thread_id[Ns]][eNB_offset]->dl_ch_estimates[(p<<1)+aarx]) { - LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d \n", Ns, ue->current_thread_id[Ns], symbol); + LOG_I(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d \n", Ns, ue->current_thread_id[Ns], symbol); idft((int16_t*) &ue->pdcch_vars[ue->current_thread_id[Ns]][eNB_offset]->dl_ch_estimates[(p<<1)+aarx][0], (int16_t*) ue->pdcch_vars[ue->current_thread_id[Ns]][eNB_offset]->dl_ch_estimates_time[(p<<1)+aarx],1); } @@ -734,7 +756,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); pil+=2; - re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 2) : (re_offset+2); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //for (int i= 0; i<8; i++) //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); @@ -749,7 +772,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); pil+=2; - re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 2) : (re_offset+2); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //printf("dl_ch addr %p\n",dl_ch); @@ -767,7 +791,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); pil+=2; - re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 2) : (re_offset+2); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; dl_ch+=8; @@ -787,7 +812,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, 8); pil+=2; - re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 2) : (re_offset+2); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -800,7 +826,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); pil+=2; - re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 2) : (re_offset+2); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; dl_ch+=8; @@ -821,7 +848,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); pil+=2; - re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 2) : (re_offset+2); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -836,7 +864,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, 8); pil+=2; - re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + //re_offset = (re_offset+2)&(ue->frame_parms.ofdm_symbol_size-1); + re_offset = (re_offset >= ue->frame_parms.ofdm_symbol_size) ? (re_offset - ue->frame_parms.ofdm_symbol_size + 2) : (re_offset+2); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; dl_ch+=8; 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_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 84d2c3011e15ff3c73b0501998efc65a110c5de2..4c8b10d89a8246e8cf83942411bb7ec6b875398e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -238,6 +238,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint16_t nb_rb = 30; double Coderate = 0.0; + nfapi_nr_dl_config_dlsch_pdu_rel15_t *dl_config_pdu = &harq_process->dl_config_pdu; uint8_t dmrs_Type = dl_config_pdu->dmrs_Type; AssertFatal(dmrs_Type == 1 || dmrs_Type == 2,"Illegal dmrs_type %d\n",dmrs_Type); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 4bdc30540d7e784425294ea1bc1ad8024874587a..f0a5e6260dd861ed22a7e2d47c23adffea6abcb8 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_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index b56573f2b3c25ecece9968fac93cf053f502f0a7..cac9ae92ac7dcc819fa2e5021d3fbf055743501f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -103,8 +103,9 @@ uint16_t nr_pbch_extract(int **rxdataF, j++; } - rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); - } + //rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); + rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1); + } rxF_ext+=9; } else { //symbol 2 @@ -125,11 +126,12 @@ uint16_t nr_pbch_extract(int **rxdataF, j++; } - rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); + //rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); + rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1); } rxF_ext+=9; - } else rx_offset = (rx_offset+12)&(frame_parms->ofdm_symbol_size-1); + } else rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 12) : (rx_offset+12);//rx_offset = (rx_offset+12)&(frame_parms->ofdm_symbol_size-1); } } @@ -566,8 +568,8 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, } uint32_t payload = 0; - uint8_t xtra_byte = 0; - xtra_byte = (out>>24)&0xff; + //uint8_t xtra_byte = 0; + nr_ue_pbch_vars->xtra_byte = (out>>24)&0xff; for (int i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++) payload |= ((out>>i)&1)<<(NR_POLAR_PBCH_PAYLOAD_BITS-i-1); @@ -575,18 +577,18 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, for (int i=0; i<3; i++) decoded_output[i] = (uint8_t)((payload>>((3-i)<<3))&0xff); - n_hf = ((xtra_byte>>4)&0x01); // computing the half frame index from the extra byte + n_hf = ((nr_ue_pbch_vars->xtra_byte>>4)&0x01); // computing the half frame index from the extra byte ssb_index = i_ssb; // ssb index corresponds to i_ssb for Lmax = 4,8 if (Lmax == 64) { // for Lmax = 64 ssb index 4th,5th and 6th bits are in extra byte for (int i=0; i<3; i++) - ssb_index += (((xtra_byte>>(7-i))&0x01)<<(3+i)); + ssb_index += (((nr_ue_pbch_vars->xtra_byte>>(7-i))&0x01)<<(3+i)); } ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms, ssb_index, n_hf); #ifdef DEBUG_PBCH - printf("xtra_byte %x payload %x\n", xtra_byte, payload); + printf("xtra_byte %x payload %x\n", nr_ue_pbch_vars->xtra_byte, payload); for (int i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++) { // printf("unscrambling pbch_a[%d] = %x \n", i,pbch_a[i]); @@ -594,19 +596,25 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, } #endif - ue->dl_indication.rx_ind = &ue->rx_ind; // hang on rx_ind instance - ue->dl_indication.proc=proc; - //ue->rx_ind.sfn_slot = 0; //should be set by higher-1-layer, i.e. clean_and_set_if_instance() - ue->rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_MIB; - ue->rx_ind.rx_indication_body[0].mib_pdu.pdu = &decoded_output[0]; - ue->rx_ind.rx_indication_body[0].mib_pdu.additional_bits = xtra_byte; - ue->rx_ind.rx_indication_body[0].mib_pdu.ssb_index = i_ssb; // confirm with TCL - ue->rx_ind.rx_indication_body[0].mib_pdu.ssb_length = Lmax; // confirm with TCL - ue->rx_ind.rx_indication_body[0].mib_pdu.cell_id = frame_parms->Nid_cell; // confirm with TCL - ue->rx_ind.number_pdus = 1; + nr_downlink_indication_t dl_indication; + fapi_nr_rx_indication_t rx_ind; + + dl_indication.rx_ind = &rx_ind; // hang on rx_ind instance + dl_indication.dci_ind = NULL; + dl_indication.proc=proc; // needed to signal back the frame number -> FIXME + dl_indication.module_id=0; + dl_indication.cc_id=proc->CC_id; + + rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_MIB; + rx_ind.rx_indication_body[0].mib_pdu.pdu = &decoded_output[0]; //not good as it is pointing to a memory that can change + rx_ind.rx_indication_body[0].mib_pdu.additional_bits = nr_ue_pbch_vars->xtra_byte; + rx_ind.rx_indication_body[0].mib_pdu.ssb_index = i_ssb; // confirm with TCL + rx_ind.rx_indication_body[0].mib_pdu.ssb_length = Lmax; // confirm with TCL + rx_ind.rx_indication_body[0].mib_pdu.cell_id = frame_parms->Nid_cell; // confirm with TCL + rx_ind.number_pdus = 1; if (ue->if_inst && ue->if_inst->dl_indication) - ue->if_inst->dl_indication(&ue->dl_indication); + ue->if_inst->dl_indication(&dl_indication); return 0; } 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 ee39829d6894a42f3699d9d6b6f88836a7a77bfe..1e000f93c31143b038048a11dfc4b42cf56fdeac 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 19ae1fd394fc61f3fa5cac94d2aa78f75fbbc3bd..6ac1122bfd186099b5c3a6e8782e77f54756ba15 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..7b161ac23d5a862fd1e2d22c889e058b34ead8c3 --- /dev/null +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -0,0 +1,411 @@ +/* + * 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,mcs,rvidx; + uint16_t n_rnti; + + NR_UE_ULSCH_t *ulsch_ue; + NR_UL_UE_HARQ_t *harq_process_ul_ue; + + //--------------------------Temporary configuration-----------------------------// + length_dmrs = 1; + n_rnti = 0x1234; + Nid_cell = 0; + nb_rb = 50; + first_rb = 30; + Nsymb_pusch = 12; + nb_codewords = 1; + mcs = 9; + rvidx = 0; + //------------------------------------------------------------------------------// + + 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 = mcs; + harq_process_ul_ue->Nl = nb_codewords; + 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 = rvidx; + harq_process_ul_ue->TBS = nr_compute_tbs(harq_process_ul_ue->mcs, + nb_rb, + Nsymb_pusch, + ulsch_ue->nb_re_dmrs, + length_dmrs, + harq_process_ul_ue->Nl); + + } + + } + + 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/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index a88095986478a2becf0a723001f99d58d44e4c08..c9fb3007063a5b48d7adf66c03e9bec50d446f0a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -89,6 +89,10 @@ void *get_idft(int ofdm_symbol_size) idft = idft2048; break; + case 3072: + idft = idft3072; + break; + case 4096: idft = idft4096; break; diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index 2771874bd3f66d83f7c88bbfdf479afcc676a576..e838b4b7476d29e95036b7ddf6d376e7aeff5004 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -195,7 +195,7 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, int16_t amp, int nr_tti_tx, uint8_t m0, - uint8_t mcs, + uint8_t mcs, uint8_t nrofSymbols, uint8_t startingSymbolIndex, uint16_t startingPRB) { @@ -366,7 +366,7 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } } - +// printf("d_re=%d\td_im=%d\n",(int)d_re,(int)d_im); #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im); #endif @@ -451,11 +451,13 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of DMRS base sequence shifted by alpha r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_re[n]))>>15); r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_im[n]))>>15); +// printf("symbol=%d\tr_u_v_re=%d\tr_u_v_im=%d\n",l,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n]); // PUCCH sequence = DM-RS sequence multiplied by d(0) y_n_re[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15) - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n) y_n_im[n] = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15) + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) +// printf("symbol=%d\tr_u_v_dmrs_re=%d\tr_u_v_dmrs_im=%d\n",l,r_u_v_alpha_delta_dmrs_re[n],r_u_v_alpha_delta_dmrs_im[n]); #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n", u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]); @@ -520,10 +522,10 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { for (int n=0; n<12 ; n++) { - z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); - z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); + z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, @@ -531,7 +533,8 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); #endif - } +// printf("gNB entering l=%d\tdmrs_re=%d\tdmrs_im=%d\n",l,z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n],z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n]); + } } } @@ -549,43 +552,41 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1); #endif - for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { - for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1} - for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { - for (int n=0; n<12 ; n++) { - z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); - z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); -#ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", - mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], - z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); -#endif - } + for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1} + for (int m=0; m < N_SF_mprime_PUCCH_1; m++) { + for (int n=0; n<12 ; n++) { + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)); + z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n], + z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); +#endif } + } - for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { - for (int n=0; n<12 ; n++) { - z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15) - - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); - z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15) - + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); + for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) { + for (int n=0; n<12 ; n++) { + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15) + - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)); + z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15) + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)); #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", - mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], - table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], - z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); + printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n", + mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n, + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n], + table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n], + z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]); #endif - } } - - N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) - N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) } + + N_SF_mprime_PUCCH_1 = table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH) + N_SF_mprime_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS) } } @@ -638,8 +639,9 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset, l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); #endif +// printf("gNb l=%d\ti=%d\treoffset=%d\tre=%d\tim=%d\n",l,i,re_offset,z_dmrs_re[i+n],z_dmrs_im[i+n]); } - + re_offset++; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index bc7bfad82bbac7950804963deaef347a40b6002a..e8cd147526be502ba16ab3e0e88e9c490e1c43b9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -42,10 +42,25 @@ #include "T.h" #define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) +void nr_decode_pucch1( int32_t **rxdataF, + pucch_GroupHopping_t pucch_GroupHopping, + uint32_t n_id, // hoppingID higher layer parameter + uint64_t *payload, + NR_DL_FRAME_PARMS *frame_parms, + int16_t amp, + int nr_tti_tx, + uint8_t m0, + uint8_t nrofSymbols, + uint8_t startingSymbolIndex, + uint16_t startingPRB, + uint16_t startingPRB_intraSlotHopping, + uint8_t timeDomainOCC, + uint8_t nr_bit); + void nr_decode_pucch0( int32_t **rxdataF, pucch_GroupHopping_t PUCCH_GroupHopping, uint32_t n_id, //PHY_VARS_gNB *gNB, generally rxdataf is in gNB->common_vars - uint8_t *payload, + uint64_t *payload, NR_DL_FRAME_PARMS *frame_parms, int16_t amp, int nr_tti_tx, @@ -74,7 +89,7 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, int16_t amp, int nr_tti_tx, uint8_t m0, - uint8_t mcs, + uint8_t mcs, uint8_t nrofSymbols, uint8_t startingSymbolIndex, uint16_t startingPRB); 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 88f29177185c53f40e6320b2031ef9f92254dfb9..8f32d994e7c96834483b470fad55c551eb34681d 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -310,6 +310,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 21fa9309716e16da64b0725bd0b822415ca39179..23a794cb6b76185ef8a3fa73ac2556b58afa6a63 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -245,8 +245,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; ////////////////////////////////////////////////////////////// @@ -365,6 +363,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 @@ -580,13 +617,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_SRS srs_vars[NUMBER_OF_UE_MAX];*/ NR_gNB_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 dd7127a8e27aa09e1c2523f37586e115ee6038c0..9d675a2c63e2f7249dce0b06d5288e3bad2b3541 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. @@ -817,6 +822,8 @@ typedef struct { /// \brief Pointer to PBCH decoded output. /// - first index: ? [0..63] (hard coded) uint8_t *decoded_output; + /// \brief PBCH additional bits + uint8_t xtra_byte; /// \brief Total number of PDU errors. uint32_t pdu_errors; /// \brief Total number of PDU errors 128 frames ago. @@ -918,18 +925,22 @@ typedef struct { NR_UE_COMMON common_vars; nr_ue_if_module_t *if_inst; - nfapi_nr_config_request_t nrUE_config; - nr_downlink_indication_t dl_indication; - nr_uplink_indication_t ul_indication; + //nfapi_nr_config_request_t nrUE_config; <-- don't use config type for gNB!!! + fapi_nr_config_request_t nrUE_config; + + // the following structures are not part of PHY_vars_UE anymore as it is not thread safe. They are now on the stack of the functions that actually need them + + //nr_downlink_indication_t dl_indication; + //nr_uplink_indication_t ul_indication; /// UE FAPI DCI request - nr_dcireq_t dcireq; + //nr_dcireq_t dcireq; // pointers to the next 2 strcutres are also included in dl_indictation /// UE FAPI indication for DLSCH reception - fapi_nr_rx_indication_t rx_ind; + //fapi_nr_rx_indication_t rx_ind; /// UE FAPI indication for DCI reception - fapi_nr_dci_indication_t dci_ind; + //fapi_nr_dci_indication_t dci_ind; // point to the current rxTx thread index uint8_t current_thread_id[40]; @@ -943,6 +954,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 +995,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 6f3d45a4c5b4d2aff6727cd61a6e2de1b1eb5abb..1cc8ccd69f59d5c8648355a53811436d988f2ceb 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 #define MAX_NUM_NR_DLSCH_SEGMENTS 16 diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index 13b139e0bb76ee30e3d4c55421a019787ced63d5..e93dcc3ead124e35d1e702237307302369a0327e 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 f566c3dacf27b9e535783cc1290ca6a56782e307..95f4d6398c736e39b3bcb684c1ec2664662e2f14 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" @@ -167,10 +169,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; @@ -189,11 +193,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); } } @@ -203,11 +207,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, } -void phy_procedures_gNB_RX(PHY_VARS_gNB *gNB, - int frame,int slot) { - - NR_DL_FRAME_PARMS *fp=&gNB->frame_parms; - nfapi_nr_config_request_t *cfg = &gNB->gNB_config; +/* if ((cfg->subframe_config.duplex_mode.value == TDD) && ((nr_slot_select(fp,frame,slot)&NR_DOWNLINK_SLOT)==SF_DL)) return; @@ -216,5 +216,79 @@ void phy_procedures_gNB_RX(PHY_VARS_gNB *gNB, if (do_prach_rx(fp,frame,slot)) L1_nr_prach_procedures(gNB,frame,slot/fp->slots_per_subframe); +*/ + +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 7f7307c4f5f6270b384344bb0ac94ff8857b24f7..fdd54860e84c6fc561ea93193fe148f52a40a35a 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -36,7 +36,9 @@ 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 318b0c311fea20d4dcd895ff045200410ba31500..8adb8fcfeeee3dcb1e965680ca78bb5bbd3878d9 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 @@ -123,6 +123,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t e @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param phy_vars_rn pointer to RN variables */ + int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id, uint8_t do_pdcch_flag,runmode_t mode, fapi_nr_dl_config_request_t *DLconfigreq); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index d783243cae544889c0bac1333ab5de153ca58c42..44d847514b594f67eb45ab3662b483ebe3f31815 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -49,10 +49,10 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ uint8_t cc_id = scheduled_response->CC_id; uint32_t i; int slot = scheduled_response->slot; - uint8_t thread_id = PHY_vars_UE_g[module_id][cc_id]->current_thread_id[slot]; if(scheduled_response != NULL){ // Note: we have to handle the thread IDs for this. To be revisited completely. + uint8_t thread_id = PHY_vars_UE_g[module_id][cc_id]->current_thread_id[slot]; NR_UE_PDCCH *pdcch_vars2 = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0]; NR_UE_DLSCH_t *dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[thread_id][0][0]; NR_UE_ULSCH_t *ulsch0 = PHY_vars_UE_g[module_id][cc_id]->ulsch[thread_id][0][0]; @@ -142,7 +142,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ uint8_t current_harq_pid = ulsch_config_pdu->harq_process_nbr; ulsch0->harq_processes[current_harq_pid]->nb_rb = ulsch_config_pdu->number_rbs; ulsch0->harq_processes[current_harq_pid]->first_rb = ulsch_config_pdu->start_rb; - ulsch0->harq_processes[current_harq_pid]->nb_symbols = ulsch_config_pdu->number_symbols; + ulsch0->harq_processes[current_harq_pid]->number_of_symbols = ulsch_config_pdu->number_symbols; ulsch0->harq_processes[current_harq_pid]->start_symbol = ulsch_config_pdu->start_symbol; ulsch0->harq_processes[current_harq_pid]->mcs = ulsch_config_pdu->mcs; ulsch0->harq_processes[current_harq_pid]->DCINdi = ulsch_config_pdu->ndi; @@ -213,6 +213,8 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){ + fapi_nr_config_request_t nrUE_config = PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config; + if(phy_config != NULL){ LOG_I(MAC,"[L1][IF module][PHY CONFIG]\n"); LOG_I(MAC,"subcarrier spacing: %d\n", phy_config->config_req.rf_config.dl_subcarrierspacing); @@ -222,8 +224,6 @@ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){ LOG_I(MAC,"searchSapceZero: %d\n", phy_config->config_req.pdcch_config.searchSpaceZero); LOG_I(MAC,"-------------------------------\n"); - - } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b1adb5e68cfe4411804e59cafe718a40e5a3b206..2c712d7efc5858663d84c13b74fcca141ebbf4ef 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2460,131 +2460,76 @@ 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; + 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 - 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( harq_process_ul_ue->mcs, harq_process_ul_ue->nb_rb, ulsch_ue->Nsymb_pusch, ulsch_ue->nb_re_dmrs, ulsch_ue->length_dmrs, harq_process_ul_ue->Nl); + +//-----------------------------------------------------// + // 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, + harq_process_ul_ue->Nl, + &ue->frame_parms); +/* if ((ue->UE_mode[eNB_id] == PRACH) && (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) { @@ -2598,54 +2543,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 +2579,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, @@ -2804,9 +2714,9 @@ void restart_phy(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc, uint8_t eNB_id,uint #endif //(0) void nr_ue_pbch_procedures(uint8_t eNB_id, - PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - uint8_t abstraction_flag) + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + uint8_t ssb_index) { // int i; //int pbch_tx_ant=0; @@ -2828,7 +2738,7 @@ void nr_ue_pbch_procedures(uint8_t eNB_id, ue->pbch_vars[eNB_id], &ue->frame_parms, eNB_id, - ue->rx_ind.rx_indication_body[0].mib_pdu.ssb_index, + ssb_index, SISO, ue->high_speed_flag); @@ -2959,6 +2869,10 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, nr_tti_rx,nb_searchspace_total); #endif + //FK: we define dci_ind and dl_indication as local variables, this way the call to the mac should be thread safe + fapi_nr_dci_indication_t dci_ind; + nr_downlink_indication_t dl_indication; + // p in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 3 different CORESETs (including coresetId 0 for common search space) //int nb_coreset_total = NR_NBR_CORESET_ACT_BWP; unsigned int dci_cnt=0; @@ -3151,7 +3065,7 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, //emos_dump_UE.dci_cnt[nr_tti_rx] = dci_cnt; #endif - ue->dci_ind.number_of_dcis = dci_cnt; + dci_ind.number_of_dcis = dci_cnt; for (int i=0; i<dci_cnt; i++) { /* @@ -3191,12 +3105,12 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, LOG_D(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> dci_format=%d, rnti=%d, dci_length=%d, dci_pdu[0]=0x%lx, dci_pdu[1]=0x%lx\n",dci_alloc_rx[i].format,dci_alloc_rx[i].rnti,dci_alloc_rx[i].dci_length,dci_alloc_rx[i].dci_pdu[0],dci_alloc_rx[i].dci_pdu[1]); - memset(&ue->dci_ind.dci_list[i].dci,0,sizeof(fapi_nr_dci_pdu_rel15_t)); + memset(&dci_ind.dci_list[i].dci,0,sizeof(fapi_nr_dci_pdu_rel15_t)); - ue->dci_ind.dci_list[i].rnti = dci_alloc_rx[i].rnti; - ue->dci_ind.dci_list[i].dci_format = dci_alloc_rx[i].format; - ue->dci_ind.dci_list[i].n_CCE = dci_alloc_rx[i].firstCCE; - ue->dci_ind.dci_list[i].N_CCE = (int)dci_alloc_rx[i].L; + dci_ind.dci_list[i].rnti = dci_alloc_rx[i].rnti; + dci_ind.dci_list[i].dci_format = dci_alloc_rx[i].format; + dci_ind.dci_list[i].n_CCE = dci_alloc_rx[i].firstCCE; + dci_ind.dci_list[i].N_CCE = (int)dci_alloc_rx[i].L; status = nr_extract_dci_info(ue, eNB_id, @@ -3204,7 +3118,7 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, dci_alloc_rx[i].dci_length, dci_alloc_rx[i].rnti, dci_alloc_rx[i].dci_pdu, - &ue->dci_ind.dci_list[i].dci, + &dci_ind.dci_list[i].dci, dci_fields_sizes_cnt[i], dci_alloc_rx[i].format, nr_tti_rx, @@ -3246,16 +3160,16 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, } // end for loop dci_cnt // fill dl_indication message - ue->dl_indication.module_id = ue->Mod_id; - ue->dl_indication.cc_id = ue->CC_id; - ue->dl_indication.gNB_index = eNB_id; - ue->dl_indication.frame = frame_rx; - ue->dl_indication.slot = nr_tti_rx; - ue->dl_indication.rx_ind = NULL; //no data, only dci for now - ue->dl_indication.dci_ind = &ue->dci_ind; + dl_indication.module_id = ue->Mod_id; + dl_indication.cc_id = ue->CC_id; + dl_indication.gNB_index = eNB_id; + dl_indication.frame = frame_rx; + dl_indication.slot = nr_tti_rx; + dl_indication.rx_ind = NULL; //no data, only dci for now + dl_indication.dci_ind = &dci_ind; // send to mac - ue->if_inst->dl_indication(&ue->dl_indication); + ue->if_inst->dl_indication(&dl_indication); #if UE_TIMING_TRACE stop_meas(&ue->dlsch_rx_pdcch_stats); @@ -3402,165 +3316,6 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, #endif -#if 0 - -void ue_pmch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc,int eNB_id,int abstraction_flag) { - - int nr_tti_rx = proc->nr_tti_rx; - int frame_rx = proc->frame_rx; - int pmch_mcs=-1; -#if defined(Rel10) || defined(Rel14) - int CC_id = ue->CC_id; -#endif - uint8_t sync_area=255; - uint8_t mcch_active; - int l; - int ret=0; - - if (is_pmch_subframe(frame_rx,nr_tti_rx,&ue->frame_parms)) { - LOG_D(PHY,"ue calling pmch nr_tti_rx ..\n "); - - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Querying for PMCH demodulation\n", - ue->Mod_id,(nr_tti_rx==9?-1:0)+frame_rx,nr_tti_rx); -#if defined(Rel10) || defined(Rel14) - /*pmch_mcs = mac_xface->ue_query_mch(ue->Mod_id, - CC_id, - frame_rx, - nr_tti_rx, - eNB_id, - &sync_area, - &mcch_active);*/ - -#else - pmch_mcs=-1; -#endif - - if (pmch_mcs>=0) { - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Programming PMCH demodulation for mcs %d\n",ue->Mod_id,frame_rx,nr_tti_rx,pmch_mcs); - fill_UE_dlsch_MCH(ue,pmch_mcs,1,0,0); - - if (abstraction_flag == 0 ) { - for (l=2; l<12; l++) { - - slot_fep_mbsfn(ue, - l, - nr_tti_rx, - 0,0);//ue->rx_offset,0); - } - - for (l=2; l<12; l++) { - rx_pmch(ue, - 0, - nr_tti_rx, - l); - } - - - ue->dlsch_MCH[0]->harq_processes[0]->G = get_G(&ue->frame_parms, - ue->dlsch_MCH[0]->harq_processes[0]->nb_rb, - ue->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even, - ue->dlsch_MCH[0]->harq_processes[0]->Qm, - 1, - 2, - frame_rx, - nr_tti_rx, - 0); - - dlsch_unscrambling(&ue->frame_parms,1,ue->dlsch_MCH[0], - ue->dlsch_MCH[0]->harq_processes[0]->G, - ue->pdsch_vars_MCH[0]->llr[0],0,nr_tti_rx<<1); - -#ifdef UE_DLSCH_PARALLELISATION - ret = dlsch_decoding_mthread(ue,proc, eNB_id, - ue->pdsch_vars_MCH[0]->llr[0], - &ue->frame_parms, - ue->dlsch_MCH[0], - ue->dlsch_MCH[0]->harq_processes[0], - frame_rx, - nr_tti_rx, - 0, - 0,1); -#else - ret = dlsch_decoding(ue, - ue->pdsch_vars_MCH[0]->llr[0], - &ue->frame_parms, - ue->dlsch_MCH[0], - ue->dlsch_MCH[0]->harq_processes[0], - frame_rx, - nr_tti_rx, - 0, - 0,1); - printf("start pmch dlsch decoding\n"); -#endif - } else { // abstraction -#ifdef PHY_ABSTRACTION - ret = dlsch_decoding_emul(ue, - nr_tti_rx, - 5, // PMCH - eNB_id); -#endif - } - - if (mcch_active == 1) - ue->dlsch_mcch_trials[sync_area][0]++; - else - ue->dlsch_mtch_trials[sync_area][0]++; - - if (ret == (1+ue->dlsch_MCH[0]->max_turbo_iterations)) { - if (mcch_active == 1) - ue->dlsch_mcch_errors[sync_area][0]++; - else - ue->dlsch_mtch_errors[sync_area][0]++; - - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: PMCH in error (%d,%d), not passing to L2 (TBS %d, iter %d,G %d)\n", - ue->Mod_id, - frame_rx,nr_tti_rx, - ue->dlsch_mcch_errors[sync_area][0], - ue->dlsch_mtch_errors[sync_area][0], - ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, - ue->dlsch_MCH[0]->max_turbo_iterations, - ue->dlsch_MCH[0]->harq_processes[0]->G); - dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,nr_tti_rx); -#ifdef DEBUG_DLSCH - - for (int i=0; i<ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3; i++) { - LOG_T(PHY,"%02x.",ue->dlsch_MCH[0]->harq_processes[0]->c[0][i]); - } - - LOG_T(PHY,"\n"); -#endif - - if (nr_tti_rx==9) - //mac_xface->macphy_exit("Why are we exiting here?"); - } else { // decoding successful -#if defined(Rel10) || defined(Rel14) - - if (mcch_active == 1) { - /*mac_xface->ue_send_mch_sdu(ue->Mod_id, - CC_id, - frame_rx, - ue->dlsch_MCH[0]->harq_processes[0]->b, - ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, - eNB_id,// not relevant in eMBMS context - sync_area);*/ - ue->dlsch_mcch_received[sync_area][0]++; - - - if (ue->dlsch_mch_received_sf[nr_tti_rx%5][0] == 1 ) { - ue->dlsch_mch_received_sf[nr_tti_rx%5][0]=0; - } else { - ue->dlsch_mch_received[0]+=1; - ue->dlsch_mch_received_sf[nr_tti_rx][0]=1; - } - - - } -#endif // Rel10 || Rel14 - } // decoding sucessful - } // pmch_mcs>=0 - } // is_pmch_subframe=true -} -#endif void copy_harq_proc_struct(NR_DL_UE_HARQ_t *harq_processes_dest, NR_DL_UE_HARQ_t *current_harq_processes) { @@ -3792,7 +3547,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, uint8_t is_cw0_active = 0; uint8_t is_cw1_active = 0; - if (dlsch0==NULL) AssertFatal(0,"dlsch0 should be defined at this level \n"); @@ -4206,7 +3960,9 @@ void *UE_thread_slot1_dl_processing(void *arg) { if ( (nr_tti_rx == 0) && (ue->decode_MIB == 1)) { - ue_pbch_procedures(0,ue,proc,0); + // fix this for multi-threaded case + uint8_t ssb_index=0; + ue_pbch_procedures(0,ue,proc,0,ssb_index); } proc->chan_est_slot1_available = 1; @@ -4341,6 +4097,7 @@ void *UE_thread_slot1_dl_processing(void *arg) { #endif + fapi_nr_dl_config_bch_pdu *is_pbch_in_slot(fapi_nr_dl_config_request_t *DLconfigreq, int frame, int slot, int periodicity, uint16_t slots_per_frame) { for (int i=0;i<DLconfigreq->number_pdus;i++) { @@ -4387,6 +4144,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN uint8_t nb_symb_pdcch = pdcch_vars->coreset[0].duration; uint8_t ssb_periodicity = 10;// ue->ssb_periodicity; // initialized to 5ms in nr_init_ue for scenarios where UE is not configured (otherwise acquired by cell configuration from gNB or LTE) uint8_t dci_cnt = 0; + LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx%1024, nr_tti_rx); @@ -4575,7 +4333,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN #endif } - nr_ue_pbch_procedures(eNB_id,ue,proc,0); + nr_ue_pbch_procedures(eNB_id,ue,proc,bch_config->ssb_index); } // do procedures for C-RNTI 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/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index e039f17419967b025f60966c1a65424076628591..a8bc7cbed7a9a73130459d2aa916b445717555fa 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);} @@ -115,8 +119,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]; void prepare_scc_sim(NR_ServingCellConfigCommon_t *scc) { @@ -902,6 +904,8 @@ int main(int argc, char **argv) UE_mac->scheduled_response.slot = slot; + nr_ue_phy_config_request(&UE_mac->phy_config); + for (SNR=snr0; SNR<snr1; SNR+=.2) { n_errors = 0; @@ -955,14 +959,13 @@ int main(int argc, char **argv) normal_txrx, &UE_mac->dl_config_request); - if (n_trials==1) { LOG_M("rxsigF0.m","rxsF0", UE->common_vars.common_vars_rx_data_per_thread[0].rxdataF[0],slot_length_complex_samples_no_prefix,1,1); if (UE->frame_parms.nb_antennas_rx>1) LOG_M("rxsigF1.m","rxsF1", UE->common_vars.common_vars_rx_data_per_thread[0].rxdataF[1],slot_length_complex_samples_no_prefix,1,1); } - if (UE->dci_ind.number_of_dcis==0) n_errors++; + if (UE_mac->dl_config_request.number_pdus==0) n_errors++; } } //noise trials diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 8e904f82305afed85906f14bae7bfcf77a183f74..8acd13c4638c08ddbb04990572588dcff6a07a11 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) @@ -636,10 +636,10 @@ int main(int argc, char **argv) uint8_t gNB_xtra_byte=0; for (int i=0; i<8; i++) gNB_xtra_byte |= ((gNB->pbch.pbch_a>>(31-i))&1)<<(7-i); - - payload_ret = (UE->rx_ind.rx_indication_body->mib_pdu.additional_bits == gNB_xtra_byte); + + payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte); for (i=0;i<3;i++){ - payload_ret += (UE->rx_ind.rx_indication_body->mib_pdu.pdu[i] == gNB->pbch_pdu[2-i]); + payload_ret += (UE->pbch_vars[0]->decoded_output[i] == gNB->pbch_pdu[2-i]); //printf("pdu byte %d gNB: 0x%02x UE: 0x%02x\n",i,gNB->pbch_pdu[i], UE->rx_ind.rx_indication_body->mib_pdu.pdu[i]); } //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->rx_ind.rx_indication_body->mib_pdu.additional_bits); @@ -655,7 +655,6 @@ int main(int argc, char **argv) if (((float)n_errors/(float)n_trials <= target_error_rate) && (n_errors_payload==0)) { printf("PBCH test OK\n"); - printf("Synchronization obtained for i_ssb = %d\n",UE->rx_ind.rx_indication_body[0].mib_pdu.ssb_index); break; } diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 439280df31ecb087f95ffbd858e5fddbe234638b..1184f86dfeee88f2570b817318c3b5f5a105c9cc 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -83,10 +83,8 @@ PHY_VARS_NR_UE * PHY_vars_UE_g[1][1]={{NULL}}; int main(int argc, char **argv) { - char c; - - int i,aa;//,l; + int i,aa=0;//,l; double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0; double cfo=0; uint8_t snr1set=0; @@ -100,38 +98,32 @@ int main(int argc, char **argv) //int freq_offset; // int subframe_offset; // char fname[40], vname[40]; - int trial,n_trials=1,n_errors=0; + int trial,n_trials=100,n_errors=0,ack_nack_errors=0; uint8_t transmission_mode = 1,n_tx=1,n_rx=1; uint16_t Nid_cell=0; uint64_t SSB_positions=0x01; - channel_desc_t *gNB2UE; - + int format=0; uint8_t extended_prefix_flag=0; - int8_t interf1=-21,interf2=-21; - - FILE *input_fd=NULL,*pbch_file_fd=NULL; - - //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0; - //char input_val_str[50],input_val_str2[50]; - //uint8_t frame_mod4,num_pdcch_symbols = 0; - //double pbch_sinr; - //int pbch_tx_ant; - + FILE *input_fd=NULL; + uint8_t nacktoack_flag=0; + int16_t amp=0x7FFF; + int nr_tti_tx=0; + uint64_t actual_payload=0,payload_received;//payload bits b7b6...b2b1b0 where b7..b3=0 b2b1=HARQ b0 is SR. payload maximum value is 7 for pucch format 0 + int nr_bit=1; // maximum value possible is 2 + uint8_t m0=0;// higher layer paramater initial cyclic shift + uint8_t nrofSymbols=1; //number of OFDM symbols can be 1-2 for format 1 + uint8_t startingSymbolIndex=0; // resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided + uint16_t startingPRB=0,startingPRB_intraSlotHopping=0; //PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided + uint8_t timeDomainOCC=0; SCM_t channel_model=AWGN;//Rayleigh1_anticorr; - - + int N_RB_DL=273,mu=1; - - unsigned char frame_type = 0; - unsigned char pbch_phase = 0; - - int frame=0,subframe=0; + float target_error_rate=0.01; 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; - + unsigned char frame_type = 0; int loglvl=OAILOG_WARNING; cpuf = get_cpu_freq_GHz(); @@ -142,7 +134,7 @@ int main(int argc, char **argv) randominit(0); - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:o:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:i:P:b:T:n:o:s:S:t:x:y:z:N:F:GR:d:IL")) != -1) { switch (c) { case 'f': write_output_file=1; @@ -196,14 +188,6 @@ int main(int argc, char **argv) break; - case 'i': - interf1=atoi(optarg); - break; - - case 'j': - interf2=atoi(optarg); - break; - case 'n': n_trials = atoi(optarg); break; @@ -292,18 +276,22 @@ int main(int argc, char **argv) break; - case 'P': - pbch_phase = atoi(optarg); - - if (pbch_phase>3) - printf("Illegal PBCH phase (0-3) got %d\n",pbch_phase); - - break; - case 'L': loglvl = atoi(optarg); break; - + case 'i': + nrofSymbols=(uint8_t)atoi(optarg); + break; + case 'P': + format=atoi(optarg); + break; + case 'b': + nr_bit=atoi(optarg); + break; + case 'T': + nacktoack_flag=(uint8_t)atoi(optarg); + target_error_rate=0.001; + 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", @@ -329,11 +317,14 @@ int main(int argc, char **argv) // 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"); + printf("-i Enter number of ofdm symbols for pucch\n"); + printf("-P Enter the format of PUCCH\n"); + printf("-b number of HARQ bits (1-2)\n"); + printf("-T to check nacktoack miss for format 1"); exit (-1); break; } - } - + } logInit(); set_glog(loglvl); T_stdout = 1; @@ -343,10 +334,11 @@ int main(int argc, char **argv) printf("Initializing gNodeB for mu %d, N_RB_DL %d\n",mu,N_RB_DL); + RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *)); RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB)); gNB = RC.gNB[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; frame_parms->nb_antennas_rx = n_rx; @@ -435,9 +427,6 @@ int main(int argc, char **argv) bzero(r_re[i],frame_length_complex_samples*sizeof(int)); } - if (pbch_file_fd!=NULL) { - load_pbch_desc(pbch_file_fd); - } //configure UE @@ -455,63 +444,89 @@ int main(int argc, char **argv) printf("Error at UE NR initialisation\n"); exit(-1); } - int16_t amp=0x1FFF; - int nr_tti_tx=0; //According to standards it is Slot number within a frame for subcarrier spacing configuration μ but not sure why he made the variable name so 4.3.2,38.211 - nr_gold_pbch(UE); - // generate signal -// pucch_config_common_nr should assign values for this if not done before structure in ue being used by functions - uint8_t actual_payload=0,payload_received;//payload bits b7b6...b2b1b0 where b7..b3=0 b2b1=HARQ b0 is SR. payload maximum value is 7 - uint8_t mcs; - int nr_bit=1; // maximum value possible is 2 -/*if(nr_bit==1){ - mcs=table1_mcs[actual_payload]; - } - else{ - mcs=table2_mcs[actual_payload]; - }*/ - uint8_t m0=0;// higher layer paramater initial cyclic shift - uint8_t nrofSymbols=1; //number of OFDM symbols can be 1-2 for format 1 - uint8_t startingSymbolIndex=0; // resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided - uint16_t startingPRB=5; //PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided + uint8_t mcs=0; + startingPRB_intraSlotHopping=N_RB_DL-1; pucch_GroupHopping_t PUCCH_GroupHopping=UE->pucch_config_common_nr->pucch_GroupHopping; uint32_t n_id=UE->pucch_config_common_nr->hoppingId; - printf("\nsnr1=%f\n",snr1); + if((format!=0) && (format!=1)){ + printf("format not supported\n"); + exit(0); + } + if(nacktoack_flag==0){ + if(format==0){ + if(nr_bit==1){ + actual_payload=2; + mcs=table1_mcs[actual_payload]; + } + else if(nr_bit==2){ + actual_payload=6; + mcs=table2_mcs[actual_payload]; + } + else{ + printf("Number of HARQ bits possible is 1-2\n"); + exit(0); + } + } + else { + if(nr_bit==1) + actual_payload=1; + else if(nr_bit==2) + actual_payload=3; + else{ + printf("number of bits carried by PUCCH format1 is 1-2\n"); + } + } + } for(SNR=snr0;SNR<=snr1;SNR=SNR+1){ + ack_nack_errors=0; n_errors = 0; sigma2_dB = 20*log10((double)amp/32767)-SNR; sigma2 = pow(10,sigma2_dB/10); - printf("entering SNR value %f\n",SNR); for (trial=0; trial<n_trials; trial++) { bzero(txdata[0],frame_length_complex_samples*sizeof(int)); - actual_payload=trial%4; - if(nr_bit==1){ - mcs=table1_mcs[actual_payload]; + if(format==0){ + nr_generate_pucch0(UE,txdata,frame_parms,UE->pucch_config_dedicated,amp,nr_tti_tx,m0,mcs,nrofSymbols,startingSymbolIndex,startingPRB); } else{ - mcs=table2_mcs[actual_payload]; - } - nr_generate_pucch0(UE,txdata,frame_parms,UE->pucch_config_dedicated,amp,nr_tti_tx,m0,mcs,nrofSymbols,startingSymbolIndex,startingPRB); - - for (i=0; i<frame_length_complex_samples; i++) { - r_re[0][i]=((double)(((int16_t *)txdata[0])[(i<<1)])/32767 + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); - r_im[0][i]=((double)(((int16_t *)txdata[0])[(i<<1)+1])/32767 + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); - if(r_re[0][i]<-1) - r_re[0][i]=-1; - else if(r_re[0][i]>1) - r_re[0][i]=1; - if(r_im[0][i]<-1) - r_im[0][i]=-1; - else if(r_im[0][i]>1) - r_im[0][0]=1; - ((int16_t *)txdata[0])[(i<<1)] = (int16_t)round(r_re[0][i]*32767); - ((int16_t *)txdata[0])[(i<<1)+1] =(int16_t)round(r_im[0][i]*32767); - + nr_generate_pucch1(UE,txdata,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,0,nr_bit); + } + for(i=0; i<frame_length_complex_samples; i++) { + r_re[aa][i]=((double)(((int16_t *)txdata[0])[(i<<1)])/32767 + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + r_im[aa][i]=((double)(((int16_t *)txdata[0])[(i<<1)+1])/32767+ sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + r_re[aa][i]=r_re[0][i]/(sqrt(sigma2/2)+1); + r_im[aa][i]=r_im[0][i]/(sqrt(sigma2/2)+1); + if(r_re[aa][i]<-1) + r_re[aa][i]=-1; + else if(r_re[aa][i]>1) + r_re[aa][i]=1; + if(r_im[aa][i]<-1) + r_im[aa][i]=-1; + else if(r_im[aa][i]>1) + r_im[aa][i]=1; + ((int16_t *)txdata[aa])[(i<<1)] = (int16_t)round(r_re[aa][i]*32767); + ((int16_t *)txdata[aa])[(i<<1)+1] =(int16_t)round(r_im[aa][i]*32767); + } + if(format==0){ + nr_decode_pucch0(txdata,PUCCH_GroupHopping,n_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,nr_bit); + if(nr_bit==1) + ack_nack_errors+=(((actual_payload^payload_received)&2)>>1); + else + ack_nack_errors+=(((actual_payload^payload_received)&2)>>1) + (((actual_payload^payload_received)&4)>>2); + } + else{ + nr_decode_pucch1(txdata,PUCCH_GroupHopping,n_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + if(nr_bit==1) + ack_nack_errors+=((actual_payload^payload_received)&1); + else + ack_nack_errors+=((actual_payload^payload_received)&1) + (((actual_payload^payload_received)&2)>>1); } - nr_decode_pucch0(txdata,PUCCH_GroupHopping,n_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,nr_bit); n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors; - //printf("actual_payload=%x,payload_received=%x",actual_payload,payload_received); } printf("SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,n_errors); + if((float)ack_nack_errors/(float)(nr_bit*n_trials)<=target_error_rate){ + printf("PUCCH test OK\n"); + break; + } } for (i=0; i<2; i++) { free(s_re[i]); diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index c891f34c5e8ae7bd943e194034c70529083b1f96..1eb02f61bf0b35d540cc17542ed7f8a53331fbf4 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -49,11 +49,6 @@ #include "SCHED_NR/sched_nr.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_ULSCHSIM PHY_VARS_gNB *gNB; @@ -125,45 +120,29 @@ 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; @@ -312,14 +291,6 @@ int main(int argc, char **argv) { break; - case 'P': - pbch_phase = atoi(optarg); - - if (pbch_phase > 3) - printf("Illegal PBCH phase (0-3) got %d\n", pbch_phase); - - break; - case 'm': Imcs = atoi(optarg); break; @@ -382,6 +353,7 @@ int main(int argc, char **argv) { exit(-1); } + RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; @@ -399,46 +371,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)); @@ -449,8 +382,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++) { @@ -464,31 +395,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 /////////// @@ -498,19 +426,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; @@ -519,18 +447,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]; @@ -543,23 +482,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; @@ -576,22 +510,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); @@ -599,13 +531,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 @@ -616,16 +543,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++; @@ -639,7 +565,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); } } @@ -648,6 +573,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"); @@ -655,46 +581,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"); @@ -705,9 +601,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++) { @@ -720,20 +616,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..02595534d8b1fd71e28db962d4a5c1099b5610be --- /dev/null +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -0,0 +1,654 @@ +/* +* 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 "SCHED_NR_UE/fapi_nr_ue_l1.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); +} + +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; + uint8_t precod_nbr_layers = 1; + 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(); + + + 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] = malloc(sizeof(PHY_VARS_gNB)); + gNB = RC.gNB[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); + } + + } + } + + + 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, 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 for gNB -------- + 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.ndi = 0; + rel15_ul->ulsch_pdu_rel15.n_layers = precod_nbr_layers; + /////////////////////////////////////////////////// + + nr_scheduled_response_t scheduled_response; + fapi_nr_ul_config_request_t ul_config; + //fapi_nr_tx_request_t tx_request; + + scheduled_response.module_id = 0; + scheduled_response.CC_id = 0; + scheduled_response.frame = frame; + scheduled_response.slot = slot; + scheduled_response.dl_config = NULL; + scheduled_response.ul_config = &ul_config; + scheduled_response.dl_config = NULL; + + + ul_config.sfn_slot = slot; + ul_config.number_pdus = 1; + ul_config.ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_ULSCH; + ul_config.ul_config_list[0].ulsch_config_pdu.rnti = n_rnti; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.number_rbs = nb_rb; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.start_rb = start_rb; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.number_symbols = nb_symb_sch; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.start_symbol = start_symbol; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.mcs = Imcs; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.ndi = 0; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.rv = 0; + ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.n_layers = precod_nbr_layers; + //there are plenty of other parameters that we don't seem to be using for now. e.g. + //ul_config.ul_config_list[0].ulsch_config_pdu.ulsch_pdu_rel15.absolute_delta_PUSCH = 0; + + // set FAPI parameters for UE, put them in the scheduled response and call + //nr_ue_scheduled_response(&scheduled_response); + + 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 7a1a0405b1d8013a6031511fb04ede418bfab835..5ab6080d79c00bd40fb6a9b0546515c861a546d2 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -116,6 +116,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); @@ -125,6 +126,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 f05e277ac639985e54dcfdd954ed13238b0ff33a..f1210960a572d7425046574f3408a40c16f4c712 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -588,6 +588,7 @@ int8_t nr_ue_decode_mib( mac->type0_pdcch_ss_sfn_c = sfn_c; mac->type0_pdcch_ss_n_c = n_c; + // fill in the elements in config request inside P5 message //mac->phy_config.config_req.pbch_config.system_frame_number = frame; // after calculation @@ -2025,7 +2026,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/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index c9f393cf46fa2e8387e6d871983d9a28dfd0a29c..92464f4448949e66acd24cc01782f1058fac6627 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -72,14 +72,15 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, fapi_nr // L2 Abstraction Layer int8_t handle_dlsch (module_id_t module_id, int cc_id, uint8_t gNB_index, fapi_nr_dci_indication_t *dci_ind, uint8_t *pduP, uint32_t pdu_len){ - // return 0; + return 0; + /* return nr_ue_process_dlsch( module_id, cc_id, gNB_index, dci_ind, pduP, pdu_len); - + */ } int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ @@ -156,6 +157,9 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info){ (dl_info->dci_ind->dci_list+i)->rnti, (dl_info->dci_ind->dci_list+i)->dci_format)) << FAPI_NR_DCI_IND; + AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is void!\n" ); + nr_ue_if_module_inst[module_id]->scheduled_response(&mac->scheduled_response); + /*switch((dl_info->dci_ind->dci_list+i)->dci_type){ case FAPI_NR_DCI_TYPE_0_0: @@ -242,9 +246,6 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info){ dl_info->rx_ind = NULL; dl_info->dci_ind = NULL; - AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is void!\n" ); - nr_ue_if_module_inst[module_id]->scheduled_response(&mac->scheduled_response); - return 0; } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index c1c85227491927b665676af811dfb7ce16b82471..3f642cac4b39e8b02fd494151483b3a9d7e40deb 100755 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -65,6 +65,7 @@ typedef struct { frame_t frame; /// slot int slot; + /// proc is needed to signal back decoded frame number to PHY. However, this is not really FAPI procedure and should be done differently UE_nr_rxtx_proc_t * proc; /// NR UE FAPI-like P7 message, direction: L1 to L2 diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index 75a7825669d2320c062ded059aa1ced9c05987bf..2613babc7bc65406ebcdfe0ed1988afe1c2ae017 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -1124,6 +1124,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->trx_set_gains_func = trx_brf_set_gains; device->openair0_cfg = openair0_cfg; device->priv = (void *)brf; + device->uhd_set_thread_priority = NULL; calibrate_rf(device); diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index bcfa08c7eb23a108c461c5e46d2fe83d533ef801..2e0107916b6a9c86b8213a82add8a463197b6d11 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -43,7 +43,7 @@ int set_device(openair0_device *device) { switch (device->type) { - + case EXMIMO_DEV: LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; @@ -95,6 +95,8 @@ 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) { @@ -102,9 +104,9 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param int ret=0; char *libname; if (flag == RAU_LOCAL_RADIO_HEAD) { - if (getenv("RFSIMULATOR") != NULL) - libname="rfsimulator"; - else + if (getenv("RFSIMULATOR") != NULL) + libname="rfsimulator"; + else libname=OAI_RF_LIBNAME; shlib_fdesc[0].fname="device_init"; } else { @@ -122,6 +124,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param + int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) { int rc=0; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 5530a68f9b88dacdc2df6f1a0dd1c22793c76c54..aca0bd64a27ff39ac06125b42819d85b615abbfc 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -387,6 +387,10 @@ struct openair0_device_t { * \param arg pointer to capabilities or configuration */ void (*configure_rru)(int idx, void *arg); + + /*! \brief set UHD thread priority + */ + void (*uhd_set_thread_priority)(void); }; /* type of device init function, implemented in shared lib */ @@ -405,7 +409,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) @@ -445,6 +449,8 @@ int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *open #define gettid() syscall(__NR_gettid) /*@}*/ + + #ifdef __cplusplus } #endif diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 108c4ca069e07ee71c7b3625cb5b5b8f5c9740ad..1475052b160de3283890c7f271ad45b20d53b534 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -401,6 +401,7 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth device->trx_stop_func = trx_eth_stop; device->trx_set_freq_func = trx_eth_set_freq; device->trx_set_gains_func = trx_eth_set_gains; + device->uhd_set_thread_priority = NULL; if (eth->flags == ETH_RAW_MODE) { device->trx_write_func = trx_eth_write_raw; diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index 7d23cdeb8929391659e668f60c4edf118cd01891..5bbe48df174fce787afa36847c5839a97c15cbf1 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -772,6 +772,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->trx_set_gains_func = trx_exmimo_set_gains; device->openair0_cfg = openair0_cfg; device->priv = (void *)exm; + device->uhd_set_thread_priority = NULL; printf("EXMIMO2: Getting addresses for memory-mapped DMA\n"); diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp index e1a1b768b27cb1413a67cbe6fb54fdea4753d098..aee30d1c7746099906819ec77e2ebe53740b3713 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -405,6 +405,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg){ device->trx_stop_func = trx_lms_stop; device->trx_set_freq_func = trx_lms_set_freq; device->trx_set_gains_func = trx_lms_set_gains; + device->uhd_set_thread_priority = NULL; device->openair0_cfg = openair0_cfg; diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/sodera_lib.cpp index 6f1afe47c0da98cda5b3bcea704d48d66fbd3f36..9b11415631fb7faa2ecea5eefc57f25fd9e9ea55 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/sodera_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/sodera_lib.cpp @@ -706,6 +706,7 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair device->trx_stop_func = trx_sodera_stop; device->trx_set_freq_func = trx_sodera_set_freq; device->trx_set_gains_func = trx_sodera_set_gains; + device->uhd_set_thread_priority = NULL; s->sample_rate = openair0_cfg[0].sample_rate; s->channelscount = openair0_cfg[0].rx_num_channels; diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index a698ab872bb925402e81a8976c9ace1dd028a715..84736dd3cfa4e00fa67e4584334ff99d7929dc11 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -591,7 +591,15 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp for (int j=0; j<nsamps2; j++) { #if defined(__x86_64__) || defined(__i386__) #ifdef __AVX2__ - ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4); + // FK: in some cases the buffer might not be 32 byte aligned, so we cannot use avx2 + + if ((((uintptr_t) buff[i])&0x1F)==0) { + ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4); + } + else { + ((__m128i *)buff[i])[2*j] = _mm_srai_epi16(((__m128i*)buff_tmp[i])[j],4); + ((__m128i *)buff[i])[2*j+1] = _mm_srai_epi16(((__m128i*)buff_tmp[i])[2*j+1],4); + } #else ((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4); #endif @@ -845,6 +853,10 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_ if (bw_gain_adjust==1) { switch ((int)openair0_cfg[0].sample_rate) { + + case 46080000: + break; + case 30720000: break; @@ -870,7 +882,7 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_ default: LOG_E(PHY,"unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate); - exit(-1); + //exit(-1); break; } } @@ -907,6 +919,12 @@ int trx_usrp_reset_stats(openair0_device *device) { return(0); } +/*! \brief Set uhd priority + */ +static void uhd_set_thread_priority(void) { + uhd::set_thread_priority_safe(1.0); +} + #if defined(USRP_REC_PLAY) extern "C" { /*! \brief Initializer for USRP record/playback config @@ -1044,6 +1062,7 @@ extern "C" { device->trx_set_freq_func = trx_usrp_set_freq; device->trx_set_gains_func = trx_usrp_set_gains; device->openair0_cfg = openair0_cfg; + device->uhd_set_thread_priority = uhd_set_thread_priority; std::cerr << "USRP device initialized in subframes replay mode for " << u_sf_loops << " loops. Use mmap=" << use_mmap << std::endl; } else { @@ -1158,6 +1177,13 @@ extern "C" { openair0_cfg[0].rx_bw = 40e6; break; + case 46080000: + //openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 115; + openair0_cfg[0].tx_bw = 40e6; + openair0_cfg[0].rx_bw = 40e6; + break; + case 30720000: // from usrp_time_offset //openair0_cfg[0].samples_per_packet = 2048; @@ -1210,7 +1236,15 @@ extern "C" { } switch ((int)openair0_cfg[0].sample_rate) { - case 30720000: + case 46080000: + s->usrp->set_master_clock_rate(46.08e6); + //openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 115; + openair0_cfg[0].tx_bw = 40e6; + openair0_cfg[0].rx_bw = 40e6; + break; + + case 30720000: s->usrp->set_master_clock_rate(30.72e6); //openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 115; @@ -1361,6 +1395,7 @@ extern "C" { device->trx_set_freq_func = trx_usrp_set_freq; device->trx_set_gains_func = trx_usrp_set_gains; device->openair0_cfg = openair0_cfg; + device->uhd_set_thread_priority = uhd_set_thread_priority; s->sample_rate = openair0_cfg[0].sample_rate; // TODO: @@ -1462,5 +1497,7 @@ extern "C" { #endif return 0; } + + } /*@}*/ diff --git a/targets/ARCH/mobipass/interface.c b/targets/ARCH/mobipass/interface.c index db186a404cbe26a709eb8006dedf555bb0ede111..6e3dc66f49c866d5cc61fc5e28d4ad0b89744906 100644 --- a/targets/ARCH/mobipass/interface.c +++ b/targets/ARCH/mobipass/interface.c @@ -132,6 +132,7 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, device->trx_set_gains_func = mobipass_set_gains; device->trx_write_func = mobipass_write; device->trx_read_func = mobipass_read; + device->uhd_set_thread_priority = NULL; device->priv = mobi; diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index 89964decd50e77c4f514c3207eefd3ae7612b747..6505f08ddb2ab73dfc97782adf57c60dace6d073 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -30,7 +30,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 For the UE, it should be set to the IP address of the eNB @@ -62,6 +62,19 @@ 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 In UE, you can add "-d" to get the softscope +### Channel simulation +The RF channel simulator is called. +In current version all channel paramters are hard coded in the call to: +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. +With path loss = 0 set "-s 5" to see a little noise + #Caveacts Still issues in power control: txgain, rxgain are not used diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index b1a6644e5ede48722718c3e9f3ae46ab7ae49b95..3673a21c11caace980713a0579ef7d2d8943b739 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,43 +27,134 @@ #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; - bool alreadyRead; - uint64_t lastReceivedTS; + openair0_timestamp lastReceivedTS; + openair0_timestamp lastWroteTS; bool headerMode; samplesBlockHeader_t th; char *transferPtr; uint64_t remainToTransfer; char *circularBufEnd; sample_t *circularBuf; + channel_desc_t *channel_model; } buffer_t; typedef struct { int listen_sock, epollfd; - uint64_t nextTimestamp; + openair0_timestamp nextTimestamp; uint64_t typeStamp; 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; + // sqrt(4*noise_figure_watt) is the thermal noise factor (volts) + // fixme: the last constant is pure trial results to make decent noise + const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10; + // 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)); + 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, ""); ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1); ptr->conn_sock=sock; - ptr->alreadyRead=false; ptr->lastReceivedTS=0; + ptr->lastWroteTS=0; ptr->headerMode=true; ptr->transferPtr=(char *)&ptr->th; ptr->remainToTransfer=sizeof(samplesBlockHeader_t); @@ -73,12 +164,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 +240,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 +253,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 @@ -206,21 +319,22 @@ sin_addr: setblocking(sock, notBlocking); allocCirBuf(t, sock); - t->buf[sock].alreadyRead=true; // UE will start blocking on read return 0; } -uint64_t lastW=-1; int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { rfsimulator_state_t *t = device->priv; LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp); + for (int i=0; i<FD_SETSIZE; i++) { - buffer_t *ptr=&t->buf[i]; + buffer_t *b=&t->buf[i]; - if (ptr->conn_sock >= 0 ) { + if (b->conn_sock >= 0 ) { + if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize) + LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS); samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp}; - fullwrite(ptr->conn_sock,&header, sizeof(header), t); + fullwrite(b->conn_sock,&header, sizeof(header), t); sample_t tmpSamples[nsamps][nbAnt]; for(int a=0; a<nbAnt; a++) { @@ -230,16 +344,19 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi tmpSamples[s][a]=in[s]; } - if (ptr->conn_sock >= 0 ) - fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); + if (b->conn_sock >= 0 ) { + fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); + b->lastWroteTS=timestamp+nsamps; + } } } - 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 flushInput(t, 0); + pthread_mutex_unlock(&Sockmutex); return nsamps; } @@ -250,9 +367,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"); } @@ -309,32 +426,35 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) || (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol"); b->headerMode=false; - b->alreadyRead=true; 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(b->lastWroteTS == 0 || ( abs((double)b->lastWroteTS-b->lastReceivedTS) < (double)CirSize), + "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, 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 +471,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,21 +494,40 @@ 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 { + bool have_to_wait; do { have_to_wait=false; 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; + buffer_t *b=&t->buf[sock]; + if ( b->circularBuf) { + LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n", + sock, b->lastWroteTS, + b->lastReceivedTS, + t->nextTimestamp+nsamps); + if ( b->lastReceivedTS > b->lastWroteTS ) { + // The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance + // This occurs for example when UE is in sync mode: it doesn't transmit + // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power + struct complex16 v={0}; + void *samplesVoid[b->th.nbAnt]; + for ( int i=0; i <b->th.nbAnt; i++) + samplesVoid[i]=(void*)&v; + rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0); } + } + + if ( b->circularBuf ) + if ( t->nextTimestamp+nsamps > b->lastReceivedTS ) { + have_to_wait=true; + break; + } } if (have_to_wait) @@ -404,17 +543,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; - } + if ( ptr->circularBuf ) { + 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 +571,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 +598,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 +610,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; @@ -495,6 +642,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->trx_set_gains_func = rfsimulator_set_gains; device->trx_write_func = rfsimulator_write; device->trx_read_func = rfsimulator_read; + device->uhd_set_thread_priority = NULL; /* let's pretend to be a b2x0 */ device->type = USRP_B200_DEV; device->openair0_cfg=&openair0_cfg[0]; @@ -504,5 +652,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/ARCH/tcp_bridge/tcp_bridge.c b/targets/ARCH/tcp_bridge/tcp_bridge.c index 8b287acfa14b24f009e5b30a653504e57c832269..3e2979f8499aef567f6418c8b939cd6cde895383 100644 --- a/targets/ARCH/tcp_bridge/tcp_bridge.c +++ b/targets/ARCH/tcp_bridge/tcp_bridge.c @@ -267,6 +267,7 @@ int device_init(openair0_device* device, openair0_config_t *openair0_cfg) device->trx_set_gains_func = tcp_bridge_set_gains; device->trx_write_func = tcp_bridge_write; device->trx_read_func = tcp_bridge_read; + device->uhd_set_thread_priority = NULL; device->priv = tcp_bridge; diff --git a/targets/ARCH/tcp_bridge/tcp_bridge_oai.c b/targets/ARCH/tcp_bridge/tcp_bridge_oai.c index 153e54a64bba427ed333ac7def69114a13d8c44e..179c0b455eeaca4f4d62f1734b26cd61eeaea82e 100644 --- a/targets/ARCH/tcp_bridge/tcp_bridge_oai.c +++ b/targets/ARCH/tcp_bridge/tcp_bridge_oai.c @@ -313,6 +313,7 @@ int device_init(openair0_device* device, openair0_config_t *openair0_cfg) device->trx_set_freq_func = tcp_bridge_set_freq; device->trx_set_gains_func = tcp_bridge_set_gains; device->trx_write_func = tcp_bridge_write; + device->uhd_set_thread_priority = NULL; if (tcp_bridge->is_enb) { device->trx_read_func = tcp_bridge_read; diff --git a/targets/DOCS/api_icic.xml b/targets/DOCS/api_icic.xml deleted file mode 100644 index 80984fb2363927c6a3002c2af9220367215bdb6d..0000000000000000000000000000000000000000 --- a/targets/DOCS/api_icic.xml +++ /dev/null @@ -1,95 +0,0 @@ - - -<ICIC_API> - <SRUCTURE> - <STRUCTNAME>SBMAP_CONF</STRUCTNAME> - <PATH>openair2/LAYER2/MAC/defs.h</PATH> - <FIELD> - <FIELDNAME>sbmap[13]</FIELDNAME> - <FIELDTYPE>unsigned char</FIELDTYPE> - <DESC>subband map indicates to scheduler allowed SB for eNB</DESC> - </FIELD> - <FIELD> - <FIELDNAME>periodicity</FIELDNAME> - <FIELDTYPE>unsigned char</FIELDTYPE> - <DESC>in millisecond indicate update instant</DESC> - </FIELD> - <FIELD> - <FIELDNAME>first_subframe</FIELDNAME> - <FIELDTYPE>unsigned char</FIELDTYPE> - <DESC>...</DESC> - </FIELD> - <FIELD> - <FIELDNAME>sb_size</FIELDNAME> - <FIELDTYPE>unsigned char</FIELDTYPE> - <DESC>number of PRB in this subband</DESC> - </FIELD> - <FIELD> - <FIELDNAME>nb_active_sb</FIELDNAME> - <FIELDTYPE>unsigned char</FIELDTYPE> - <DESC>indicates the number of set subbands</DESC> - </FIELD> - </SRUCTURE> - - <SRUCTURE> - <STRUCTNAME>eNB_MAC_INST</STRUCTNAME> - <PATH>openair2/LAYER2/MAC/defs.h</PATH> - <FIELD> - ... - </FIELD> - <FIELD> - <FIELDNAME>sbmap_conf</FIELDNAME> - <FIELDTYPE>SBMAP_CONF</FIELDTYPE> - <DESC>subband map configuration for each eNB</DESC> - </FIELD> - <INITPATH>openair2/LAYER2/MAC/main.c</INITPATH> - <INITFUNC>mac_top_init</INITFUNC> - </SRUCTURE> - - <SRUCTURE> - <STRUCTNAME>MAC_xface</STRUCTNAME> - <PATH>openair2/PHY_INTERFACE/defs.h</PATH> - <FIELD> - ... - </FIELD> - <FIELD> - <FIELDNAME>(*get_SB_size)(unsigned char)</FIELDNAME> - <FIELDTYPE>function pointer n</FIELDTYPE> - <DESC>return the number of PRB supported in a subband configuration</DESC> - </FIELD> - <INITPATH>openair2/LAYER2/MAC/main.c</INITPATH> - <INITFUNC>l2_init</INITFUNC> - </SRUCTURE> - - <FUNCTION> - <FUNCNAME>Get_Cell_SBMap</FUNCNAME> - <PARAMS>unsigned char Mod_id</PARAMS> - <RETURN>void</RETURN> - <PROTOPATH>openair2/LAYER2/MAC/defs.h</PROTOPATH> - <IMPLPATH>openair2/LAYER2/MAC/eNB_scheduler.c</IMPLPATH> - <DESC>imlements ICIC algo</DESC> - </FUNCTION> - <FUNCTION> - <FUNCNAME>Get_SB_size</FUNCNAME> - <PARAMS>unsigned char n_rb_dl</PARAMS> - <RETURN>unsigned char </RETURN> - <PROTOPATH>openair1/PHY/LTE_TRANSPORT/proto.h</PROTOPATH> - <IMPLPATH>openair1/PHY/LTE_TRANSPORT/lte_mcs.c</IMPLPATH> - <DESC>return the number of PRB supported in a subband configuration.</DESC> - </FUNCTION> -</ICIC_API> - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/targets/DOCS/oaiemu.doc b/targets/DOCS/oaiemu.doc deleted file mode 100644 index 13433a5f35d916480a21aaeb5ce9cc6315539a60..0000000000000000000000000000000000000000 Binary files a/targets/DOCS/oaiemu.doc and /dev/null differ diff --git a/targets/DOCS/oaisim_walkthrough.pdf b/targets/DOCS/oaisim_walkthrough.pdf deleted file mode 100644 index b6d766e7f6dd825202526e18b13308766b65f3a9..0000000000000000000000000000000000000000 Binary files a/targets/DOCS/oaisim_walkthrough.pdf and /dev/null differ diff --git a/targets/DOCS/openair_header.tex b/targets/DOCS/openair_header.tex deleted file mode 100755 index 14e1baee5aa95cc29c8f2bab58ac9f7e490be938..0000000000000000000000000000000000000000 --- a/targets/DOCS/openair_header.tex +++ /dev/null @@ -1,47 +0,0 @@ -\documentclass[a4paper]{book} -\usepackage{a4wide} -\usepackage{makeidx} -\usepackage{fancyhdr} -\usepackage{graphicx} -\usepackage{multicol} -\usepackage{float} -\usepackage{textcomp} -\usepackage{alltt} -\usepackage{amsmath} -\usepackage{amssymb} -\ifx\pdfoutput\undefined -\usepackage[ps2pdf, - pagebackref=true, - colorlinks=true, - linkcolor=blue - ]{hyperref} -\usepackage{pspicture} -\else -\usepackage[pdftex, - pagebackref=true, - colorlinks=true, - linkcolor=blue - ]{hyperref} -\fi -\usepackage{doxygen} -\usepackage{times} -\makeindex -\setcounter{tocdepth}{1} -\renewcommand{\footrulewidth}{0.4pt} -\begin{document} -\begin{titlepage} -\vspace*{7cm} -\begin{center} -{\Large openair Specifications }\\ -Phyiscal, Medium-Access, Radio-link Control, Packet Data Convergence Protocol and Radio Resource Control Layers\\ -\vspace*{1cm} -{\large Generated by Doxygen 1.3.8}\\ -\vspace*{0.5cm} -{\small Sun Oct 31 19:27:37 2004}\\ -\end{center} -\end{titlepage} -\clearemptydoublepage -\pagenumbering{roman} -\tableofcontents -\clearemptydoublepage -\pagenumbering{arabic} diff --git a/targets/DOCS/path_loss_oaisim.xlsx b/targets/DOCS/path_loss_oaisim.xlsx deleted file mode 100644 index 2ba25b466bb99c3886046669fe8d86348f8ce389..0000000000000000000000000000000000000000 Binary files a/targets/DOCS/path_loss_oaisim.xlsx and /dev/null differ diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf new file mode 100644 index 0000000000000000000000000000000000000000..fdc4894da64a9606bf69b59fb1440d64e55278f4 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf @@ -0,0 +1,298 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "3GPP_gNODEB"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + DL_prefix_type = "NORMAL"; + UL_prefix_type = "NORMAL"; + eutra_band = 78; + downlink_frequency = 3510000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 106; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + MIB_subCarrierSpacingCommon = 30; + MIB_ssb_SubcarrierOffset = 0; + MIB_dmrs_TypeA_Position = 2; + pdcch_ConfigSIB1 = 0; + SIB1_frequencyOffsetSSB = "khz5"; + SIB1_ssb_PeriodicityServingCell = 5; + SIB1_ss_PBCH_BlockPower = -60; + absoluteFrequencySSB = 0; + DL_FreqBandIndicatorNR = 15; + DL_absoluteFrequencyPointA = 15; + DL_offsetToCarrier = 15; + DL_SCS_SubcarrierSpacing = "kHz30"; + DL_SCS_SpecificCarrier_k0 = 0; + DL_carrierBandwidth = 15; + DL_locationAndBandwidth = 15; + DL_BWP_SubcarrierSpacing = "kHz30"; + DL_BWP_prefix_type = "NORMAL"; + UL_FreqBandIndicatorNR = 15; + UL_absoluteFrequencyPointA = 13; + UL_additionalSpectrumEmission = 3; + UL_p_Max = -1; + UL_frequencyShift7p5khz = "TRUE"; + UL_offsetToCarrier = 10; + UL_SCS_SubcarrierSpacing = "kHz30"; + UL_SCS_SpecificCarrier_k0 = 0; + UL_carrierBandwidth = 15; + UL_locationAndBandwidth = 15; + UL_BWP_SubcarrierSpacing = "kHz30"; + UL_BWP_prefix_type = "NORMAL"; + UL_timeAlignmentTimerCommon = "infinity"; + ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" + ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; + ServingCellConfigCommon_ssb_periodicityServingCell = 10; + ServingCellConfigCommon_dmrs_TypeA_Position = 2; + NIA_SubcarrierSpacing = "kHz15"; + ServingCellConfigCommon_ss_PBCH_BlockPower = -60; + referenceSubcarrierSpacing = "kHz15"; + dl_UL_TransmissionPeriodicity = "ms0p5"; + nrofDownlinkSlots = 10; + nrofDownlinkSymbols = 10; + nrofUplinkSlots = 10; + nrofUplinkSymbols = 10; + rach_totalNumberOfRA_Preambles = 63; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice = "oneEighth"; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth = 4; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth = 8; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf = 16; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one = 24; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two = 32; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four = 8; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight = 4; + rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen = 2; + rach_groupBconfigured = "ENABLE"; + rach_ra_Msg3SizeGroupA = 56; + rach_messagePowerOffsetGroupB = "dB0"; + rach_numberOfRA_PreamblesGroupA = 32; + rach_ra_ContentionResolutionTimer = 8; + rsrp_ThresholdSSB = 64; + rsrp_ThresholdSSB_SUL = 64; + prach_RootSequenceIndex_choice = "l839"; + prach_RootSequenceIndex_l839 = 0; + prach_RootSequenceIndex_l139 = 0; + prach_msg1_SubcarrierSpacing = "kHz30"; + restrictedSetConfig = "unrestrictedSet"; + msg3_transformPrecoding = "ENABLE"; + prach_ConfigurationIndex = 10; + prach_msg1_FDM = "one"; + prach_msg1_FrequencyStart = 10; + zeroCorrelationZoneConfig = 10; + preambleReceivedTargetPower = -150; + preambleTransMax = 6; + powerRampingStep = "dB0"; + ra_ResponseWindow = 8; + groupHoppingEnabledTransformPrecoding = "ENABLE"; + msg3_DeltaPreamble = 0; + p0_NominalWithGrant = 0; + PUSCH_TimeDomainResourceAllocation_k2 = 0; + PUSCH_TimeDomainResourceAllocation_mappingType = "typeA"; + PUSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; + pucch_ResourceCommon = 0; + pucch_GroupHopping = "neither"; + hoppingId = 0; + p0_nominal = -30; + PDSCH_TimeDomainResourceAllocation_k0 = 2; + PDSCH_TimeDomainResourceAllocation_mappingType = "typeA"; + PDSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; + rateMatchPatternId = 0; + RateMatchPattern_patternType = "bitmaps"; + symbolsInResourceBlock = "oneSlot"; + periodicityAndPattern = 2; + RateMatchPattern_controlResourceSet = 5; + RateMatchPattern_subcarrierSpacing = "kHz30"; + RateMatchPattern_mode = "dynamic"; + controlResourceSetZero = 0; + searchSpaceZero = 0; + searchSpaceSIB1 = 10; + searchSpaceOtherSystemInformation = 10; + pagingSearchSpace = 10; + ra_SearchSpace = 10; + PDCCH_common_controlResourceSetId = 5; + PDCCH_common_ControlResourceSet_duration = 2; + PDCCH_cce_REG_MappingType = "nonInterleaved"; + PDCCH_reg_BundleSize = 3; + PDCCH_interleaverSize = 3; + PDCCH_shiftIndex = 10; + PDCCH_precoderGranularity = "sameAsREG-bundle"; + PDCCH_TCI_StateId = 32; + tci_PresentInDCI = "ENABLE"; + PDCCH_DMRS_ScramblingID = 0; + SearchSpaceId = 10; + commonSearchSpaces_controlResourceSetId = 5; + SearchSpace_monitoringSlotPeriodicityAndOffset_choice = "sl1"; + SearchSpace_monitoringSlotPeriodicityAndOffset_value = 0; + SearchSpace_duration = 2; + SearchSpace_nrofCandidates_aggregationLevel1 = 0; + SearchSpace_nrofCandidates_aggregationLevel2 = 0; + SearchSpace_nrofCandidates_aggregationLevel4 = 0; + SearchSpace_nrofCandidates_aggregationLevel8 = 0; + SearchSpace_nrofCandidates_aggregationLevel16 = 0; + SearchSpace_searchSpaceType = "common"; + Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1 = 1; + Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2 = 1; + Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4 = 1; + Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8 = 1; + Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16 = 1; + Common_dci_Format2_3_monitoringPeriodicity = 1; + Common_dci_Format2_3_nrofPDCCH_Candidates = 1; + ue_Specific__dci_Formats = "formats0-0-And-1-0"; + RateMatchPatternLTE_CRS_carrierFreqDL = 6; + RateMatchPatternLTE_CRS_carrierBandwidthDL = 6; + RateMatchPatternLTE_CRS_nrofCRS_Ports = 1; + RateMatchPatternLTE_CRS_v_Shift = 0; + RateMatchPatternLTE_CRS_radioframeAllocationPeriod = 1; + RateMatchPatternLTE_CRS_radioframeAllocationOffset = 0; + RateMatchPatternLTE_CRS_subframeAllocation_choice = "oneFrame"; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + sdr_addrs = "type=b200"; + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + 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..26f6eddf520ddfe20290c99adf2304a86654c103 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"; } ); @@ -262,7 +262,7 @@ RUs = ( THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" - parallel_config = "PARALLEL_SINGLE_THREAD"; + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" worker_config = "WORKER_DISABLE"; } 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 428fe8ad030fe5e3d55c3d15baa6999329c6b07a..0f1ea13c663f0db5e60afd5f22b6e065b40b082a 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 @@ -230,7 +230,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"; } );