diff --git a/.gitignore b/.gitignore index 1ed392ef06..2adc5d457c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ cmake_targets/log/ -cmake_targets/ran_build/ +cmake_targets/*/build/ targets/bin/ diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index 6ae75d71ae..b5c34d5b81 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -131,10 +131,10 @@ pipeline { } } - stage ("Start VM -- nu-ue-usrp") { + stage ("Start VM -- nr-ue-usrp") { steps { timeout (time: 5, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant nu-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" + sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" } } } @@ -239,7 +239,7 @@ pipeline { steps { gitlabCommitStatus(name: "Build nr-UE-usrp") { timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant nu-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" + sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" } } } diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran index 6795eab9b8..525ceec525 100644 --- a/ci-scripts/Jenkinsfile-tmp-ran +++ b/ci-scripts/Jenkinsfile-tmp-ran @@ -27,6 +27,8 @@ def pythonExecutor = params.pythonExecutor // Location of the test XML file to be run def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true // Name of the test stage def testStageName = params.pipelineTestStageName @@ -53,6 +55,7 @@ def eNB_Repository def eNB_Branch def eNB_CommitID def eNB_AllowMergeRequestProcess = false +def eNB_TargetBranch pipeline { agent { @@ -107,8 +110,16 @@ pipeline { if (params.pythonTestXmlFile == null) { // picking default testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " } else { - echo "Test XML file : ${testXMLFile}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists("ci-scripts/" + xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } } // If not present picking a default Stage Name if (params.pipelineTestStageName == null) { @@ -150,6 +161,14 @@ pipeline { echo "eNB_CommitID : ${eNB_CommitID}" if (params.eNB_mergeRequest != null) { eNB_AllowMergeRequestProcess = params.eNB_mergeRequest + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } } if (params.EPC_IPAddress == null) { @@ -174,6 +193,13 @@ pipeline { if (allParametersPresent) { echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } } else { echo "Some parameters are missing" sh "./ci-scripts/fail.sh" @@ -185,17 +211,25 @@ pipeline { steps { script { dir ('ci-scripts') { - try { - echo "\u2705 \u001B[32m${testStageName}\u001B[0m" - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] - ]) { - sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBRepository=${eNB_Repository} --eNBBranch=${eNB_Branch} --eNBCommitID=${eNB_CommitID} --eNB_AllowMerge=${eNB_AllowMergeRequestProcess} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${testXMLFile}" + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --eNBRepository=${eNB_Repository} --eNBBranch=${eNB_Branch} --eNBCommitID=${eNB_CommitID} --eNB_AllowMerge=${eNB_AllowMergeRequestProcess} --eNBTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBRepository=${eNB_Repository} --eNBBranch=${eNB_Branch} --eNBCommitID=${eNB_CommitID} --eNB_AllowMerge=${eNB_AllowMergeRequestProcess} --eNBTargetBranch=${eNB_TargetBranch} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } } - } catch (Exception e) { - currentBuild.result = 'FAILURE' + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } } } @@ -327,7 +361,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: ${BUILD_ID}#' 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: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" archiveArtifacts "test_results-${JOB_NAME}.html" } } diff --git a/ci-scripts/active_net_interfaces.awk b/ci-scripts/active_net_interfaces.awk new file mode 100644 index 0000000000..6d1174c1cc --- /dev/null +++ b/ci-scripts/active_net_interfaces.awk @@ -0,0 +1,21 @@ +#/* +# * 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 +# */ +/inet.*brd/{print "interfaceToUse="$NF"done"} diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh index aed449f180..ec774a00ea 100755 --- a/ci-scripts/buildOnVM.sh +++ b/ci-scripts/buildOnVM.sh @@ -94,15 +94,22 @@ function build_on_vm { echo "############################################################" echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" + acquire_vm_create_lock uvt-kvm create $VM_NAME release=xenial --memory $VM_MEMORY --cpu $VM_CPU --unsafe-caching --template ci-scripts/template-host.xml + echo "Waiting for VM to be started" + uvt-kvm wait $VM_NAME --insecure + + VM_IP_ADDR=`uvt-kvm ip $VM_NAME` + echo "$VM_NAME has for IP addr = $VM_IP_ADDR" + release_vm_create_lock + else + echo "Waiting for VM to be started" + uvt-kvm wait $VM_NAME --insecure + + VM_IP_ADDR=`uvt-kvm ip $VM_NAME` + echo "$VM_NAME has for IP addr = $VM_IP_ADDR" fi - echo "Waiting for VM to be started" - uvt-kvm wait $VM_NAME --insecure - - VM_IP_ADDR=`uvt-kvm ip $VM_NAME` - echo "$VM_NAME has for IP addr = $VM_IP_ADDR" - echo "############################################################" echo "Copying GIT repo into VM ($VM_NAME)" echo "############################################################" diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh index 192008d867..e693b07b91 100755 --- a/ci-scripts/createVM.sh +++ b/ci-scripts/createVM.sh @@ -49,6 +49,35 @@ function create_usage { echo "" } +function acquire_vm_create_lock { + local FlockFile="/tmp/vmclone.lck" + local unlocked="0" + touch ${FlockFile} 2>/dev/null + if [[ $? -ne 0 ]] + then + echo "Cannot access lock file ${FlockFile}" + exit 2 + fi + while [ $unlocked -eq 0 ] + do + exec 5>${FlockFile} + flock -nx 5 + if [[ $? -ne 0 ]] + then + echo "Another instance of VM creation is running" + sleep 10 + else + unlocked="1" + fi + done + chmod 666 ${FlockFile} 2>/dev/null +} + +function release_vm_create_lock { + local FlockFile="/tmp/vmclone.lck" + rm -Rf ${FlockFile} +} + function create_vm { echo "############################################################" echo "OAI CI VM script" @@ -60,10 +89,12 @@ function create_vm { echo "############################################################" echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" + acquire_vm_create_lock uvt-kvm create $VM_NAME release=xenial --memory $VM_MEMORY --cpu $VM_CPU --unsafe-caching --template ci-scripts/template-host.xml echo "Waiting for VM to be started" uvt-kvm wait $VM_NAME --insecure VM_IP_ADDR=`uvt-kvm ip $VM_NAME` echo "$VM_NAME has for IP addr = $VM_IP_ADDR" + release_vm_create_lock } diff --git a/ci-scripts/doGitLabMerge.sh b/ci-scripts/doGitLabMerge.sh index dfe2f02b55..dd93ff41b7 100755 --- a/ci-scripts/doGitLabMerge.sh +++ b/ci-scripts/doGitLabMerge.sh @@ -1,4 +1,24 @@ #!/bin/bash +#/* +# * 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 +# */ function usage { echo "OAI GitLab merge request applying script" @@ -83,6 +103,11 @@ esac done +if [[ $TARGET_COMMIT_ID == "latest" ]] +then + TARGET_COMMIT_ID=`git log -n1 --pretty=format:%H origin/$TARGET_BRANCH` +fi + echo "Source Branch is : $SOURCE_BRANCH" echo "Source Commit ID is : $SOURCE_COMMIT_ID" echo "Target Branch is : $TARGET_BRANCH" @@ -101,6 +126,7 @@ git config user.email "jenkins@openairinterface.org" git config user.name "OAI Jenkins" git checkout -f $SOURCE_COMMIT_ID +git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG git merge --ff $TARGET_COMMIT_ID -m "Temporary merge for CI" diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 5c371a99ee..dc101fe7ea 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -42,6 +42,7 @@ ENB_PROCESS_OK = +1 ENB_PROCESS_SEG_FAULT = -11 ENB_PROCESS_ASSERTION = -12 ENB_PROCESS_REALTIME_ISSUE = -13 +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 HSS_PROCESS_FAILED = -2 HSS_PROCESS_OK = +2 MME_PROCESS_FAILED = -3 @@ -58,6 +59,7 @@ import re # reg import pexpect # pexpect import time # sleep import os +import subprocess import xml.etree.ElementTree as ET import logging import datetime @@ -78,6 +80,7 @@ class SSHConnection(): self.eNBBranch = '' self.eNB_AllowMerge = False self.eNBCommitID = '' + self.eNBTargetBranch = '' self.eNBUserName = '' self.eNBPassword = '' self.eNBSourceCodePath = '' @@ -90,7 +93,8 @@ class SSHConnection(): self.ADBUserName = '' self.ADBPassword = '' self.testCase_id = '' - self.testXMLfile = '' + self.testXMLfiles = [] + self.nbTestXMLfiles = 0 self.desc = '' self.Build_eNB_args = '' self.Initialize_eNB_args = '' @@ -101,13 +105,27 @@ class SSHConnection(): self.iperf_args = '' self.iperf_packetloss_threshold = '' self.iperf_profile = '' + self.nbMaxUEtoAttach = -1 self.UEDevices = [] + self.CatMDevices = [] self.UEIPAddresses = [] self.htmlFile = '' self.htmlHeaderCreated = False self.htmlFooterCreated = False - self.htmlUEConnected = 0 + self.htmlUEConnected = -1 self.htmleNBFailureMsg = '' + self.picocom_closure = False + self.idle_sleep_time = 0 + self.htmlTabRefs = [] + self.htmlTabNames = [] + self.htmlTabIcons = [] + self.finalStatus = False + self.eNBOsVersion = '' + self.eNBKernelVersion = '' + self.eNBUhdVersion = '' + self.eNBCpuNb = '' + self.eNBCpuModel = '' + self.eNBCpuMHz = '' def open(self, ipaddress, username, password): count = 0 @@ -169,8 +187,9 @@ class SSHConnection(): elif self.sshresponse == 2: logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') logging.debug('Expected Line : ' + expectedline) - result = re.search('ping |iperf ', str(commandline)) + result = re.search('ping |iperf |picocom', str(commandline)) if result is None: + logging.debug(str(self.ssh.before)) sys.exit(self.sshresponse) else: return -1 @@ -186,64 +205,87 @@ class SSHConnection(): if self.sshresponse == 0: pass elif self.sshresponse == 1: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') + if not self.picocom_closure: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') else: - logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') + logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') def copyin(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) - scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 5) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + while count < 10: + scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) if scp_response == 0: - pass + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True else: - logging.debug('1 - scp_response = ' + str(scp_response)) - sys.exit('SCP failed') - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - pass - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - sys.exit('SCP failed') - elif scp_response == 2: - pass + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + return 0 else: - logging.debug('3 - scp_response = ' + str(scp_response)) - sys.exit('SCP failed') + return -1 def copyout(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) - scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 5) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + while count < 4: + scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) if scp_response == 0: - pass + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True else: - logging.debug('1 - scp_response = ' + str(scp_response)) - sys.exit('SCP failed') - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - pass - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - sys.exit('SCP failed') - elif scp_response == 2: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: pass else: - logging.debug('3 - scp_response = ' + str(scp_response)) sys.exit('SCP failed') def BuildeNB(self): @@ -264,17 +306,21 @@ class SSHConnection(): # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier if (self.eNB_AllowMerge): - if (self.eNBBranch != 'develop') and (self.eNBBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + if self.eNBTargetBranch == '': + if (self.eNBBranch != 'develop') and (self.eNBBranch != 'origin/develop'): + self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.eNBTargetBranch) + self.command('git merge --ff origin/' + self.eNBTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) self.command('source oaienv', '\$', 5) self.command('cd cmake_targets', '\$', 5) 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('mkdir -p build_log_' + SSH.testCase_id, '\$', 5) - self.command('mv log/* ' + 'build_log_' + SSH.testCase_id, '\$', 5) - self.command('mv compile_oai_enb.log ' + 'build_log_' + SSH.testCase_id, '\$', 5) + 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) # Workaround to run with develop-nr self.command('if [ -e ran_build ]; then cp -rf ran_build lte_build_oai; fi', '\$', 30) self.close() @@ -290,7 +336,7 @@ class SSHConnection(): self.command('cd ' + self.EPCSourceCodePath, '\$', 5) self.command('source oaienv', '\$', 5) self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + SSH.testCase_id + '.log &', 'Core state: 2 -> 3', 35) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) else: logging.debug('Using the ltebox simulated HSS') self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) @@ -316,7 +362,7 @@ class SSHConnection(): logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') sys.exit(1) host_name = result.group('host_name') - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + SSH.testCase_id + '.log &', 'MME app initialization complete', 100) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) else: self.command('cd /opt/ltebox/tools', '\$', 5) self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) @@ -332,7 +378,7 @@ class SSHConnection(): self.command('cd ' + self.EPCSourceCodePath, '\$', 5) self.command('source oaienv', '\$', 5) self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + SSH.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) else: self.command('cd /opt/ltebox/tools', '\$', 5) self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) @@ -347,8 +393,20 @@ class SSHConnection(): pStatus = self.CheckProcessExist(initialize_eNB_flag) if (pStatus < 0): self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) + # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) + result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', str(self.ssh.before)) + if result is not None: + eth_interface = result.group('eth_interface') + logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/enb_' + self.testCase_id + '_s1log.pcap', '\$', 5) + self.command('echo $USER; nohup sudo tshark -f "host ' + self.eNBIPAddress +'" -i ' + eth_interface + ' -w /tmp/enb_' + self.testCase_id + '_s1log.pcap > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + self.close() self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) self.command('cd ' + self.eNBSourceCodePath, '\$', 5) # Initialize_eNB_args usually start with -O and followed by the location in repository @@ -356,6 +414,14 @@ class SSHConnection(): extIdx = full_config_file.find('.conf') if (extIdx > 0): extra_options = full_config_file[extIdx + 5:] + # if tracer options is on, compiling and running T Tracer + result = re.search('T_stdout', str(extra_options)) + if result is not None: + logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') + self.command('cd common/utils/T/tracer', '\$', 5) + self.command('make', '\$', 10) + self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', self.eNBUserName, 5) + self.command('cd ' + self.eNBSourceCodePath, '\$', 5) full_config_file = full_config_file[:extIdx + 5] config_path, config_file = os.path.split(full_config_file) else: @@ -372,26 +438,42 @@ class SSHConnection(): # Launch eNB with the modified config file self.command('source oaienv', '\$', 5) self.command('cd cmake_targets', '\$', 5) - self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + self.eNBSourceCodePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(SSH.eNB_instance) + '.sh ', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-run' + str(SSH.eNB_instance) + '.sh ', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm -Rf enb_' + SSH.testCase_id + '.log', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(SSH.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + SSH.testCase_id + '.log ./my-lte-softmodem-run' + str(SSH.eNB_instance) + '.sh', '\$', 5) + self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + self.eNBSourceCodePath + '/' + ci_full_config_file + extra_options + '" > ./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 enb_' + self.testCase_id + '.log', '\$', 5) + self.command('echo ' + self.eNBPassword + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + self.eNBSourceCodePath + '/cmake_targets -o ' + self.eNBSourceCodePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) if not rruCheck: - self.eNBLogFile = 'enb_' + SSH.testCase_id + '.log' + self.eNBLogFile = 'enb_' + self.testCase_id + '.log' time.sleep(6) doLoop = True loopCounter = 10 while (doLoop): loopCounter = loopCounter - 1 if (loopCounter == 0): + # In case of T tracer recording, we may need to kill it + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + 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') self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) - self.CreateHtmlFooter(False) - self.close() + self.CreateHtmlTabFooter(False) + # In case of T tracer recording, we need to kill tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + self.close() + time.sleep(1) + pcap_log_file = 'enb_' + self.testCase_id + '_s1log.pcap' + copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + pcap_log_file, '.') + if (copyin_res == 0): + self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.') sys.exit(1) else: - self.command('stdbuf -o0 cat enb_' + SSH.testCase_id + '.log | egrep --color=never -i "wait|sync"', '\$', 4) + self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) if rruCheck: result = re.search('wait RUs', str(self.ssh.before)) else: @@ -427,7 +509,7 @@ class SSHConnection(): sys.exit('Insufficient Parameter') multi_jobs = [] for device_id in self.UEDevices: - p = Process(target = SSH.InitializeUE_common, args = (device_id,)) + p = Process(target = self.InitializeUE_common, args = (device_id,)) p.daemon = True p.start() multi_jobs.append(p) @@ -435,6 +517,109 @@ class SSHConnection(): job.join() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + def checkDevTTYisUnlocked(self): + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + count = 0 + while count < 5: + self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) + result = re.search('picocom', str(self.ssh.before)) + if result is None: + count = 10 + else: + time.sleep(5) + count = count + 1 + self.close() + + def InitializeCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Disabling the Radio + self.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + # Checking if auto-attach is enabled + self.command('AT^AUTOATT?', 'OK', 5) + result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) + if result is not None: + if result.group('state') is not None: + autoAttachState = int(result.group('state')) + if autoAttachState is not None: + if autoAttachState == 0: + self.command('AT^AUTOATT=1', 'OK', 5) + logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') + # Force closure of picocom but device might still be locked + self.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def TerminateCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Disabling the Radio + self.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + self.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def AttachCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Enabling the Radio + self.command('AT+CFUN=1', 'SIMSTORE,READY', 5) + logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') + time.sleep(4) + # We should check if we register + count = 0 + while count < 3: + self.command('AT+CEREG?', 'OK', 5) + result = re.search('CEREG: 2,(?P[0-9\-]+)', str(self.ssh.before)) + if result is not None: + mDataConnectionState = int(result.group('state')) + if mDataConnectionState is not None: + logging.debug('+CEREG: 2,' + str(mDataConnectionState)) + else: + logging.debug(str(self.ssh.before)) + count = count + 1 + time.sleep(1) + self.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + def AttachUE_common(self, device_id, statusQueue, lock): try: self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -491,22 +676,25 @@ class SSHConnection(): if (pStatus < 0): self.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] status_queue = SimpleQueue() lock = Lock() + nb_ue_to_connect = 0 for device_id in self.UEDevices: - p = Process(target = SSH.AttachUE_common, args = (device_id, status_queue, lock,)) - p.daemon = True - p.start() - multi_jobs.append(p) + if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): + p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,)) + p.daemon = True + p.start() + multi_jobs.append(p) + nb_ue_to_connect = nb_ue_to_connect + 1 for job in multi_jobs: job.join() if (status_queue.empty()): self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) self.AutoTerminateUEandeNB() sys.exit(1) else: @@ -519,16 +707,20 @@ class SSHConnection(): device_id = status_queue.get() message = status_queue.get() if (count < 0): - html_cell = "
UE (" + device_id + ")\n" + message + "
" + html_cell = '
UE (' + device_id + ')\n' + message + '
' else: - html_cell = "
UE (" + device_id + ")\n" + message + ' in ' + str(count + 2) + ' seconds
' + html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' html_queue.put(html_cell) if (attach_status): self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) else: self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) def DetachUE_common(self, device_id): @@ -549,17 +741,21 @@ class SSHConnection(): if (pStatus < 0): self.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] for device_id in self.UEDevices: - p = Process(target = SSH.DetachUE_common, args = (device_id,)) + p = Process(target = self.DetachUE_common, args = (device_id,)) p.daemon = True p.start() multi_jobs.append(p) for job in multi_jobs: job.join() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) def RebootUE_common(self, device_id): try: @@ -608,11 +804,11 @@ class SSHConnection(): pStatus = self.CheckProcessExist(initialize_eNB_flag) if (pStatus < 0): self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] for device_id in self.UEDevices: - p = Process(target = SSH.RebootUE_common, args = (device_id,)) + p = Process(target = self.RebootUE_common, args = (device_id,)) p.daemon = True p.start() multi_jobs.append(p) @@ -633,6 +829,19 @@ class SSHConnection(): sys.exit(1) self.close() + def GetAllCatMDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) + self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) + if terminate_ue_flag == False: + if len(self.CatMDevices) == 0: + logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') + sys.exit(1) + self.close() + def GetAllUEIPAddresses(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': Usage() @@ -679,7 +888,7 @@ class SSHConnection(): self.command('cd ' + self.EPCSourceCodePath, '\$', 5) self.command('cd scripts', '\$', 5) ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee -a ping_' + SSH.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee -a ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' @@ -747,12 +956,12 @@ class SSHConnection(): pStatus = self.CheckProcessExist(initialize_eNB_flag) if (pStatus < 0): self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] i = 0 @@ -760,7 +969,7 @@ class SSHConnection(): status_queue = SimpleQueue() for UE_IPAddress in self.UEIPAddresses: device_id = self.UEDevices[i] - p = Process(target = SSH.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) + p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -771,7 +980,7 @@ class SSHConnection(): if (status_queue.empty()): self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) else: ping_status = True @@ -783,14 +992,14 @@ class SSHConnection(): device_id = status_queue.get() ip_addr = status_queue.get() message = status_queue.get() - html_cell = "
UE (" + device_id + ")\nIP Address  : " + ip_addr + "\n" + message + "
" + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (ping_status): self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) def Iperf_ComputeTime(self): @@ -806,11 +1015,11 @@ class SSHConnection(): logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') sys.exit(1) iperf_bandwidth = result.group('iperf_bandwidth') - if SSH.iperf_profile == 'balanced': + if self.iperf_profile == 'balanced': iperf_bandwidth_new = float(iperf_bandwidth)/ue_num - if SSH.iperf_profile == 'single-ue': + if self.iperf_profile == 'single-ue': iperf_bandwidth_new = float(iperf_bandwidth) - if SSH.iperf_profile == 'unbalanced': + if self.iperf_profile == 'unbalanced': # residual is 2% of max bw residualBW = float(iperf_bandwidth) / 50 if idx == 0: @@ -826,7 +1035,7 @@ class SSHConnection(): return result def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + SSH.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) if result is not None: avgbitrate = result.group('average') @@ -932,7 +1141,7 @@ class SSHConnection(): return 0 def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - if (not os.path.isfile('iperf_server_' + SSH.testCase_id + '_' + device_id + '.log')): + if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') return # Computing the requested bandwidth in float @@ -957,7 +1166,7 @@ class SSHConnection(): req_bandwidth = '%.1f Gbits/sec' % req_bw req_bw = req_bw * 1000000000 - server_file = open('iperf_server_' + SSH.testCase_id + '_' + device_id + '.log', 'r') + server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') br_sum = 0.0 ji_sum = 0.0 pl_sum = 0 @@ -1082,12 +1291,12 @@ class SSHConnection(): # Launch iperf server on EPC side self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f iperf_server_' + SSH.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) port = 5001 + idx if udpIperf: - self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + SSH.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) else: - self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + SSH.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) time.sleep(0.5) self.close() @@ -1104,8 +1313,8 @@ class SSHConnection(): modified_options = modified_options.replace('-R','') time.sleep(0.5) - self.command('rm -f iperf_' + SSH.testCase_id + '_' + device_id + '.log', '\$', 5) - iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee -a iperf_' + SSH.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee -a iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) # TIMEOUT Case if iperf_status < 0: self.close() @@ -1123,15 +1332,15 @@ class SSHConnection(): # in case of failure, retrieve server log if (clientStatus == -1): time.sleep(1) - if (os.path.isfile('iperf_server_' + SSH.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + SSH.testCase_id + '_' + device_id + '.log') - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + SSH.testCase_id + '_' + device_id + '.log', '.') + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: # Single-UE profile -- iperf only on one UE - if SSH.iperf_profile == 'single-ue' and idx != 0: + if self.iperf_profile == 'single-ue' and idx != 0: return useIperf3 = False udpIperf = True @@ -1162,13 +1371,13 @@ class SSHConnection(): if (useIperf3): self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) else: - self.command('rm -f iperf_server_' + SSH.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) result = re.search('-u', str(self.iperf_args)) if result is None: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + SSH.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) udpIperf = False else: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + SSH.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) time.sleep(0.5) self.close() @@ -1183,14 +1392,14 @@ class SSHConnection(): modified_options = str(self.iperf_args) time.sleep(0.5) - self.command('rm -f iperf_' + SSH.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if (useIperf3): - self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee -a iperf_' + SSH.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee -a iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) clientStatus = 0 self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) else: - iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee -a iperf_' + SSH.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee -a iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) if iperf_status < 0: self.close() message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' @@ -1209,9 +1418,9 @@ class SSHConnection(): self.close() if (clientStatus == -1): time.sleep(1) - if (os.path.isfile('iperf_server_' + SSH.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + SSH.testCase_id + '_' + device_id + '.log') - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + SSH.testCase_id + '_' + device_id + '.log', '.') + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1225,13 +1434,13 @@ class SSHConnection(): if (pStatus < 0): self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] i = 0 @@ -1251,7 +1460,7 @@ class SSHConnection(): if (status_queue.empty()): self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) else: iperf_status = True @@ -1266,7 +1475,7 @@ class SSHConnection(): device_id = status_queue.get() ip_addr = status_queue.get() message = status_queue.get() - html_cell = "
UE (" + device_id + ")\nIP Address  : " + ip_addr + "\n" + message + "
" + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (iperf_noperf and iperf_status): self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) @@ -1275,7 +1484,7 @@ class SSHConnection(): else: self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() - self.CreateHtmlFooter(False) + self.CreateHtmlTabFooter(False) sys.exit(1) def CheckProcessExist(self, initialize_eNB_flag): @@ -1313,7 +1522,7 @@ class SSHConnection(): fileCheck = re.search('enb_', str(self.eNBLogFile)) if fileCheck is not None: self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile, '.') - logStatus = self.AnalyzeLogFile_eNB() + logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFile) if logStatus < 0: result = logStatus return result @@ -1384,10 +1593,10 @@ class SSHConnection(): except: os.kill(os.getppid(),signal.SIGUSR1) - def AnalyzeLogFile_eNB(self): - if (not os.path.isfile('./' + SSH.eNBLogFile)): + def AnalyzeLogFile_eNB(self, eNBlogFile): + if (not os.path.isfile('./' + eNBlogFile)): return -1 - enb_log_file = open('./' + SSH.eNBLogFile, 'r') + enb_log_file = open('./' + eNBlogFile, 'r') foundAssertion = False msgAssertion = '' msgLine = 0 @@ -1401,6 +1610,8 @@ class SSHConnection(): rrcReestablishRequest = 0 rrcReestablishComplete = 0 rrcReestablishReject = 0 + rlcDiscardBuffer = 0 + rachCanceledProcedure = 0 uciStatMsgCount = 0 pdcpFailure = 0 ulschFailure = 0 @@ -1420,28 +1631,28 @@ class SSHConnection(): if foundAssertion and (msgLine < 3): msgLine += 1 msgAssertion += str(line) - result = re.search('Generating RRCConnectionSetup', str(line)) + result = re.search('Generating LTE_RRCConnectionSetup|Generating RRCConnectionSetup', str(line)) if result is not None: rrcSetupRequest += 1 - result = re.search('RRCConnectionSetupComplete from UE', str(line)) + result = re.search('LTE_RRCConnectionSetupComplete from UE|RRCConnectionSetupComplete from UE', str(line)) if result is not None: rrcSetupComplete += 1 - result = re.search('Generate RRCConnectionRelease', str(line)) + result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) if result is not None: rrcReleaseRequest += 1 - result = re.search('Generate RRCConnectionReconfiguration', str(line)) + result = re.search('Generate LTE_RRCConnectionReconfiguration|Generate RRCConnectionReconfiguration', str(line)) if result is not None: rrcReconfigRequest += 1 - result = re.search('RRCConnectionReconfigurationComplete from UE rnti', str(line)) + result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti|RRCConnectionReconfigurationComplete from UE rnti', str(line)) if result is not None: rrcReconfigComplete += 1 - result = re.search('RRCConnectionReestablishmentRequest', str(line)) + result = re.search('LTE_RRCConnectionReestablishmentRequest|RRCConnectionReestablishmentRequest', str(line)) if result is not None: rrcReestablishRequest += 1 - result = re.search('RRCConnectionReestablishmentComplete', str(line)) + result = re.search('LTE_RRCConnectionReestablishmentComplete|RRCConnectionReestablishmentComplete', str(line)) if result is not None: rrcReestablishComplete += 1 - result = re.search('RRCConnectionReestablishmentReject', str(line)) + result = re.search('LTE_RRCConnectionReestablishmentReject|RRCConnectionReestablishmentReject', str(line)) if result is not None: rrcReestablishReject += 1 result = re.search('uci->stat', str(line)) @@ -1453,6 +1664,12 @@ class SSHConnection(): result = re.search('ULSCH in error in round', str(line)) if result is not None: ulschFailure += 1 + result = re.search('BAD all_segments_received', str(line)) + if result is not None: + rlcDiscardBuffer += 1 + result = re.search('Canceled RA procedure for UE rnti', str(line)) + if result is not None: + rachCanceledProcedure += 1 enb_log_file.close() self.htmleNBFailureMsg = '' if uciStatMsgCount > 0: @@ -1495,6 +1712,10 @@ class SSHConnection(): rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rrcMsg + '\n' + if rachCanceledProcedure > 0: + rachMsg = 'eNB 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') return ENB_PROCESS_SEG_FAULT @@ -1506,33 +1727,75 @@ class SSHConnection(): logging.debug('\u001B[1;37;41m eNB faced real time issues! \u001B[0m') self.htmleNBFailureMsg += 'eNB faced real time issues!\n' #return ENB_PROCESS_REALTIME_ISSUE + if rlcDiscardBuffer > 0: + rlcMsg = 'eNB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' + logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rlcMsg + '\n' + return ENB_PROCESS_REALTIME_ISSUE return 0 def TerminateeNB(self): self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S daemon --name=enb' + str(SSH.eNB_instance) + '_daemon --stop', '\$', 5) - self.command('rm -f my-lte-softmodem-run' + str(SSH.eNB_instance) + '.sh', '\$', 5) + 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) self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) time.sleep(5) self.command('stdbuf -o0 ps -aux | grep -v grep | grep lte-softmodem', '\$', 5) result = re.search('lte-softmodem', str(self.ssh.before)) if result is not None: self.command('echo ' + self.eNBPassword + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) + time.sleep(5) self.close() - result = re.search('enb_', str(self.eNBLogFile)) + # If tracer options is on, stopping tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFile, '.') - logStatus = self.AnalyzeLogFile_eNB() - if (logStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', logStatus) - self.CreateHtmlFooter(False) - sys.exit(1) - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + time.sleep(1) + pcap_log_file = self.eNBLogFile.replace('.log', '_s1log.pcap') + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + pcap_log_file, '\$', 5) + self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + pcap_log_file, '.') + self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, pcap_log_file, self.eNBSourceCodePath + '/cmake_targets/.') + self.close() + logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('cd ' + self.eNBSourceCodePath + '/common/utils/T/tracer/', '\$', 5) + raw_record_file = self.eNBLogFile.replace('.log', '_record.raw') + replay_log_file = self.eNBLogFile.replace('.log', '_replay.log') + extracted_txt_file = self.eNBLogFile.replace('.log', '_extracted_messages.txt') + extracted_log_file = self.eNBLogFile.replace('.log', '_extracted_messages.log') + self.command('./extract_config -i ' + self.eNBSourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.eNBSourceCodePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) + self.command('echo $USER; nohup ./replay -i ' + self.eNBSourceCodePath + '/cmake_targets/' + raw_record_file + ' > ' + self.eNBSourceCodePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', self.eNBUserName, 5) + self.command('./textlog -d ' + self.eNBSourceCodePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + self.eNBSourceCodePath + '/cmake_targets/' + extracted_log_file, '\$', 5) + self.close() + self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + extracted_log_file, '.') + logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.eNBLogFile = '' else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + result = re.search('enb_', str(self.eNBLogFile)) + 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!' + self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + self.eNBLogFile = '' + return + logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFile) + if (logStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', logStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.eNBLogFile = '' + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateHSS(self): self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) @@ -1548,11 +1811,8 @@ class SSHConnection(): self.command('cd scripts', '\$', 5) self.command('rm -f ./kill_hss.sh', '\$', 5) self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) - time.sleep(2) - self.command('ps -aux | egrep --color=never "hss_sim|simulated_hss" | grep -v grep | awk \'BEGIN{n=0}{pidId[n]=$2;n=n+1}END{print "kill -9 " pidId[0] " " pidId[1]}\' > ./kill_hss.sh', '\$', 5) - self.command('chmod 755 ./kill_hss.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./kill_hss.sh', '\$', 5) - self.command('rm ./kill_hss.sh', '\$', 5) + time.sleep(1) + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) self.close() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) @@ -1603,7 +1863,7 @@ class SSHConnection(): def TerminateUE(self): terminate_ue_flag = True - SSH.GetAllUEDevices(terminate_ue_flag) + self.GetAllUEDevices(terminate_ue_flag) multi_jobs = [] for device_id in self.UEDevices: p = Process(target= SSH.TerminateUE_common, args = (device_id,)) @@ -1625,6 +1885,10 @@ class SSHConnection(): self.eNB_instance = '0' self.TerminateeNB() + def IdleSleep(self): + time.sleep(self.idle_sleep_time) + self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + def LogCollectBuild(self): self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) self.command('cd ' + self.eNBSourceCodePath, '\$', 5) @@ -1639,8 +1903,8 @@ class SSHConnection(): self.command('cd ' + self.eNBSourceCodePath, '\$', 5) self.command('cd cmake_targets', '\$', 5) self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core*', '\$', 60) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core*', '\$', 5) + self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) + self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) self.close() def LogCollectPing(self): @@ -1699,6 +1963,46 @@ class SSHConnection(): self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) self.command('zip spgw.log.zip xGwLog.0', '\$', 60) self.close() + + def RetrieveSystemVersion(self): + if self.eNBIPAddress == 'none': + self.eNBOsVersion = 'Ubuntu 16.04.5 LTS' + self.eNBKernelVersion = '4.15.0-45-generic' + self.eNBUhdVersion = '3.13.0.1-0' + self.eNBCpuNb = '4' + self.eNBCpuModel = 'Intel(R) Core(TM) i5-6200U' + self.eNBCpuMHz = '2399.996 MHz' + return + if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('lsb_release -a', '\$', 5) + result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) + if result is not None: + self.eNBOsVersion = result.group('os_type') + logging.debug('OS is: ' + self.eNBOsVersion) + self.command('uname -r', '\$', 5) + result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) + if result is not None: + self.eNBKernelVersion = result.group('kernel_version') + logging.debug('Kernel Version is: ' + self.eNBKernelVersion) + self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) + result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) + if result is not None: + self.eNBUhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + self.eNBUhdVersion) + self.command('lscpu', '\$', 5) + result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) + if result is not None: + self.eNBCpuNb = result.group('nb_cpus') + logging.debug('nb_cpus: ' + self.eNBCpuNb) + self.eNBCpuModel = result.group('model') + logging.debug('model: ' + self.eNBCpuModel) + self.eNBCpuMHz = result.group('cpu_mhz') + ' MHz' + logging.debug('cpu_mhz: ' + self.eNBCpuMHz) + self.close() + #----------------------------------------------------------- # HTML Reporting.... #----------------------------------------------------------- @@ -1708,9 +2012,14 @@ class SSHConnection(): self.htmlFile.write('\n') self.htmlFile.write('\n') self.htmlFile.write('\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') self.htmlFile.write('\n') - self.htmlFile.write('\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
\n') @@ -1725,60 +2034,113 @@ class SSHConnection(): self.htmlFile.write('
\n') self.htmlFile.write('
\n') + self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (SSH.eNB_AllowMerge): + self.htmlFile.write(' \n') + if (self.eNB_AllowMerge): self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - if (SSH.eNB_AllowMerge): - self.htmlFile.write(' \n') + if (self.eNB_AllowMerge): + self.htmlFile.write(' \n') else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - if (SSH.eNB_AllowMerge): - self.htmlFile.write(' \n') + if (self.eNB_AllowMerge): + self.htmlFile.write(' \n') else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') - if (SSH.eNB_AllowMerge): + if self.eNB_AllowMerge != '': + commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.eNBCommitID, shell=True, universal_newlines=True) + commit_message = commit_message.strip() self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + if (self.eNB_AllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.eNB_AllowMerge): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.eNBTargetBranch == ''): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
Build Start Time (UTC) Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository' + SSH.eNBRepository + ' GIT Repository ' + self.eNBRepository + '
Job Trigger Job Trigger Merge-RequestPush to Branch
Source Branch Source Branch Branch' + SSH.eNBBranch + ' Branch' + self.eNBBranch + '
Source Commit ID Source Commit ID Commit ID' + SSH.eNBCommitID + ' Commit ID ' + self.eNBCommitID + '
Target Branchdevelop Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.eNBTargetBranch + '
\n') terminate_ue_flag = True - SSH.GetAllUEDevices(terminate_ue_flag) + if (self.ADBIPAddress != 'none'): + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + else: + self.UEDevices.append('doughq9rehg') + self.UEDevices.append('dnsgiuahgia') + self.UEDevices.append('uehgieng9') self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

Jump to Final Status

\n') + self.htmlFile.write('

' + str(len(self.UEDevices)) + ' UE(s) is(are) connected to ADB bench server

\n') + self.htmlFile.write('

' + str(len(self.CatMDevices)) + ' CAT-M UE(s) is(are) connected to bench server

\n') self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.close() - self.htmlFile.write('

' + str(self.htmlUEConnected) + ' UE(s) is(are) connected to ADB bench server

\n') - self.htmlFile.write('
\n') - - self.htmlFile.write('

Test Summary for ' + SSH.testXMLfile + '

\n') - self.htmlFile.write(' \n') + def CreateHtmlTabHeader(self): + if (not self.htmlHeaderCreated): + if (not os.path.isfile('test_results.html')): + self.CreateHtmlHeader() + self.htmlFile = open('test_results.html', 'a') + if (self.nbTestXMLfiles == 1): + self.htmlFile.write('
\n') + self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') + else: + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') + if (self.htmlUEConnected == -1): + terminate_ue_flag = True + if (self.ADBIPAddress != 'none'): + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + else: + self.UEDevices.append('doughq9rehg') + self.UEDevices.append('dnsgiuahgia') + self.UEDevices.append('uehgieng9') + self.htmlUEConnected = len(self.UEDevices) + i = 0 while (i < self.htmlUEConnected): self.htmlFile.write(' \n') @@ -1786,26 +2148,64 @@ class SSHConnection(): self.htmlFile.write(' \n') self.htmlHeaderCreated = True - def CreateHtmlFooter(self, passStatus): + def CreateHtmlTabFooter(self, passStatus): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') if passStatus: - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') else: - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write('
Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Status
Final Tab StatusPASSPASS FAILFAIL
\n') - self.htmlFile.write('\n') + self.htmlFile.write('
\n') + self.htmlFooterCreated = False + + def CreateHtmlFooter(self, passStatus): + if (os.path.isfile('test_results.html')): + self.RetrieveSystemVersion() + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write('
\n') + self.htmlFile.write('

\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
eNB Server Characteristics
OS Version' + self.eNBOsVersion + 'Kernel Version' + self.eNBKernelVersion + 'UHD Version' + self.eNBUhdVersion + '
Nb CPUs' + self.eNBCpuNb + 'CPU Model Name' + self.eNBCpuModel + 'CPU Frequency' + self.eNBCpuMHz + '
Final StatusPASS FAIL
\n') + self.htmlFile.write('

\n') + self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') + self.htmlFile.write('\n') self.htmlFile.write('\n') self.htmlFile.close() - self.htmlFooterCreated = False def CreateHtmlTestRow(self, options, status, processesStatus): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile.write(' \n') - self.htmlFile.write(' ' + SSH.testCase_id + '\n') - self.htmlFile.write(' ' + SSH.desc + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') self.htmlFile.write(' ' + str(options) + '\n') if (str(status) == 'OK'): self.htmlFile.write(' ' + str(status) + '\n') @@ -1819,7 +2219,9 @@ class SSHConnection(): elif (processesStatus == ENB_PROCESS_ASSERTION): self.htmlFile.write(' KO - eNB process ended in Assertion\n') elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): - self.htmlFile.write(' KO - eNB process faced Real Time issue(s)/td>\n') + self.htmlFile.write(' KO - eNB process faced Real Time issue(s)\n') + elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE): + self.htmlFile.write(' OK\n') elif (processesStatus == HSS_PROCESS_FAILED): self.htmlFile.write(' KO - HSS process not found\n') elif (processesStatus == MME_PROCESS_FAILED): @@ -1838,10 +2240,11 @@ class SSHConnection(): if result is not None: cellBgColor = 'red' else: - result = re.search('showed|Reestablishment', self.htmleNBFailureMsg) + result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) if result is not None: cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') + self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') self.htmleNBFailureMsg = '' else: i = 0 @@ -1854,8 +2257,8 @@ class SSHConnection(): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): addOrangeBK = False self.htmlFile.write(' \n') - self.htmlFile.write(' ' + SSH.testCase_id + '\n') - self.htmlFile.write(' ' + SSH.desc + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') self.htmlFile.write(' ' + str(options) + '\n') if (str(status) == 'OK'): self.htmlFile.write(' ' + str(status) + '\n') @@ -1869,7 +2272,7 @@ class SSHConnection(): if (i < ue_status): if (not ue_queue.empty()): if (addOrangeBK): - self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') + self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') else: self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') else: @@ -1899,12 +2302,15 @@ def Usage(): print(' --help Show this help.') print(' --mode=[Mode]') print(' TesteNB') + print(' InitiateHtml, FinalizeHtml') print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') print(' --eNBIPAddress=[eNB\'s IP Address]') print(' --eNBRepository=[eNB\'s Repository URL]') print(' --eNBBranch=[eNB\'s Branch Name]') print(' --eNBCommitID=[eNB\'s Commit Number]') + print(' --eNB_AllowMerge=[eNB\'s Allow Merge Request (with target branch)]') + print(' --eNBTargetBranch=[eNB\'s Target Branch in case of a Merge Request]') print(' --eNBUserName=[eNB\'s Login User Name]') print(' --eNBPassword=[eNB\'s Login Password]') print(' --eNBSourceCodePath=[eNB\'s Source Code Path]') @@ -1920,7 +2326,7 @@ def Usage(): print('------------------------------------------------------------') def CheckClassValidity(action,id): - if action != 'Build_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW': + if action != 'Build_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'IdleSleep': logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) return False return True @@ -1940,6 +2346,13 @@ def GetParametersFromXML(action): if (SSH.eNB_instance is None): SSH.eNB_instance = '0' + if action == 'Attach_UE': + nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') + if (nbMaxUEtoAttach is None): + SSH.nbMaxUEtoAttach = -1 + else: + SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach) + if action == 'Ping': SSH.ping_args = test.findtext('ping_args') SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') @@ -1955,6 +2368,13 @@ def GetParametersFromXML(action): logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile) SSH.iperf_profile = 'balanced' + if action == 'IdleSleep': + string_field = test.findtext('idle_sleep_time_in_sec') + if (string_field is None): + SSH.idle_sleep_time = 5 + else: + SSH.idle_sleep_time = int(string_field) + #check if given test is in list #it is in list if one of the strings in 'list' is at the beginning of 'test' def test_in_list(test, list): @@ -2001,6 +2421,9 @@ while len(argvs) > 1: elif re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) SSH.eNBCommitID = matchReg.group(1) + elif re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) + SSH.eNBTargetBranch = matchReg.group(1) elif re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) SSH.eNBUserName = matchReg.group(1) @@ -2042,7 +2465,13 @@ while len(argvs) > 1: SSH.ADBPassword = matchReg.group(1) elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - SSH.testXMLfile = matchReg.group(1) + SSH.testXMLfiles.append(matchReg.group(1)) + SSH.nbTestXMLfiles += 1 + elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) + finalStatus = matchReg.group(1) + if ((finalStatus == 'true') or (finalStatus == 'True')): + SSH.finalStatus = True else: Usage() sys.exit('Invalid Parameter: ' + myArgv) @@ -2108,26 +2537,49 @@ elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): Usage() sys.exit('Insufficient Parameter') SSH.LogCollectIperf() +elif re.match('^InitiateHtml$', mode, re.IGNORECASE): + if SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + count = 0 + foundCount = 0 + while (count < SSH.nbTestXMLfiles): + xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count] + if (os.path.isfile(xml_test_file)): + xmlTree = ET.parse(xml_test_file) + xmlRoot = xmlTree.getroot() + SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) + SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + foundCount += 1 + count += 1 + if foundCount != SSH.nbTestXMLfiles: + SSH.nbTestXMLfiles = foundCount + SSH.CreateHtmlHeader() +elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): + SSH.CreateHtmlFooter(SSH.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE): if SSH.eNBIPAddress == '' or SSH.eNBRepository == '' or SSH.eNBBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or 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') - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, sys.path[0] + "/tcp_iperf_stats.awk", "/tmp") - SSH.CreateHtmlHeader() - + if (SSH.EPCIPAddress != 'none'): + SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, sys.path[0] + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, sys.path[0] + "/active_net_interfaces.awk", "/tmp") #read test_case_list.xml file # if no parameters for XML file, use default value - if SSH.testXMLfile == '': + if (SSH.nbTestXMLfiles != 1): xml_test_file = sys.path[0] + "/test_case_list.xml" else: - xml_test_file = sys.path[0] + "/" + SSH.testXMLfile + xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[0] xmlTree = ET.parse(xml_test_file) xmlRoot = xmlTree.getroot() exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') + if (SSH.nbTestXMLfiles == 1): + SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) all_tests=xmlRoot.findall('testCase') exclusion_tests=exclusion_tests.split() @@ -2165,6 +2617,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE): signal.signal(signal.SIGUSR1, receive_signal) + SSH.CreateHtmlTabHeader() + for test_case_id in todo_tests: for test in all_tests: id = test.get('id') @@ -2194,6 +2648,14 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE): SSH.AttachUE() elif action == 'Detach_UE': SSH.DetachUE() + elif action == 'Initialize_CatM_module': + SSH.InitializeCatM() + elif action == 'Terminate_CatM_module': + SSH.TerminateCatM() + elif action == 'Attach_CatM_module': + SSH.AttachCatM() + elif action == 'Detach_CatM_module': + SSH.TerminateCatM() elif action == 'Ping': SSH.Ping() elif action == 'Iperf': @@ -2212,10 +2674,12 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE): SSH.InitializeSPGW() elif action == 'Terminate_SPGW': SSH.TerminateSPGW() + elif action == 'IdleSleep': + SSH.IdleSleep() else: sys.exit('Invalid action') - SSH.CreateHtmlFooter(True) + SSH.CreateHtmlTabFooter(True) else: Usage() sys.exit('Invalid mode') diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool index 940bcd2852..ed43e26729 100755 --- a/ci-scripts/oai-ci-vm-tool +++ b/ci-scripts/oai-ci-vm-tool @@ -39,7 +39,7 @@ function variant_usage { echo " --variant phy-sim OR -v3" echo " --variant cppcheck OR -v4" echo " --variant gnb-usrp OR -v5" - echo " --variant nu-ue-usrp OR -v6" + echo " --variant nr-ue-usrp OR -v6" echo " --variant enb-ethernet OR -v7" echo " --variant ue-ethernet OR -v8" } @@ -252,9 +252,9 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=8 + NB_PATTERN_FILES=9 BUILD_OPTIONS="--phy_simulators" - VM_MEMORY=4096 + VM_MEMORY=8192 RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b" NBARGS=$[$NBARGS+256] shift @@ -331,9 +331,9 @@ case $key in VM_NAME=ci-phy-sim ARCHIVES_LOC=phy_sim LOG_PATTERN=.Rel15.txt - NB_PATTERN_FILES=8 + NB_PATTERN_FILES=9 BUILD_OPTIONS="--phy_simulators" - VM_MEMORY=4096 + VM_MEMORY=8192 RUN_OPTIONS="./run_exec_autotests.bash -g \"01510*\" -q -np -b" NBARGS=$[$NBARGS+256] ;; @@ -354,7 +354,7 @@ case $key in BUILD_OPTIONS="--gNB -w USRP" NBARGS=$[$NBARGS+256] ;; - nu-ue-usrp) + nr-ue-usrp) VM_NAME=ci-ue-nr-usrp ARCHIVES_LOC=nrue_usrp LOG_PATTERN=.Rel15.txt diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 527fe48edb..da6649ed05 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -441,10 +441,16 @@ function run_test_on_vm { echo "############################################################" echo "Creating test EPC VM ($EPC_VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" + acquire_vm_create_lock uvt-kvm create $EPC_VM_NAME release=xenial --unsafe-caching + echo "Waiting for VM to be started" + uvt-kvm wait $EPC_VM_NAME --insecure + release_vm_create_lock + else + echo "Waiting for VM to be started" + uvt-kvm wait $EPC_VM_NAME --insecure fi - uvt-kvm wait $EPC_VM_NAME --insecure EPC_VM_IP_ADDR=`uvt-kvm ip $EPC_VM_NAME` echo "$EPC_VM_NAME has for IP addr = $EPC_VM_IP_ADDR" scp -o StrictHostKeyChecking=no /etc/apt/apt.conf.d/01proxy ubuntu@$EPC_VM_IP_ADDR:/home/ubuntu diff --git a/ci-scripts/tcp_iperf_stats.awk b/ci-scripts/tcp_iperf_stats.awk index e5c64b6283..3a00e4555f 100644 --- a/ci-scripts/tcp_iperf_stats.awk +++ b/ci-scripts/tcp_iperf_stats.awk @@ -1,3 +1,23 @@ +#/* +# * 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 +# */ BEGIN{max=0;min=10000} { if ($0 ~/Mbits/) { diff --git a/ci-scripts/xml_files/enb_usrp210_band40_build.xml b/ci-scripts/xml_files/enb_usrp210_band40_build.xml new file mode 100644 index 0000000000..8f9489b03e --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band40_build.xml @@ -0,0 +1,54 @@ + + + build-tab + Build + wrench + + 010101 + 050101 060101 070101 + + + + + Build_eNB + Build eNB (USRP) + -w USRP -c --eNB + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + Initialize_SPGW + Initialize SPGW + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band40_epc_closure.xml b/ci-scripts/xml_files/enb_usrp210_band40_epc_closure.xml new file mode 100644 index 0000000000..ad34381a2a --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band40_epc_closure.xml @@ -0,0 +1,47 @@ + + + epc-closure + EPC-Closure + log-out + + 050201 060201 070201 + + + + + Terminate_HSS + Terminate HSS + + + + Terminate_MME + Terminate MME + + + + Terminate_SPGW + Terminate SPGW + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm1.xml new file mode 100644 index 0000000000..d5a25c7fa7 --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm1.xml @@ -0,0 +1,119 @@ + + + test-05-tm1 + Test-05MHz-TM1 + tasks + + 040101 + 030104 040301 040501 040602 040601 040603 040642 040641 040643 040401 040201 030201 + + + + + Initialize_eNB + Initialize eNB (TDD/Band40/5MHz) + -O ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 25 + + + + Iperf + iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(balanced) + -u -b 6.5M -t 30 -i 1 + 50 + balanced + + + + Iperf + iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(single-ue) + -u -b 6.5M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(unbalanced) + -u -b 6.5M -t 30 -i 1 + 50 + unbalanced + + + + Iperf + iperf (5MHz - UL/2Mbps/UDP)(30 sec)(balanced) + -u -b 2M -t 30 -i 1 -R + 50 + balanced + + + + Iperf + iperf (5MHz - UL/2Mbps/UDP)(30 sec)(single-ue) + -u -b 2M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/2Mbps/UDP)(30 sec)(unbalanced) + -u -b 2M -t 30 -i 1 -R + 50 + unbalanced + + + diff --git a/ci-scripts/xml_files/enb_usrpb210_band40.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_10mhz_tm1.xml similarity index 51% rename from ci-scripts/xml_files/enb_usrpb210_band40.xml rename to ci-scripts/xml_files/enb_usrp210_band40_test_10mhz_tm1.xml index 1af1c319cf..ef50933d4a 100644 --- a/ci-scripts/xml_files/enb_usrpb210_band40.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_10mhz_tm1.xml @@ -21,43 +21,21 @@ --> + test-10-tm1 + Test-10MHz-TM1 + tasks - 010101 - 050101 060101 070101 040101 - 030104 040301 040501 040602 040601 040603 040642 040641 040643 040401 040201 030201 + 040101 030114 040301 040511 040612 040611 040613 040652 040651 040653 040401 040201 030201 - 050201 060201 070201 - - - - Build_eNB - Build eNB (USRP) - -w USRP -c --eNB - - - - Initialize_eNB - Initialize eNB (TDD/Band40/5MHz) - -O ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf --codingw --fepw - - Initialize_eNB Initialize eNB (TDD/Band40/10MHz/info) - -O ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf --codingw --fepw + -O ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf - - Initialize_eNB - Initialize eNB (TDD/Band40/20MHz/info) - -O ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf --codingw --fepw - - Terminate_eNB Terminate eNB @@ -83,13 +61,6 @@ Detach UE - - Ping - ping (5MHz - 20 sec) - -c 20 - 25 - - Ping ping (10MHz - 20 sec) @@ -97,30 +68,6 @@ 25 - - Iperf - iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(balanced) - -u -b 6.5M -t 30 -i 1 - 50 - balanced - - - - Iperf - iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(single-ue) - -u -b 6.5M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(unbalanced) - -u -b 6.5M -t 30 -i 1 - 50 - unbalanced - - Iperf iperf (10MHz - DL/13.5Mbps/UDP)(30 sec)(balanced) @@ -145,30 +92,6 @@ unbalanced - - Iperf - iperf (5MHz - UL/2Mbps/UDP)(30 sec)(balanced) - -u -b 2M -t 30 -i 1 -R - 50 - balanced - - - - Iperf - iperf (5MHz - UL/2Mbps/UDP)(30 sec)(single-ue) - -u -b 2M -t 30 -i 1 -R - 50 - single-ue - - - - Iperf - iperf (5MHz - UL/2Mbps/UDP)(30 sec)(unbalanced) - -u -b 2M -t 30 -i 1 -R - 50 - unbalanced - - Iperf iperf (10MHz - UL/2Mbps/UDP)(30 sec)(balanced) @@ -193,34 +116,4 @@ unbalanced - - Initialize_HSS - Initialize HSS - - - - Initialize_MME - Initialize MME - - - - Initialize_SPGW - Initialize SPGW - - - - Terminate_HSS - Terminate HSS - - - - Terminate_MME - Terminate MME - - - - Terminate_SPGW - Terminate SPGW - - diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1_not_run.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1_not_run.xml new file mode 100644 index 0000000000..9a96baac3f --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_20mhz_tm1_not_run.xml @@ -0,0 +1,119 @@ + + + test-20-tm1 + Test-20MHz-TM1 + tasks + + 040101 + 030124 040301 040521 040622 040621 040623 040662 040661 040663 040401 040201 030201 + + + + + Initialize_eNB + Initialize eNB (TDD/Band40/20MHz/info) + -O ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (20MHz - 20 sec) + -c 20 + 25 + + + + Iperf + iperf (20MHz - DL/13.5Mbps/UDP)(30 sec)(balanced) + -u -b 13.5M -t 30 -i 1 + 50 + balanced + + + + Iperf + iperf (20MHz - DL/13.5Mbps/UDP)(30 sec)(single-ue) + -u -b 13.5M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (20MHz - DL/13.5Mbps/UDP)(30 sec)(unbalanced) + -u -b 13.5M -t 30 -i 1 + 50 + unbalanced + + + + Iperf + iperf (20MHz - UL/2Mbps/UDP)(30 sec)(balanced) + -u -b 2M -t 30 -i 1 -R + 50 + balanced + + + + Iperf + iperf (20MHz - UL/2Mbps/UDP)(30 sec)(single-ue) + -u -b 2M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (20MHz - UL/2Mbps/UDP)(30 sec)(unbalanced) + -u -b 2M -t 30 -i 1 -R + 50 + unbalanced + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band40_tracer.xml b/ci-scripts/xml_files/enb_usrp210_band40_tracer.xml new file mode 100644 index 0000000000..dceb6be97a --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band40_tracer.xml @@ -0,0 +1,65 @@ + + + tracer-test + T-Tracer + duplicate + + 040101 + 030100 040300 040401 040201 030201 + + + + + Initialize_eNB + Initialize eNB (TDD/Band40/5MHz) with T Tracer on + -O ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf --T_stdout 0 + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach single UE + 1 + + + + Detach_UE + Detach UE + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band7.xml b/ci-scripts/xml_files/enb_usrp210_band7.xml deleted file mode 100644 index 0785ad815d..0000000000 --- a/ci-scripts/xml_files/enb_usrp210_band7.xml +++ /dev/null @@ -1,350 +0,0 @@ - - - - 010101 - 050101 060101 070101 040101 - 030101 040301 040501 040603 040604 040605 040606 040607 040641 040642 040643 040644 040401 040201 030201 - 030111 040301 040511 040613 040614 040615 040616 040617 040651 040652 040653 040654 040401 040201 030201 - 030121 040301 040521 040623 040624 040625 040626 040627 040662 040661 040663 040664 040401 040201 030201 - 050201 060201 070201 - - - - - Build_eNB - Build eNB (USRP) - -w USRP -c --eNB - - - - Initialize_eNB - Initialize eNB (FDD/Band7/5MHz) - -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --codingw --fepw - - - - Initialize_eNB - Initialize eNB (FDD/Band7/10MHz) - -O ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf --codingw --fepw - - - - Initialize_eNB - Initialize eNB (FDD/Band7/20MHz) - -O ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf --codingw --fepw - - - - Terminate_eNB - Terminate eNB - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - - Ping - ping (5MHz - 20 sec) - -c 20 - 5 - - - - Ping - ping (10MHz - 20 sec) - -c 20 - 5 - - - - Ping - ping (20MHz - 20 sec) - -c 20 - 5 - - - - Iperf - iperf (5MHz - DL/15Mbps/UDP)(30 sec)(balanced profile) - -u -b 15M -t 30 -i 1 - 50 - balanced - - - - Iperf - iperf (5MHz - DL/15Mbps/UDP)(30 sec)(single-ue profile) - -u -b 15M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (5MHz - DL/15Mbps/UDP)(30 sec)(unbalanced profile) - -u -b 15M -t 30 -i 1 - 50 - unbalanced - - - - Iperf - iperf (5MHz - DL/TCP)(30 sec)(single-ue profile) - -t 30 -i 1 -fm - 50 - single-ue - - - - Iperf - iperf (5MHz - DL/TCP)(30 sec)(balanced profile) - -t 30 -i 1 -fm - 50 - balanced - - - - Iperf - iperf (5MHz - UL/9Mbps/UDP)(30 sec)(balanced profile) - -u -b 9M -t 30 -i 1 -R - 50 - balanced - - - - Iperf - iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) - -u -b 9M -t 30 -i 1 -R - 50 - single-ue - - - - Iperf - iperf (5MHz - UL/TCP)(30 sec)(single-ue profile) - -t 30 -i 1 -fm -R - 50 - single-ue - - - - Iperf - iperf (5MHz - UL/TCP)(30 sec)(balanced profile) - -t 30 -i 1 -fm -R - 50 - balanced - - - - Iperf - iperf (10MHz - DL/30Mbps/UDP)(30 sec)(balanced profile) - -u -b 30M -t 30 -i 1 - 50 - balanced - - - - Iperf - iperf (10MHz - DL/30Mbps/UDP)(30 sec)(single-ue profile) - -u -b 30M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (10MHz - DL/30Mbps/UDP)(30 sec)(unbalanced profile) - -u -b 30M -t 30 -i 1 - 50 - unbalanced - - - - Iperf - iperf (10MHz - DL/TCP)(30 sec)(single-ue profile) - -t 30 -i 1 -fm - 50 - single-ue - - - - Iperf - iperf (10MHz - DL/TCP)(30 sec)(balanced profile) - -t 30 -i 1 -fm - 50 - balanced - - - - Iperf - iperf (10MHz - UL/20Mbps/UDP)(30 sec)(balanced profile) - -u -b 20M -t 30 -i 1 -R - 50 - balanced - - - - Iperf - iperf (10MHz - UL/20Mbps/UDP)(30 sec)(single-ue profile) - -u -b 20M -t 30 -i 1 -R - 50 - single-ue - - - - Iperf - iperf (10MHz - UL/TCP)(30 sec)(single-ue profile) - -t 30 -i 1 -fm -R - 50 - single-ue - - - - Iperf - iperf (10MHz - UL/TCP)(30 sec)(balanced profile) - -t 30 -i 1 -fm -R - 50 - balanced - - - - Iperf - iperf (20MHz - DL/70Mbps/UDP)(30 sec)(balanced profile) - -u -b 70M -t 30 -i 1 - 50 - balanced - - - - Iperf - iperf (20MHz - DL/70Mbps/UDP)(30 sec)(single-ue profile) - -u -b 70M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (20MHz - DL/70Mbps/UDP)(30 sec)(unbalanced profile) - -u -b 70M -t 30 -i 1 - 50 - unbalanced - - - - Iperf - iperf (20MHz - DL/TCP)(30 sec)(single-ue profile) - -t 30 -i 1 -fm - 50 - single-ue - - - - Iperf - iperf (20MHz - DL/TCP)(30 sec)(balanced profile) - -t 30 -i 1 -fm - 50 - balanced - - - - Iperf - iperf (20MHz - UL/20Mbps/UDP)(30 sec)(balanced profile) - -u -b 20M -t 30 -i 1 -R - 50 - balanced - - - - Iperf - iperf (20MHz - UL/20Mbps/UDP)(30 sec)(single-ue profile) - -u -b 20M -t 30 -i 1 -R - 50 - single-ue - - - - Iperf - iperf (20MHz - UL/TCP)(30 sec)(single-ue profile) - -t 30 -i 1 -fm -R - 50 - single-ue - - - - Iperf - iperf (20MHz - UL/TCP)(30 sec)(balanced profile) - -t 30 -i 1 -fm -R - 50 - balanced - - - - Initialize_HSS - Initialize HSS - - - - Initialize_MME - Initialize MME - - - - Initialize_SPGW - Initialize SPGW - - - - Terminate_HSS - Terminate HSS - - - - Terminate_MME - Terminate MME - - - - Terminate_SPGW - Terminate SPGW - - - diff --git a/ci-scripts/xml_files/enb_usrp210_band7_build.xml b/ci-scripts/xml_files/enb_usrp210_band7_build.xml new file mode 100644 index 0000000000..31ee57e941 --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band7_build.xml @@ -0,0 +1,54 @@ + + + build-tab + Build + wrench + + 010101 + 050101 060101 070101 + + + + + Build_eNB + Build eNB (USRP) + -w USRP -c --eNB + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + Initialize_SPGW + Initialize SPGW + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band7_epc_closure.xml b/ci-scripts/xml_files/enb_usrp210_band7_epc_closure.xml new file mode 100644 index 0000000000..07fb6951f8 --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band7_epc_closure.xml @@ -0,0 +1,47 @@ + + + epc-closure + EPC-Closure + log-out + + 050201 060201 070201 + + + + + Terminate_HSS + Terminate HSS + + + + Terminate_MME + Terminate MME + + + + Terminate_SPGW + Terminate SPGW + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml new file mode 100644 index 0000000000..0057eaefa4 --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml @@ -0,0 +1,143 @@ + + + test-05-tm1 + Test-05MHz-TM1 + tasks + + 040101 + 030101 040301 040501 040603 040604 040605 040606 040607 040641 040642 040643 040644 040401 040201 030201 + + + + + Initialize_eNB + Initialize eNB (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(balanced profile) + -u -b 15M -t 30 -i 1 + 50 + balanced + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(single-ue profile) + -u -b 15M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(unbalanced profile) + -u -b 15M -t 30 -i 1 + 50 + unbalanced + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm + 50 + balanced + + + + Iperf + iperf (5MHz - UL/9Mbps/UDP)(30 sec)(balanced profile) + -u -b 9M -t 30 -i 1 -R + 50 + balanced + + + + Iperf + iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) + -u -b 9M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm -R + 50 + balanced + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1.xml new file mode 100644 index 0000000000..92ec1efa6e --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band7_test_10mhz_tm1.xml @@ -0,0 +1,143 @@ + + + test-10-tm1 + Test-10MHz-TM1 + tasks + + 040101 + 030111 040301 040511 040613 040614 040615 040616 040617 040651 040652 040653 040654 040401 040201 030201 + + + + + Initialize_eNB + Initialize eNB (FDD/Band7/10MHz) + -O ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (10MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (10MHz - DL/30Mbps/UDP)(30 sec)(balanced profile) + -u -b 30M -t 30 -i 1 + 50 + balanced + + + + Iperf + iperf (10MHz - DL/30Mbps/UDP)(30 sec)(single-ue profile) + -u -b 30M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (10MHz - DL/30Mbps/UDP)(30 sec)(unbalanced profile) + -u -b 30M -t 30 -i 1 + 50 + unbalanced + + + + Iperf + iperf (10MHz - DL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm + 50 + single-ue + + + + Iperf + iperf (10MHz - DL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm + 50 + balanced + + + + Iperf + iperf (10MHz - UL/20Mbps/UDP)(30 sec)(balanced profile) + -u -b 20M -t 30 -i 1 -R + 50 + balanced + + + + Iperf + iperf (10MHz - UL/20Mbps/UDP)(30 sec)(single-ue profile) + -u -b 20M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (10MHz - UL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm -R + 50 + single-ue + + + + Iperf + iperf (10MHz - UL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm -R + 50 + balanced + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band7_test_20mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band7_test_20mhz_tm1.xml new file mode 100644 index 0000000000..b6c441b19a --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band7_test_20mhz_tm1.xml @@ -0,0 +1,143 @@ + + + test-20-tm1 + Test-20MHz-TM1 + tasks + + 040101 + 030121 040301 040521 040623 040624 040625 040662 040401 040201 030201 + + 040626 040627 040661 040663 040664 + + + Initialize_eNB + Initialize eNB (FDD/Band7/20MHz) + -O ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (20MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (20MHz - DL/70Mbps/UDP)(30 sec)(balanced profile) + -u -b 70M -t 30 -i 1 + 50 + balanced + + + + Iperf + iperf (20MHz - DL/70Mbps/UDP)(30 sec)(single-ue profile) + -u -b 70M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (20MHz - DL/70Mbps/UDP)(30 sec)(unbalanced profile) + -u -b 70M -t 30 -i 1 + 50 + unbalanced + + + + Iperf + iperf (20MHz - DL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm + 50 + single-ue + + + + Iperf + iperf (20MHz - DL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm + 50 + balanced + + + + Iperf + iperf (20MHz - UL/12Mbps/UDP)(30 sec)(balanced profile) + -u -b 12M -t 30 -i 1 -R + 50 + balanced + + + + Iperf + iperf (20MHz - UL/17Mbps/UDP)(30 sec)(single-ue profile) + -u -b 17M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (20MHz - UL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm -R + 50 + single-ue + + + + Iperf + iperf (20MHz - UL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm -R + 50 + balanced + + + diff --git a/ci-scripts/xml_files/enb_usrp210_band7_tracer.xml b/ci-scripts/xml_files/enb_usrp210_band7_tracer.xml new file mode 100644 index 0000000000..4c74f52b0f --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band7_tracer.xml @@ -0,0 +1,65 @@ + + + tracer-test + T-Tracer + duplicate + + 040101 + 030100 040300 040401 040201 030201 + + + + + Initialize_eNB + Initialize eNB (FDD/Band7/5MHz) with T Tracer on + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --T_stdout 0 + + + + Terminate_eNB + Terminate eNB + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach single UE + 1 + + + + Detach_UE + Detach UE + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40.xml b/ci-scripts/xml_files/if4p5_usrp210_band40.xml deleted file mode 100644 index 9c1b721bef..0000000000 --- a/ci-scripts/xml_files/if4p5_usrp210_band40.xml +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - 010101 - 050101 060101 070101 040101 - 030104 030105 040301 040501 040602 040401 040201 030201 030202 - 050201 060201 070201 - - - - - - - Build_eNB - Build eNB (USRP -- Ethernet Fronthaul) - -t ETHERNET -w USRP -c --eNB - - - - Initialize_eNB - Initialize RRU (TDD/Band40) - -O ci-scripts/conf_files/rru.tdd.band40.conf --codingw --fepw - 0 - - - - Initialize_eNB - Initialize RCC (TDD/Band40/5MHz) - -O ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf --codingw --fepw - 1 - - - - Initialize_eNB - Initialize RRU (TDD/Band40) - -O ci-scripts/conf_files/rru.tdd.band40.conf --codingw --fepw - 0 - - - - Initialize_eNB - Initialize RCC (TDD/Band40/10MHz/info) - -O ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf --codingw --fepw - 1 - - - - Initialize_eNB - Initialize RRU (TDD/Band40) - -O ci-scripts/conf_files/rru.tdd.band40.conf --codingw --fepw - 0 - - - - Initialize_eNB - Initialize RCC (TDD/Band40/20MHz/info) - -O ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf --codingw --fepw - 1 - - - - Terminate_eNB - Terminate RCC - 1 - - - - Terminate_eNB - Terminate RRU - 0 - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - - Ping - ping (5MHz - 20 sec) - -c 20 - 25 - - - - Ping - ping (10MHz - 20 sec) - -c 20 - 25 - - - - Ping - ping (20MHz - 20 sec) - -c 20 - 25 - - - - Iperf - iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(single-ue) - -u -b 6.5M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (10MHz - DL/13.5Mbps/UDP)(30 sec)(single-ue) - -u -b 13.5M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (20MHz - DL/13.5Mbps/UDP)(30 sec)(single-ue) - -u -b 13.5M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (5MHz - UL/2Mbps/UDP)(30 sec)(single-ue) - -u -b 2M -t 30 -i 1 -R - 50 - single-ue - - - - Iperf - iperf (10MHz - UL/2Mbps/UDP)(30 sec)(single-ue) - -u -b 2M -t 30 -i 1 -R - 50 - single-ue - - - - Iperf - iperf (20MHz - UL/2Mbps/UDP)(30 sec)(single-ue) - -u -b 2M -t 30 -i 1 -R - 50 - single-ue - - - - Initialize_HSS - Initialize HSS - - - - Initialize_MME - Initialize MME - - - - Initialize_SPGW - Initialize SPGW - - - - Terminate_HSS - Terminate HSS - - - - Terminate_MME - Terminate MME - - - - Terminate_SPGW - Terminate SPGW - - - diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_build.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_build.xml new file mode 100644 index 0000000000..5bb7db5299 --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band40_build.xml @@ -0,0 +1,55 @@ + + + build-tab + Build + wrench + + 010101 + 050101 060101 070101 + + + + + + Build_eNB + Build eNB (USRP -- Ethernet Fronthaul) + -t ETHERNET -w USRP -c --eNB + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + Initialize_SPGW + Initialize SPGW + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_epc_closure.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_epc_closure.xml new file mode 100644 index 0000000000..c04a8b3cf4 --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band40_epc_closure.xml @@ -0,0 +1,48 @@ + + + epc-closure + EPC-Closure + log-out + + 050201 060201 070201 + + + + + + Terminate_HSS + Terminate HSS + + + + Terminate_MME + Terminate MME + + + + Terminate_SPGW + Terminate SPGW + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_test_05mhz.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_test_05mhz.xml new file mode 100644 index 0000000000..1de23d05d6 --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band40_test_05mhz.xml @@ -0,0 +1,103 @@ + + + test-05 + Test-05MHz + tasks + + 040101 + 030104 030105 040301 040501 040602 040642 040401 040201 030201 030202 + + + + + + Initialize_eNB + Initialize RRU (TDD/Band40) + -O ci-scripts/conf_files/rru.tdd.band40.conf + 0 + + + + Initialize_eNB + Initialize RCC (TDD/Band40/5MHz) + -O ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf + 1 + + + + Terminate_eNB + Terminate RCC + 1 + + + + Terminate_eNB + Terminate RRU + 0 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 25 + + + + Iperf + iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(single-ue) + -u -b 6.5M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/2Mbps/UDP)(30 sec)(single-ue) + -u -b 2M -t 30 -i 1 -R + 50 + single-ue + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_test_10mhz.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_test_10mhz.xml new file mode 100644 index 0000000000..e68a893247 --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band40_test_10mhz.xml @@ -0,0 +1,110 @@ + + + test-10 + Test-10MHz + tasks + + 000001 + + + 040101 + 030114 030115 040301 040511 040612 040652 040401 040201 030201 030202 + + + + IdleSleep + No Test in IF4.5 for FDD-10MHz + 10 + + + + Initialize_eNB + Initialize RRU (TDD/Band40) + -O ci-scripts/conf_files/rru.tdd.band40.conf + 0 + + + + Initialize_eNB + Initialize RCC (TDD/Band40/10MHz/info) + -O ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf + 1 + + + + Terminate_eNB + Terminate RCC + 1 + + + + Terminate_eNB + Terminate RRU + 0 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (10MHz - 20 sec) + -c 20 + 25 + + + + Iperf + iperf (10MHz - DL/13.5Mbps/UDP)(30 sec)(single-ue) + -u -b 13.5M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (10MHz - UL/2Mbps/UDP)(30 sec)(single-ue) + -u -b 2M -t 30 -i 1 -R + 50 + single-ue + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band40_test_20mhz_not_run.xml b/ci-scripts/xml_files/if4p5_usrp210_band40_test_20mhz_not_run.xml new file mode 100644 index 0000000000..150515757f --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band40_test_20mhz_not_run.xml @@ -0,0 +1,110 @@ + + + test-20 + Test-20MHz + tasks + + 000001 + + + 040101 + 030124 030125 040301 040521 040622 040662 040401 040201 030201 030202 + + + + IdleSleep + No Test in IF4.5 for FDD-20MHz + 10 + + + + Initialize_eNB + Initialize RRU (TDD/Band40) + -O ci-scripts/conf_files/rru.tdd.band40.conf + 0 + + + + Initialize_eNB + Initialize RCC (TDD/Band40/20MHz/info) + -O ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf + 1 + + + + Terminate_eNB + Terminate RCC + 1 + + + + Terminate_eNB + Terminate RRU + 0 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (20MHz - 20 sec) + -c 20 + 25 + + + + Iperf + iperf (20MHz - DL/13.5Mbps/UDP)(30 sec)(single-ue) + -u -b 13.5M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (20MHz - UL/2Mbps/UDP)(30 sec)(single-ue) + -u -b 2M -t 30 -i 1 -R + 50 + single-ue + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band7.xml b/ci-scripts/xml_files/if4p5_usrp210_band7.xml deleted file mode 100644 index a3e5ecd72c..0000000000 --- a/ci-scripts/xml_files/if4p5_usrp210_band7.xml +++ /dev/null @@ -1,217 +0,0 @@ - - - - - 010101 - 050101 060101 070101 040101 - 030101 030102 040301 040501 040604 040642 040401 040201 030201 030202 - 050201 060201 070201 - - - - - - - Build_eNB - Build eNB (USRP -- Ethernet Fronthaul) - -t ETHERNET -w USRP -c --eNB - - - - Initialize_eNB - Initialize RRU (FDD/Band7) - -O ci-scripts/conf_files/rru.fdd.band7.conf --codingw --fepw - 1 - - - - Initialize_eNB - Initialize RCC (FDD/Band7/5MHz) - -O ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf --codingw --fepw - 0 - - - - Initialize_eNB - Initialize RRU (FDD/Band7) - -O ci-scripts/conf_files/rru.fdd.band7.conf --codingw --fepw - 1 - - - - Initialize_eNB - Initialize RCC (FDD/Band7/10MHz) - -O ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf --codingw --fepw - 0 - - - - Initialize_eNB - Initialize RRU (FDD/Band7) - -O ci-scripts/conf_files/rru.fdd.band7.conf --codingw --fepw - 1 - - - - Initialize_eNB - Initialize RCC (FDD/Band7/20MHz) - -O ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf --codingw --fepw - 0 - - - - Terminate_eNB - Terminate RCC - 0 - - - - Terminate_eNB - Terminate RRU - 1 - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - - Ping - ping (5MHz - 20 sec) - -c 20 - 5 - - - - Iperf - iperf (5MHz - DL/15Mbps/UDP)(30 sec)(single-ue profile) - -u -b 15M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) - -u -b 9M -t 30 -i 1 -R - 50 - single-ue - - - - Ping - ping (10MHz - 20 sec) - -c 20 - 5 - - - - Iperf - iperf (10MHz - DL/32Mbps/UDP)(30 sec)(single-ue profile) - -u -b 32M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (10MHz - UL/20Mbps/UDP)(30 sec)(single-ue profile) - -u -b 20M -t 30 -i 1 -R - 50 - single-ue - - - - Ping - ping (20MHz - 20 sec) - -c 20 - 5 - - - - Iperf - iperf (20MHz - DL/70Mbps/UDP)(30 sec)(single-ue profile) - -u -b 70M -t 30 -i 1 - 50 - single-ue - - - - Iperf - iperf (20MHz - UL/20Mbps/UDP)(30 sec)(single-ue profile) - -u -b 20M -t 30 -i 1 -R - 50 - single-ue - - - - Initialize_HSS - Initialize HSS - - - - Initialize_MME - Initialize MME - - - - Initialize_SPGW - Initialize SPGW - - - - Terminate_HSS - Terminate HSS - - - - Terminate_MME - Terminate MME - - - - Terminate_SPGW - Terminate SPGW - - - diff --git a/ci-scripts/xml_files/if4p5_usrp210_band7_build.xml b/ci-scripts/xml_files/if4p5_usrp210_band7_build.xml new file mode 100644 index 0000000000..a0be9253db --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band7_build.xml @@ -0,0 +1,55 @@ + + + build-tab + Build + wrench + + 010101 + 050101 060101 070101 040101 + + + + + + Build_eNB + Build eNB (USRP -- Ethernet Fronthaul) + -t ETHERNET -w USRP -c --eNB + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + Initialize_SPGW + Initialize SPGW + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band7_epc_closure.xml b/ci-scripts/xml_files/if4p5_usrp210_band7_epc_closure.xml new file mode 100644 index 0000000000..8587db959d --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band7_epc_closure.xml @@ -0,0 +1,48 @@ + + + epc-closure + EPC-Closure + log-out + + 050201 060201 070201 + + + + + + Terminate_HSS + Terminate HSS + + + + Terminate_MME + Terminate MME + + + + Terminate_SPGW + Terminate SPGW + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band7_test_05mhz.xml b/ci-scripts/xml_files/if4p5_usrp210_band7_test_05mhz.xml new file mode 100644 index 0000000000..b0501e9875 --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band7_test_05mhz.xml @@ -0,0 +1,103 @@ + + + test-05 + Test-05MHz + tasks + + 040101 + 030101 030102 040301 040501 040604 040642 040401 040201 030201 030202 + + + + + + Initialize_eNB + Initialize RRU (FDD/Band7) + -O ci-scripts/conf_files/rru.fdd.band7.conf + 1 + + + + Initialize_eNB + Initialize RCC (FDD/Band7/5MHz) + -O ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf + 0 + + + + Terminate_eNB + Terminate RCC + 0 + + + + Terminate_eNB + Terminate RRU + 1 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(single-ue profile) + -u -b 15M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) + -u -b 9M -t 30 -i 1 -R + 50 + single-ue + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band7_test_10mhz.xml b/ci-scripts/xml_files/if4p5_usrp210_band7_test_10mhz.xml new file mode 100644 index 0000000000..86bd6521ca --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band7_test_10mhz.xml @@ -0,0 +1,110 @@ + + + test-10 + Test-10MHz + tasks + + 000001 + + + 040101 + 030111 030112 040301 040511 040614 040652 040401 040201 030201 030202 + + + + IdleSleep + No Test in IF4.5 for FDD-10MHz + 10 + + + + Initialize_eNB + Initialize RRU (FDD/Band7) + -O ci-scripts/conf_files/rru.fdd.band7.conf + 1 + + + + Initialize_eNB + Initialize RCC (FDD/Band7/10MHz) + -O ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf + 0 + + + + Terminate_eNB + Terminate RCC + 0 + + + + Terminate_eNB + Terminate RRU + 1 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (10MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (10MHz - DL/32Mbps/UDP)(30 sec)(single-ue profile) + -u -b 32M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (10MHz - UL/5Mbps/UDP)(30 sec)(single-ue profile) + -u -b 5M -t 30 -i 1 -R + 60 + single-ue + + + diff --git a/ci-scripts/xml_files/if4p5_usrp210_band7_test_20mhz.xml b/ci-scripts/xml_files/if4p5_usrp210_band7_test_20mhz.xml new file mode 100644 index 0000000000..63997fc925 --- /dev/null +++ b/ci-scripts/xml_files/if4p5_usrp210_band7_test_20mhz.xml @@ -0,0 +1,110 @@ + + + test-20 + Test-20MHz + tasks + + 000001 + + + 040101 + 030121 030122 040301 040521 040624 040662 040401 040201 030201 030202 + + + + IdleSleep + No Test in IF4.5 for FDD-20MHz + 10 + + + + Initialize_eNB + Initialize RRU (FDD/Band7) + -O ci-scripts/conf_files/rru.fdd.band7.conf + 1 + + + + Initialize_eNB + Initialize RCC (FDD/Band7/20MHz) + -O ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf + 0 + + + + Terminate_eNB + Terminate RCC + 0 + + + + Terminate_eNB + Terminate RRU + 1 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (20MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (20MHz - DL/50Mbps/UDP)(30 sec)(single-ue profile) + -u -b 50M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (20MHz - UL/10Mbps/UDP)(30 sec)(single-ue profile) + -u -b 10M -t 30 -i 1 -R + 50 + single-ue + + + diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 668c3acc2e..253a78726a 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -21,7 +21,7 @@ # Author: laurent THOMAS, Lionel GAUTHIER -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 3.0) ############################################# # Base directories, compatible with legacy OAI building @@ -167,13 +167,14 @@ endif() # set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC ") + "${CMAKE_C_FLAGS} ${C_FLAGS_PROCESSOR} -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC") # add autotools definitions that were maybe used! +set(MKVER "'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'") set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'" + "${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D${MKVER}" ) set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D'MAKE_VERSION(a,b,c)=((a)*256+(b)*16+c)'" + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D${MKVER}" ) add_definitions("-DASN_DISABLE_OER_SUPPORT") @@ -252,6 +253,7 @@ add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace") add_boolean_option(DISABLE_LOG_X False "Deactivate all LOG_* macros") add_boolean_option(USRP_REC_PLAY False "Enable USRP record playback mode") add_boolean_option(UE_NAS_USE_TUN False "Enable UE NAS TUN device instead of ue_ip.ko") +add_boolean_option(NOS1 False "Allows to run without a EPC") add_boolean_option(BASIC_SIMULATOR False "Has to be True when building the basic simulator, False otherwise") add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering") @@ -260,17 +262,17 @@ add_boolean_option(ENABLE_ITTI True "ITTI is internal messaging, should remain e set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) if (${ENABLE_ITTI}) add_library(ITTI - # add .h files if depend on (this one is generated) ${OCP_ITTI}/intertask_interface.cpp ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/memory_pools.c ) +add_dependencies(ITTI rrc_flag) set(ITTI_LIB ITTI) set(GTPU_need_ITTI ${OPENAIR3_DIR}/GTPV1-U/gtpv1u_eNB.c) endif (${ENABLE_ITTI}) ############################# -# ASN.1 grammar C code generation & dependancies +# ASN.1 grammar C code generation & dependencies ################################ # A difficulty: asn1c generates C code of a un-predictable list of files # so, generate the c from asn1c once at cmake run time @@ -278,8 +280,6 @@ endif (${ENABLE_ITTI}) # (so creating new asn.1 objects instead of modifying the object attributes) # New C code source file, cmake must be re-run (instead of re-running make only) ############# -# set(asn1c_call "${OPENAIR_CMAKE}/tools/generate_asn1") -# set(fix_asn1c_call "${OPENAIR_CMAKE}/tools/fix_asn1") set(asn1_generated_dir ${OPENAIR_BIN_DIR}) set(protoc_call "${OPENAIR_CMAKE}/tools/generate_protobuf") @@ -290,7 +290,6 @@ set(protobuf_generated_dir ${OPENAIR_BIN_DIR}) add_list2_option(RRC_ASN1_VERSION "Rel15" "ASN.1 version of RRC interface" "Rel8" "Rel10" "Rel14" "CBA") -Message("RRC_ASN1_VERSION is ${RRC_ASN1_VERSION}") if (${RRC_ASN1_VERSION} STREQUAL "Rel8") make_version(RRC_VERSION 8 6 0) @@ -320,34 +319,25 @@ elseif (${RRC_ASN1_VERSION} STREQUAL "Rel15") endif (${RRC_ASN1_VERSION} STREQUAL "Rel8") add_definitions(-DRRC_VERSION=${RRC_VERSION}) set (RRC_FULL_DIR ${asn1_generated_dir}/RRC_${RRC_ASN1_VERSION}) -message("calling asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example -D ${RRC_FULL_DIR} ${RRC_GRAMMAR}") -execute_process(COMMAND mkdir -p ${RRC_FULL_DIR} - COMMAND env asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example -D ${RRC_FULL_DIR} ${RRC_GRAMMAR} - RESULT_VARIABLE ret - OUTPUT_QUIET - ERROR_QUIET) + +# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make +execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${RRC_FULL_DIR}" "${RRC_GRAMMAR}" + RESULT_VARIABLE ret) if (NOT ${ret} STREQUAL 0) message(FATAL_ERROR "${ret}: error") endif (NOT ${ret} STREQUAL 0) - file(GLOB rrc_source ${RRC_FULL_DIR}/*.c) -file(GLOB rrc_h ${RRC_FULL_DIR}/*.h) -set(rrc_h ${rrc_h} ${RRC_FULL_DIR}/asn_constant.h) -set_source_files_properties(${rrc_source} PROPERTIES COMPILE_FLAGS -w) # suppress warnings from generated code -add_library(RRC_LIB ${rrc_h} ${rrc_source} - ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg.c - ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.c) -include_directories ("${RRC_FULL_DIR}") - -# add the command to generate the source code -# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make -add_custom_command ( - OUTPUT ${RRC_FULL_DIR}/asn_constant.h - COMMAND mkdir -p ${RRC_FULL_DIR} - COMMAND env asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example -D ${RRC_FULL_DIR} ${RRC_GRAMMAR} +add_custom_target ( + rrc_flag ALL + ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${RRC_FULL_DIR}" "${RRC_GRAMMAR}" DEPENDS ${RRC_GRAMMAR} ) +add_library(RRC_LIB ${rrc_source} + ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg.c + ${OPENAIR2_DIR}/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.c) +add_dependencies(RRC_LIB rrc_flag) +include_directories ("${RRC_FULL_DIR}") #NR RRC ###### @@ -361,34 +351,26 @@ endif (${NR_RRC_ASN1_VERSION} STREQUAL "NR_Rel15") add_definitions(-DNR_RRC_VERSION=${NR_RRC_VERSION}) set (NR_RRC_FULL_DIR ${asn1_generated_dir}/${NR_RRC_ASN1_VERSION}) -message("calling ASN1C_PREFIX=NR_ asn1c -pdu=all -fcompound-names -findirect-choice -gen-PER -no-gen-OER -no-gen-example -D ${NR_RRC_FULL_DIR} ${NR_RRC_GRAMMAR}") -execute_process(COMMAND mkdir -p ${NR_RRC_FULL_DIR} - COMMAND env "ASN1C_PREFIX=NR_" asn1c -fcompound-names -findirect-choice -gen-PER -no-gen-OER -no-gen-example -D ${NR_RRC_FULL_DIR} ${NR_RRC_GRAMMAR} - RESULT_VARIABLE ret - OUTPUT_QUIET - ERROR_QUIET) - -#if (NOT ${ret} STREQUAL 0) -# message(FATAL_ERROR "${ret}: error") -#endif (NOT ${ret} STREQUAL 0) - +# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make +execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${NR_RRC_FULL_DIR}" "${NR_RRC_GRAMMAR}" "NR_" "-findirect-choice" + RESULT_VARIABLE ret) +if (NOT ${ret} STREQUAL 0) + message(FATAL_ERROR "${ret}: error") +endif () file(GLOB nr_rrc_source ${NR_RRC_FULL_DIR}/*.c) file(GLOB nr_rrc_h ${NR_RRC_FULL_DIR}/*.h) -set(nr_rrc_h ${nr_rrc_h} ${NR_RRC_FULL_DIR}/NR_asn_constant.h) -#set_source_files_properties(${nr_rrc_source} PROPERTIES COMPILE_FLAGS -w) # suppress warnings from generated code -add_library(NR_RRC_LIB - ${nr_rrc_h} - ${nr_rrc_source} - ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c) +add_custom_target ( + nr_rrc_flag ALL + ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${NR_RRC_FULL_DIR}" "${NR_RRC_GRAMMAR}" "NR_" "-findirect-choice" + DEPENDS ${NR_RRC_GRAMMAR} + ) + +add_library(NR_RRC_LIB ${nr_rrc_h} ${nr_rrc_source} + ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c + ) +add_dependencies(NR_RRC_LIB nr_rrc_flag) include_directories ("${NR_RRC_FULL_DIR}") -# add the command to generate the source code -# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make - -add_custom_command (OUTPUT ${NR_RRC_FULL_DIR}/NR_asn_constant.h - COMMAND mkdir -p ${NR_RRC_FULL_DIR} - DEPENDS ${NR_RRC_GRAMMAR} - ) # S1AP # Same limitation as described in RRC: unknown generated file list @@ -425,30 +407,26 @@ endif(${S1AP_RELEASE} STREQUAL "R8") add_definitions(-DS1AP_VERSION=${S1AP_VERSION}) set(S1AP_ASN_DIR ${S1AP_DIR}/MESSAGES/ASN1/${S1AP_RELEASE}) set(S1AP_C_DIR ${asn1_generated_dir}/S1AP_${S1AP_RELEASE}) -message("calling ASN1C_PREFIX=S1AP_ asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${S1AP_C_DIR} ${S1AP_ASN_DIR}/${S1AP_ASN_FILES}") -execute_process(COMMAND mkdir -p ${S1AP_C_DIR} - COMMAND env "ASN1C_PREFIX=S1AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${S1AP_C_DIR} ${S1AP_ASN_DIR}/${S1AP_ASN_FILES} - RESULT_VARIABLE ret - OUTPUT_QUIET - ERROR_QUIET) + +# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make +execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${S1AP_C_DIR}" "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" "S1AP_" -fno-include-deps + RESULT_VARIABLE ret) if (NOT ${ret} STREQUAL 0) message(FATAL_ERROR "${ret}: error") endif (NOT ${ret} STREQUAL 0) file(GLOB S1AP_source ${S1AP_C_DIR}/*.c) -file(GLOB s1ap_h ${S1AP_C_DIR}/*.h) -set(s1ap_h ${s1ap_h}) - -add_custom_command ( - OUTPUT ${S1AP_C_DIR}/S1AP_asn_constant.h - COMMAND mkdir -p ${S1AP_C_DIR} - COMMAND env "ASN1C_PREFIX=S1AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${S1AP_C_DIR} ${S1AP_ASN_DIR}/${S1AP_ASN_FILES} - DEPENDS ${S1AP_ASN_DIR}/${S1AP_ASN_FILES} +add_custom_target ( + s1ap_flag ALL + ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${S1AP_C_DIR}" "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" "S1AP_" -fno-include-deps + DEPENDS "${S1AP_ASN_DIR}/${S1AP_ASN_FILES}" ) + add_library(S1AP_LIB ${S1AP_source} ${S1AP_DIR}/s1ap_common.c ) +add_dependencies(S1AP_LIB rrc_flag s1ap_flag) include_directories ("${S1AP_C_DIR}") include_directories ("${S1AP_DIR}") @@ -467,6 +445,7 @@ add_library(S1AP_ENB ${S1AP_DIR}/s1ap_eNB_trace.c ${S1AP_DIR}/s1ap_eNB_ue_context.c ) +add_dependencies(S1AP_ENB rrc_flag s1ap_flag) #X2AP # Same limitation as described in RRC/S1AP: unknown generated file list @@ -494,24 +473,19 @@ endif(${X2AP_RELEASE} STREQUAL "R8") add_definitions(-DX2AP_VERSION=${X2AP_VERSION}) set(X2AP_ASN_DIR ${X2AP_DIR}/MESSAGES/ASN1/${X2AP_RELEASE}) set(X2AP_C_DIR ${asn1_generated_dir}/X2AP_${X2AP_RELEASE}) -message("calling ASN1C_PREFIX=X2AP_ asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${X2AP_C_DIR} ${X2AP_ASN_DIR}/${X2AP_ASN_FILES}") -execute_process(COMMAND mkdir -p ${X2AP_C_DIR} - COMMAND env "ASN1C_PREFIX=X2AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${X2AP_C_DIR} ${X2AP_ASN_DIR}/${X2AP_ASN_FILES} - RESULT_VARIABLE ret - OUTPUT_QUIET - ERROR_QUIET) + +# Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make +execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${X2AP_C_DIR}" "${X2AP_ASN_DIR}/${X2AP_ASN_FILES}" "X2AP_" -fno-include-deps + RESULT_VARIABLE ret) if (NOT ${ret} STREQUAL 0) message(FATAL_ERROR "${ret}: error") endif (NOT ${ret} STREQUAL 0) + file(GLOB X2AP_source ${X2AP_C_DIR}/*.c) -file(GLOB x2ap_h ${X2AP_C_DIR}/*.h) -set(x2ap_h ${x2ap_h}) - -add_custom_command ( - OUTPUT ${X2AP_C_DIR}/X2AP_asn_constant.h - COMMAND mkdir -p ${X2AP_C_DIR} - COMMAND env "ASN1C_PREFIX=X2AP_" asn1c -pdu=all -fcompound-names -fno-include-deps -gen-PER -no-gen-OER -no-gen-example -D ${X2AP_C_DIR} ${X2AP_ASN_DIR}/${X2AP_ASN_FILES} +add_custom_target ( + x2_flag ALL + COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${X2AP_C_DIR}" "${X2AP_ASN_DIR}/${X2AP_ASN_FILES}" "X2AP_" -fno-include-deps DEPENDS ${X2AP_ASN_DIR}/${X2AP_ASN_FILES} ) @@ -519,6 +493,7 @@ add_library(X2AP_LIB ${X2AP_source} ${X2AP_DIR}/x2ap_common.c ) +add_dependencies(X2AP_LIB rrc_flag x2_flag) include_directories ("${X2AP_C_DIR}") include_directories ("${X2AP_DIR}") @@ -532,6 +507,7 @@ add_library(X2AP_ENB ${X2AP_DIR}/x2ap_eNB_management_procedures.c ${X2AP_DIR}/x2ap_eNB_generate_messages.c ) +add_dependencies(X2AP_ENB rrc_flag x2_flag) # Hardware dependant options ################################### @@ -539,6 +515,10 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4 add_list1_option(NB_ANTENNAS_TX "4" "Number of antennas in transmission" "1" "2" "4") add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "OAI_LMSSDR") +if (NOT ${RF_BOARD} STREQUAL "None") + add_definitions(-DMANAGED_RF=1) +endif() + add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET") #NOKIA config enhancement @@ -639,6 +619,8 @@ 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") @@ -661,7 +643,6 @@ add_boolean_option(NAS_NETLINK False "useless ??? Must be True to compile nasmes add_boolean_option(OAI_NW_DRIVER_USE_NETLINK True "????") add_boolean_option(USE_MME False "this flag is used only one time in lte-softmodem.c") -add_list_string_option(PACKAGE_NAME "NotDefined" "As per attribute name") add_boolean_option(MESSAGE_CHART_GENERATOR False "For generating sequence diagrams") add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams") add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams") @@ -669,11 +650,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchang add_boolean_option(UE_EXPANSION False "enable UE_EXPANSION with max 256 UE") add_boolean_option(PHY_TX_THREAD False "enable UE_EXPANSION with max 256 UE") add_boolean_option(PRE_SCD_THREAD False "enable UE_EXPANSION with max 256 UE") - -######################## -# Include order -########################## -add_boolean_option(ENB_MODE True "Swap the include directories between openair2 and openair3" ) +add_boolean_option(UESIM_EXPANSION False "enable UESIM_EXPANSION with max 256 UE") ########################## # SCHEDULING/REAL-TIME/PERF options @@ -694,7 +671,7 @@ add_boolean_option(EXMIMO_IOT True "????") add_boolean_option(LOCALIZATION False "???") add_integer_option(MAX_NUM_CCs 1 "????") add_boolean_option(MU_RECEIVER False "????") -add_boolean_option(PHYSIM True "for L1 simulators (dlsim, ulsim, ...)") +add_boolean_option(PHYSIM False "for L1 simulators (dlsim, ulsim, ...)") add_boolean_option(PHY_CONTEXT True "not clear: must remain False for dlsim") add_boolean_option(PHY_EMUL False "not clear: must remain False for dlsim") add_boolean_option(SMBV False "Rohde&Schwarz SMBV100A vector signal generator") @@ -776,19 +753,13 @@ include_directories("${OPENAIR_BIN_DIR}") #include_directories("${include_dirs_all}") # Legacy exact order -if(ENB_MODE) - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") -else() - include_directories("${OPENAIR3_DIR}/COMMON") - include_directories("${OPENAIR3_DIR}/UTILS") - include_directories("${OPENAIR2_DIR}/COMMON") - include_directories("${OPENAIR2_DIR}/UTIL") - include_directories("${OPENAIR2_DIR}/UTIL/LOG") -endif() + +include_directories("${OPENAIR2_DIR}/COMMON") +include_directories("${OPENAIR2_DIR}/UTIL") +include_directories("${OPENAIR2_DIR}/UTIL/LOG") +include_directories("${OPENAIR3_DIR}/COMMON") +include_directories("${OPENAIR3_DIR}/UTILS") + include_directories("${NFAPI_DIR}/nfapi/public_inc") include_directories("${NFAPI_DIR}/common/public_inc") include_directories("${NFAPI_DIR}/pnf/public_inc") @@ -927,6 +898,7 @@ add_library(FLEXRAN_AGENT ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c ${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c ) +add_dependencies(FLEXRAN_AGENT rrc_flag) set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT) #include_directories(${OPENAIR2_DIR}/ENB_APP) @@ -992,6 +964,7 @@ set(UTIL_SRC # ${OPENAIR2_DIR}/UTIL/OTG/otg_rx.c ) add_library(UTIL ${UTIL_SRC}) +add_dependencies(UTIL rrc_flag) #set(OMG_SUMO_SRC # ${OPENAIR2_DIR}/UTIL/OMG/client_traci_OMG.c @@ -1031,7 +1004,7 @@ set(SCHED_SRC ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c ) add_library(SCHED_LIB ${SCHED_SRC}) - +add_dependencies(SCHED_LIB rrc_flag) set(SCHED_NR_SRC ${OPENAIR1_DIR}/SCHED_NR/fapi_nr_l1.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c @@ -1045,6 +1018,7 @@ set(SCHED_SRC_RU ${OPENAIR1_DIR}/SCHED/prach_procedures.c ) add_library(SCHED_RU_LIB ${SCHED_SRC_RU}) +add_dependencies(SCHED_RU_LIB rrc_flag) set(SCHED_SRC_UE ${OPENAIR1_DIR}/SCHED_UE/phy_procedures_lte_ue.c @@ -1054,7 +1028,7 @@ set(SCHED_SRC_UE ${OPENAIR1_DIR}/SCHED_UE/srs_pc.c ) add_library(SCHED_UE_LIB ${SCHED_SRC_UE}) - +add_dependencies(SCHED_UE_LIB rrc_flag) set(SCHED_SRC_NR_UE ${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c @@ -1116,6 +1090,7 @@ set(NFAPI_USER_SRC ${NFAPI_USER_DIR}/nfapi_vnf.c ) add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC}) +add_dependencies(NFAPI_USER_LIB rrc_flag) include_directories(${NFAPI_USER_DIR}) # Layer 1 @@ -1158,11 +1133,7 @@ set(PHY_LDPCSRC ) add_library(coding MODULE ${PHY_TURBOSRC} ) - set(PHY_SRC_COMMON - # depend on code generation from asn1c - ${RRC_FULL_DIR}/asn_constant.h - # actual source ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c # ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slss.c @@ -1216,7 +1187,6 @@ set(PHY_SRC_COMMON ) set(PHY_SRC - # actual source ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pss.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss_gen.c @@ -1244,7 +1214,6 @@ set(PHY_SRC ) set(PHY_SRC_RU - # actual source ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_tools.c ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c @@ -1259,7 +1228,6 @@ set(PHY_SRC_RU ) set(PHY_SRC_UE - # actual source ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/sss_ue.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss_gen.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -1301,9 +1269,6 @@ set(PHY_SRC_UE ) set(PHY_NR_SRC - # depend on code generation from asn1c - ${RRC_FULL_DIR}/asn_constant.h - # actual source ${OPENAIR1_DIR}/PHY/INIT/nr_init.c ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pss.c @@ -1314,6 +1279,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c ${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_tbs_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c @@ -1335,9 +1301,6 @@ set(PHY_SRC_UE ) set(PHY_NR_UE_SRC - # depend on code generation from asn1c - ${RRC_FULL_DIR}/asn_constant.h - # actual source ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -1347,6 +1310,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c + ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -1396,11 +1360,15 @@ if (${COMPILATION_AVX2} STREQUAL "True") endif () add_library(PHY_COMMON ${PHY_SRC_COMMON}) +add_dependencies(PHY_COMMON rrc_flag) add_library(PHY ${PHY_SRC}) +add_dependencies(PHY rrc_flag) add_library(PHY_UE ${PHY_SRC_UE}) +add_dependencies(PHY_UE rrc_flag) add_library(PHY_NR ${PHY_NR_SRC}) add_library(PHY_NR_UE ${PHY_NR_UE_SRC}) add_library(PHY_RU ${PHY_SRC_RU}) +add_dependencies(PHY_RU rrc_flag) #Library for mex functions #########################3 @@ -1614,6 +1582,7 @@ add_library(L2 ${MAC_SRC} ${ENB_APP_SRC} ) +add_dependencies(L2 rrc_flag s1ap_flag x2_flag) add_library(MAC_NR ${MAC_NR_SRC} @@ -1628,52 +1597,26 @@ add_library(L2_NR ${MAC_NR_SRC} ${GNB_APP_SRC} ) +add_dependencies(S1AP_LIB nr_rrc_flag s1ap_flag) add_library(L2_UE ${L2_SRC_UE} ${MAC_SRC_UE} - #${MAC_NR_SRC_UE} ) +if (NOT ${NOS1}) +target_compile_definitions(L2_UE PUBLIC -DPDCP_USE_NETLINK) +endif() + +add_dependencies(L2_UE rrc_flag s1ap_flag x2_flag) add_library( NR_L2_UE - #${L2_SRC_UE} ${NR_L2_SRC_UE} ${MAC_NR_SRC_UE} - #${MAC_SRC_UE} -) - -set ( NR_LTE_UE_REUSE_SRC - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_timefreq.c - ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c - #${OPENAIR1_DIR}/SCHED_UE/phy_procedures_lte_ue.c - ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c - #${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch_common.c - - #${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_cell_spec.c - #${OPENAIR1_DIR}/PHY/CODING/lte_segmentation.c - #${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach_common.c -# ${OPENAIR1_DIR}/PHY/INIT/lte_init_ue.c - ${OPENAIR1_DIR}/PHY/CODING/crc_byte.c - ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c - ${OPENAIR1_DIR}/PHY/CODING/viterbi.c - #${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/phich_common.c - ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c - -# ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c -# ${OPENAIR1_DIR}/PHY/CODING/lte_rate_matching.c - ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_lte.c - ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte.c - ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_est_freq_offset.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c - ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ue_measurements.c - #${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c - #${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c -) - -add_library( NR_LTE_UE_REUSE_LIB - ${NR_LTE_UE_REUSE_SRC} -) + ) + +add_library( MAC_NR_COMMON + ${OPENAIR2_DIR}/LAYER2/NR_MAC_gNB/nr_mac_common.c + ) include_directories("${OPENAIR2_DIR}/NR_UE_PHY_INTERFACE") include_directories("${OPENAIR2_DIR}/LAYER2/NR_MAC_UE") @@ -1702,6 +1645,7 @@ set (GTPV1U_SRC ${GTPV1U_DIR}/gtpv1u_teid_pool.c ) add_library(GTPV1U ${GTPV1U_SRC}) +add_dependencies(GTPV1U rrc_flag) set(SCTP_SRC ${OPENAIR3_DIR}/SCTP/sctp_common.c @@ -1709,8 +1653,10 @@ set(SCTP_SRC ${OPENAIR3_DIR}/SCTP/sctp_eNB_itti_messaging.c ) add_library(SCTP_CLIENT ${SCTP_SRC}) +add_dependencies(SCTP_CLIENT rrc_flag) add_library(UDP ${OPENAIR3_DIR}/UDP/udp_eNB_task.c) +add_dependencies(UDP rrc_flag) set(NAS_SRC ${OPENAIR3_DIR}/NAS/) @@ -1959,6 +1905,7 @@ if(NAS_UE) ${libnas_ue_esm_OBJS} ${libnas_ue_esm_sap_OBJS} ) + add_dependencies(LIB_NAS_UE rrc_flag) set(NAS_UE_LIB LIB_NAS_UE) include_directories(${NAS_SRC}UE) @@ -2219,8 +2166,6 @@ add_definitions(-DASN1_MINIMUM_VERSION=924) ################################################### add_executable(lte-softmodem - ${rrc_h} - ${s1ap_h} ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/RT/USER/lte-enb.c ${OPENAIR_TARGETS}/RT/USER/lte-ru.c @@ -2242,6 +2187,7 @@ add_executable(lte-softmodem ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} ) +add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag) target_link_libraries (lte-softmodem -Wl,--start-group @@ -2258,8 +2204,6 @@ target_link_libraries (lte-softmodem ${T_LIB}) # lte-softmodem-nos1 is both eNB and UE implementation ################################################### add_executable(lte-softmodem-nos1 - ${rrc_h} - ${s1ap_h} ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/RT/USER/lte-enb.c ${OPENAIR_TARGETS}/RT/USER/lte-ru.c @@ -2296,8 +2240,6 @@ target_link_libraries (lte-softmodem-nos1 ${T_LIB}) ####################################### add_executable(lte-uesoftmodem - ${rrc_h} - ${s1ap_h} ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/RT/USER/lte-ue.c ${OPENAIR_TARGETS}/RT/USER/lte-uesoftmodem.c @@ -2319,6 +2261,10 @@ add_executable(lte-uesoftmodem ${SHLIB_LOADER_SOURCES} ) +add_dependencies(lte-uesoftmodem rrc_flag s1ap_flag x2_flag) +if (NOT ${NOS1}) + target_compile_definitions(lte-uesoftmodem PRIVATE -DPDCP_USE_NETLINK) +endif() target_link_libraries (lte-uesoftmodem -Wl,--start-group RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU @@ -2334,8 +2280,6 @@ target_link_libraries (lte-uesoftmodem ${T_LIB}) # lte-uesoftmodem-nos1 is UE implementation ################################################### add_executable(lte-uesoftmodem-nos1 - ${rrc_h} - ${s1ap_h} ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/RT/USER/lte-ue.c ${OPENAIR_TARGETS}/RT/USER/lte-uesoftmodem.c @@ -2358,6 +2302,7 @@ add_executable(lte-uesoftmodem-nos1 ${SHLIB_LOADER_SOURCES} ) +add_dependencies(lte-uesoftmodem-nos1 rrc_flag s1ap_flag x2_flag) target_link_libraries (lte-uesoftmodem-nos1 -Wl,--start-group RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY_UE PHY_RU LFDS L2_UE SIMU ${RAL_LIB} ${ITTI_LIB} @@ -2400,7 +2345,7 @@ target_link_libraries (nr-softmodem -Wl,--start-group UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_RU LFDS GTPV1U SECU_CN SECU_OSA ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} - RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB L2 L2_NR + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB L2 L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB -Wl,--end-group z dl) @@ -2441,7 +2386,7 @@ target_link_libraries (nr-softmodem-nos1 -Wl,--start-group UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_RU LFDS GTPV1U SECU_CN SECU_OSA ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${MIH_LIB} - RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB L2 L2_NR + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB L2 L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB -Wl,--end-group z dl) @@ -2457,11 +2402,10 @@ add_executable(nr-uesoftmodem ${rrc_h} ${s1ap_h} # ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c - ${OPENAIR_TARGETS}/RT/USER/nr-ue.c - ${OPENAIR_TARGETS}/RT/USER/nr-uesoftmodem.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/executables//nr-uesoftmodem.c + ${OPENAIR_DIR}/executables/nr-ue.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c -# ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c @@ -2476,7 +2420,7 @@ add_executable(nr-uesoftmodem target_link_libraries (nr-uesoftmodem -Wl,--start-group - RRC_LIB NR_RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_UE PHY_RU LFDS NR_L2_UE #NR_LTE_UE_REUSE_LIB + RRC_LIB NR_RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_UE PHY_RU LFDS NR_L2_UE MAC_NR_COMMON ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} -Wl,--end-group z dl) @@ -2510,7 +2454,7 @@ add_executable(nr-uesoftmodem-nos1 target_link_libraries (nr-uesoftmodem-nos1 -Wl,--start-group - RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_UE PHY_UE PHY_RU LFDS NR_L2_UE + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_UE PHY_UE PHY_RU LFDS NR_L2_UE MAC_NR_COMMON ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} -Wl,--end-group z dl) @@ -2561,36 +2505,56 @@ target_link_libraries (dlsim_tm4 pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB} ) -add_executable(polartest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c) +add_executable(polartest + ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c + ${OPENAIR_DIR}/common/utils/backtrace.c) target_link_libraries(polartest SIMU PHY PHY_NR PHY_COMMON m ${ATLAS_LIBRARIES}) + add_executable(smallblocktest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/smallblocktest.c) target_link_libraries(smallblocktest SIMU PHY PHY_NR PHY_COMMON m ${ATLAS_LIBRARIES}) -add_executable(ldpctest ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c) +add_executable(ldpctest + ${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c + ${OPENAIR_DIR}/common/utils/backtrace.c) target_link_libraries(ldpctest SIMU PHY PHY_NR m ${ATLAS_LIBRARIES}) -add_executable(nr_dlschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c ${T_SOURCE}) +add_executable(nr_dlschsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c + ${OPENAIR_DIR}/common/utils/backtrace.c + ${T_SOURCE}) target_link_libraries(nr_dlschsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl) -add_executable(nr_pbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c ${T_SOURCE}) +add_executable(nr_pbchsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c + ${OPENAIR_DIR}/common/utils/backtrace.c + ${T_SOURCE}) target_link_libraries(nr_pbchsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl) -add_executable(nr_dlsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c ${T_SOURCE}) -target_link_libraries(nr_dlsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR RRC_LIB NR_RRC_LIB CONFIG_LIB L2_NR -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl) +add_executable(nr_dlsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c + ${OPENAIR_DIR}/common/utils/backtrace.c + ${T_SOURCE}) +target_link_libraries(nr_dlsim -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) + +add_executable(nr_ulschsim + ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c + ${OPENAIR_DIR}/common/utils/backtrace.c + ${T_SOURCE}) +target_link_libraries(nr_ulschsim -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} dl) foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim) - + add_executable(${myExe} ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c + ${OPENAIR_DIR}/common/utils/backtrace.c ${XFORMS_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} ) target_link_libraries (${myExe} - -Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON PHY PHY_UE PHY_RU LFDS ${ITTI_LIB} LFDS7 -Wl,--end-group pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB} dl ) @@ -2660,7 +2624,7 @@ if (${T_TRACER}) #all "add_executable" definitions (except tests, rb_tool, updatefw) lte-softmodem lte-softmodem-nos1 lte-uesoftmodem lte-uesoftmodem-nos1 nr-softmodem nr-softmodem-nos1 nr-uesoftmodem nr-uesoftmodem-nos1 - dlsim_tm4 dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim + dlsim_tm4 nr_dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syncsim ulsim ldpctest polartest #all "add_library" definitions @@ -2710,7 +2674,9 @@ L2 L2_NR L2_UE NR_L2_UE -NR_LTE_UE_REUSE_LIB +MAC_NR_COMMON +MAC_NR +MAC_UE_NR CN_UTILS GTPV1U SCTP_CLIENT @@ -2776,7 +2742,7 @@ endfunction(make_driver name dir src) # nashmesh module ################ list(APPEND nasmesh_src device.c common.c ioctl.c classifier.c tool.c mesh.c) -set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK") +set(module_cc_opt "${module_cc_opt} -DNAS_NETLINK -DPDCP_USE_NETLINK -D${MKVER}") # legacy Makefile was using NAS_NETLINK flag, but other drivers the hereafter flag # so, this cmake use OAI_NW_DRIVER_USE_NETLINK everywhere if (OAI_NW_DRIVER_USE_NETLINK) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index aa1db28d75..c0f8eac447 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1057,8 +1057,8 @@ (Test2: PBCH and synchronization, 106PBR), (Test3: PBCH-only, 217 PRB), (Test4: PBCH and synchronization, 217 RPB), - (Test5: PBCH-only, 217 PRB), - (Test6: PBCH and synchronization, 217 PRB) + (Test5: PBCH-only, 273 PRB), + (Test6: PBCH and synchronization, 273 PRB) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1071,24 +1071,59 @@ -s0 -S1 -n10 -I -R217 -s0 -S1 -n1000 -R273 -s0 -S1 -n10 -I -R273 - nr_pbchsim.test1 nr_pbchsim.test2 + nr_pbchsim.test1 nr_pbchsim.test2 nr_pbchsim.test3 nr_pbchsim.test4 nr_pbchsim.test5 nr_pbchsim.test6 PBCH test OK segmentation fault|assertion|exiting|fatal 3 - + + execution + nr_dlsim Test cases. (Test1: 106 PRB), + (Test2: 217 PRB), + (Test3: 273 PRB) + + $OPENAIR_DIR/cmake_targets/build_oai + --phy_simulators -c + $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash + + $OPENAIR_DIR/targets/bin/nr_dlsim.Rel15 + -n100 -R106 + -n100 -R217 + -n100 -R273 + nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 + PDCCH test OK + segmentation fault|assertion|exiting|fatal + 3 + + + + execution + nr_dlschsim Test cases. (Test1: 106 PRB), + (Test2: 217 PRB), + (Test3: 273 PRB) + + $OPENAIR_DIR/cmake_targets/build_oai + --phy_simulators -c + $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash + + $OPENAIR_DIR/targets/bin/nr_dlschsim.Rel15 + -R 106 -m9 -s13 -n100 + -R 217 -m15 -s15 -n100 + -R 273 -m19 -s20 -n100 + nr_dlschsim.test1 nr_dlschsim.test2 nr_dlschsim.test3 + PDSCH test OK + segmentation fault|assertion|exiting|fatal + 3 + + + execution shortblocktest Test cases. (Test1: 3 bits), (Test2: 6 bits) (Test3: 7 bits) (Test4: 11 bits) - - $OPENAIR_DIR/cmake_targets/build_oai - --phy_simulators -c - $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash - $OPENAIR_DIR/targets/bin/smallblocktest.Rel15 -l 3 -l 6 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 69aafbc41b..4bfa734709 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -43,10 +43,10 @@ conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf MSC_GEN=0 XFORMS="True" UE_EXPANSION="False" +UESIM_EXPANSION="False" PRINT_STATS="False" VCD_TIMING="False" -DEADLINE_SCHEDULER_FLAG_USER="False" -FORCE_DEADLINE_SCHEDULER_FLAG_USER="" +DEADLINE_SCHEDULER_FLAG_USER="" CPU_AFFINITY_FLAG_USER="False" #Only valid when lowlatecy flag is set to False REL="Rel15" NR_REL="NR_Rel15" @@ -78,7 +78,7 @@ trap handle_ctrl_c INT function print_help() { echo_info " This program installs OpenAirInterface Software -You should have ubuntu 14.xx, updated, and the Linux kernel >= 3.14 +You should have ubuntu 16.xx or 18.04 updated Options -h This help @@ -116,7 +116,7 @@ Options Rel8 limits the implementation to 3GPP Release 8 version Rel10 limits the implementation to 3GPP Release 10 version -w | --hardware - EXMIMO, USRP, BLADERF, ETHERNET, LMSSDR, ADRV9371_ZC706, None (Default) + EXMIMO, USRP, BLADERF, ETHERNET, LMSSDR, ADRV9371_ZC706, SIMU, None (Default) Adds this RF board support (in external packages installation and in compilation) -t | --transport protocol ETHERNET , None @@ -175,6 +175,9 @@ Options --basic-simulator Generates a basic [1 UE + 1 eNB + no channel] simulator. See targets/ARCH/tcp_bridge/README.tcp_bridge_oai for documentation. +--rfsimulator + Generate virtual RF driver + to use it, set the environement variable RFSIMULATOR to \"enb\" in the eNB and to the eNB IP address in the UEs Usage (first build): NI/ETTUS B201 + COTS UE : ./build_oai -I --eNB -x --install-system-files -w USRP Usage (Regular): @@ -250,7 +253,7 @@ function main() { -w | --hardware) HW="$2" #"${i#*=}" # Use OAI_USRP as the key word USRP is used inside UHD driver - if [ "$HW" != "BLADERF" -a "$HW" != "USRP" -a "$HW" != "LMSSDR" -a "$HW" != "None" -a "$HW" != "EXMIMO" -a "$HW" != "ADRV9371_ZC706" ] ; then + if [ "$HW" != "BLADERF" -a "$HW" != "USRP" -a "$HW" != "LMSSDR" -a "$HW" != "None" -a "$HW" != "EXMIMO" -a "$HW" != "ADRV9371_ZC706" -a "$HW" != "SIMU" ] ; then echo_fatal "Unknown HW type $HW will exit..." else if [ "$HW" == "USRP" ] ; then @@ -265,6 +268,9 @@ function main() { if [ "$HW" == "LMSSDR" ] ; then HW="OAI_LMSSDR" fi + if [ "$HW" == "SIMU" ] ; then + HW="OAI_SIMU" + fi echo_info "Setting hardware to: $HW" fi shift 2;; @@ -331,13 +337,13 @@ function main() { BUILD_DOXYGEN=1 echo_info "Will build doxygen support" shift;; - --disable-deadline) - FORCE_DEADLINE_SCHEDULER_FLAG_USER="False" - echo_info "Disabling the usage of deadline scheduler" - shift 1;; - --enable-deadline) - FORCE_DEADLINE_SCHEDULER_FLAG_USER="True" - echo_info "Enabling the usage of deadline scheduler" + --disable-deadline) + DEADLINE_SCHEDULER_FLAG_USER="False" + echo_info "Disabling the usage of deadline scheduler" + shift 1;; + --enable-deadline) + DEADLINE_SCHEDULER_FLAG_USER="True" + echo_info "Enabling the usage of deadline scheduler" shift 1;; --enable-cpu-affinity) CPU_AFFINITY_FLAG_USER="True" @@ -400,7 +406,11 @@ function main() { BASIC_SIMULATOR=1 echo_info "Compiling the basic simulator" shift 1;; - -h | --help) + --rfsimulator) + RFSIMULATOR=true + echo_info "Compiling the RF simulator" + shift 1;; + -h | --help) print_help exit 1;; *) @@ -441,33 +451,18 @@ function main() { fi fi - echo_info "RF HW set to $HW" - #Now we set flags to enable deadline scheduler settings - #By default: USRP: disable, - #By default: BLADERF: enable, - #By default: EXMIMO: enable - if [ "$FORCE_DEADLINE_SCHEDULER_FLAG_USER" = "" ]; then - if [ "$HW" = "EXMIMO" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="True" - elif [ "$HW" = "ETHERNET" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="False" - elif [ "$HW" = "OAI_USRP" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="False" - elif [ "$HW" = "OAI_ADRV9371_ZC706" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="False" - elif [ "$HW" = "OAI_BLADERF" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="False" - elif [ "$HW" = "OAI_LMSSDR" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="False" - elif [ "$HW" = "None" ] ; then - DEADLINE_SCHEDULER_FLAG_USER="False" - else - echo_error "Unknown HW type $HW. Exiting now..." - exit - fi - else - DEADLINE_SCHEDULER_FLAG_USER=$FORCE_DEADLINE_SCHEDULER_FLAG_USER - fi + echo_info "RF HW set to $HW" + # If the user doesn't specify the Linux scheduler to use, we set a value + if [ "$DEADLINE_SCHEDULER_FLAG_USER" = "" ]; then + case "$HW" in + "EXMIMO") + DEADLINE_SCHEDULER_FLAG_USER="True" + ;; + *) + DEADLINE_SCHEDULER_FLAG_USER="False" + ;; + esac + fi #Disable CPU Affinity for deadline scheduler if [ "$DEADLINE_SCHEDULER_FLAG_USER" = "True" ] ; then @@ -696,7 +691,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="dlsim ulsim polartest ldpctest smallblocktest nr_pbchsim nr_dlschsim nr_dlsim" + simlist="dlsim ulsim polartest ldpctest smallblocktest nr_pbchsim nr_dlschsim nr_dlsim nr_ulschsim" for f in $simlist ; do compilations \ phy_simulators $f \ diff --git a/cmake_targets/tools/make_asn1c_includes.sh b/cmake_targets/tools/make_asn1c_includes.sh new file mode 100755 index 0000000000..bd4254c938 --- /dev/null +++ b/cmake_targets/tools/make_asn1c_includes.sh @@ -0,0 +1,15 @@ +#!/bin/bash +GENERATED_FULL_DIR=$1 +shift +ASN1_SOURCE_DIR=$1 +shift +export ASN1C_PREFIX=$1 +shift +options=$* +done_flag="$GENERATED_FULL_DIR"/done +if [ "$done_flag" -ot $ASN1_SOURCE_DIR ] ; then + rm -f "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}*.c "$GENERATED_FULL_DIR"/${ASN1C_PREFIX}*.h + mkdir -p "$GENERATED_FULL_DIR" + asn1c -pdu=all -fcompound-names -gen-PER -no-gen-OER -no-gen-example $options -D $GENERATED_FULL_DIR $ASN1_SOURCE_DIR |& egrep -v "^Copied|^Compiled" | sort -u +fi +touch $done_flag diff --git a/common/utils/backtrace.h b/common/utils/backtrace.h index 9a77767cf4..3977d0321c 100644 --- a/common/utils/backtrace.h +++ b/common/utils/backtrace.h @@ -23,9 +23,16 @@ #ifndef BACKTRACE_H_ #define BACKTRACE_H_ +#ifdef __cplusplus +extern "C" { +#endif void display_backtrace(void); void backtrace_handle_signal(siginfo_t *info); +#ifdef __cplusplus +} +#endif + #endif /* BACKTRACE_H_ */ diff --git a/common/utils/threadPool/Makefile b/common/utils/threadPool/Makefile new file mode 100644 index 0000000000..6f0e884886 --- /dev/null +++ b/common/utils/threadPool/Makefile @@ -0,0 +1,8 @@ +all: measurement_display thread-pool-test + +measurement_display: measurement_display.c thread-pool.h + gcc measurement_display.c -I /data/openairinterface5g.nr/common/utils/ -I. /data/openairinterface5g.nr/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o measurement_display + +thread-pool-test: thread-pool.c thread-pool.h + gcc -g thread-pool.c -I /data/openairinterface5g.nr/common/utils/ -I. /data/openairinterface5g.nr/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o thread-pool-test + diff --git a/common/utils/threadPool/measurement_display.c b/common/utils/threadPool/measurement_display.c new file mode 100644 index 0000000000..ac7beca1fe --- /dev/null +++ b/common/utils/threadPool/measurement_display.c @@ -0,0 +1,61 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#define __USE_GNU +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thread-pool.h" + +#define SEP "\t" + +uint64_t cpuCyclesMicroSec; + +int main(int argc, char *argv[]) { + if(argc != 2) { + printf("Need one paramter: the trace Linux pipe (fifo)"); + exit(1); + } + + mkfifo(argv[1],0666); + int fd=open(argv[1], O_RDONLY); + + if ( fd == -1 ) { + perror("open read mode trace file:"); + exit(1); + } + + uint64_t deb=rdtsc(); + usleep(100000); + cpuCyclesMicroSec=(rdtsc()-deb)/100000; + printf("Cycles per µs: %lu\n",cpuCyclesMicroSec); + printf("Key" SEP "delay to process" SEP "processing time" SEP "delay to be read answer\n"); + notifiedFIFO_elt_t doneRequest; + + while ( 1 ) { + if ( read(fd,&doneRequest, sizeof(doneRequest)) == sizeof(doneRequest)) { + printf("%lu" SEP "%lu" SEP "%lu" SEP "%lu" "\n", + doneRequest.key, + (doneRequest.startProcessingTime-doneRequest.creationTime)/cpuCyclesMicroSec, + (doneRequest.endProcessingTime-doneRequest.startProcessingTime)/cpuCyclesMicroSec, + (doneRequest.returnTime-doneRequest.endProcessingTime)/cpuCyclesMicroSec + ); + } else { + printf("no measurements\n"); + sleep(1); + } + } +} diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c new file mode 100644 index 0000000000..4cc56fc9b8 --- /dev/null +++ b/common/utils/threadPool/thread-pool.c @@ -0,0 +1,230 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void displayList(notifiedFIFO_t *nf) { + int n=0; + notifiedFIFO_elt_t *ptr=nf->outF; + + while(ptr) { + printf("element: %d, key: %lu\n",++n,ptr->key); + ptr=ptr->next; + } + + printf("End of list: %d elements\n",n); +} + +static inline notifiedFIFO_elt_t *pullNotifiedFifoRemember( notifiedFIFO_t *nf, struct one_thread *thr) { + mutexlock(nf->lockF); + + while(!nf->outF) + condwait(nf->notifF, nf->lockF); + + notifiedFIFO_elt_t *ret=nf->outF; + nf->outF=nf->outF->next; + + if (nf->outF==NULL) + nf->inF=NULL; + + // For abort feature + thr->runningOnKey=ret->key; + thr->abortFlag=false; + mutexunlock(nf->lockF); + return ret; +} + +void *one_thread(void *arg) { + struct one_thread *myThread=(struct one_thread *) arg; + struct thread_pool *tp=myThread->pool; + + // configure the thread core assignment + // TBD: reserve the core for us exclusively + if ( myThread->coreID >= 0 && myThread->coreID < get_nprocs_conf()) { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(myThread->coreID, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + } + + //Configure the thread scheduler policy for Linux + struct sched_param sparam= {0}; + sparam.sched_priority = sched_get_priority_max(SCHED_RR); + pthread_setschedparam(pthread_self(), SCHED_RR, &sparam); + // set the thread name for debugging + sprintf(myThread->name,"Tpool_%d",myThread->coreID); + pthread_setname_np(pthread_self(), myThread->name ); + + // Infinite loop to process requests + do { + notifiedFIFO_elt_t *elt=pullNotifiedFifoRemember(&tp->incomingFifo, myThread); + + if (tp->measurePerf) elt->startProcessingTime=rdtsc(); + + elt->processingFunc(NotifiedFifoData(elt)); + + if (tp->measurePerf) elt->endProcessingTime=rdtsc(); + + if (elt->reponseFifo) { + // Check if the job is still alive, else it has been aborted + mutexlock(tp->incomingFifo.lockF); + + if (myThread->abortFlag) + delNotifiedFIFO_elt(elt); + else + pushNotifiedFIFO(elt->reponseFifo, elt); + + mutexunlock(tp->incomingFifo.lockF); + } + } while (true); +} + +void initTpool(char *params,tpool_t *pool, bool performanceMeas) { + memset(pool,0,sizeof(*pool)); + char *measr=getenv("threadPoolMeasurements"); + pool->measurePerf=performanceMeas; + // force measurement if the output is defined + pool->measurePerf=measr!=NULL; + + if (measr) { + mkfifo(measr,0666); + AssertFatal(-1 != (pool->dummyTraceFd= + open(measr, O_RDONLY| O_NONBLOCK)),""); + AssertFatal(-1 != (pool->traceFd= + open(measr, O_WRONLY|O_APPEND|O_NOATIME|O_NONBLOCK)),""); + } else + pool->traceFd=-1; + + //Configure the thread scheduler policy for Linux + struct sched_param sparam= {0}; + sparam.sched_priority = sched_get_priority_max(SCHED_RR)-1; + pthread_setschedparam(pthread_self(), SCHED_RR, &sparam); + pool->activated=true; + initNotifiedFIFO(&pool->incomingFifo); + char *saveptr, * curptr; + pool->nbThreads=0; + pool->restrictRNTI=false; + curptr=strtok_r(params,",",&saveptr); + + while ( curptr!=NULL ) { + int c=toupper(curptr[0]); + + switch (c) { + case 'U': + pool->restrictRNTI=true; + break; + + case 'N': + pool->activated=false; + break; + + default: + pool->allthreads=(struct one_thread *)malloc(sizeof(struct one_thread)); + pool->allthreads->next=pool->allthreads; + printf("create a thread for core %d\n", atoi(curptr)); + pool->allthreads->coreID=atoi(curptr); + pool->allthreads->id=pool->nbThreads; + pool->allthreads->pool=pool; + pthread_create(&pool->allthreads->threadID, NULL, one_thread, (void *)pool->allthreads); + pool->nbThreads++; + } + + curptr=strtok_r(NULL,",",&saveptr); + } + + if (pool->activated && pool->nbThreads==0) { + printf("No servers created in the thread pool, exit\n"); + exit(1); + } +} + +#ifdef TEST_THREAD_POOL + +struct testData { + int id; + char txt[30]; +}; + +void processing(void *arg) { + struct testData *in=(struct testData *)arg; + printf("doing: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); + sprintf(in->txt,"Done by %ld, job %d", pthread_self(), in->id); + usleep(rand()%100); + printf("done: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); +} + +int main() { + notifiedFIFO_t myFifo; + initNotifiedFIFO(&myFifo); + pushNotifiedFIFO(&myFifo,newNotifiedFIFO_elt(sizeof(struct testData), 1234,NULL,NULL)); + + for(int i=10; i>1; i--) { + pushNotifiedFIFO(&myFifo,newNotifiedFIFO_elt(sizeof(struct testData), 1000+i,NULL,NULL)); + } + + displayList(&myFifo); + notifiedFIFO_elt_t *tmp=pullNotifiedFIFO(&myFifo); + printf("pulled: %lu\n", tmp->key); + displayList(&myFifo); + tmp=pullNotifiedFIFO(&myFifo); + printf("pulled: %lu\n", tmp->key); + displayList(&myFifo); + abortNotifiedFIFO(&myFifo,1005); + printf("aborted 1005\n"); + displayList(&myFifo); + pushNotifiedFIFO(&myFifo,newNotifiedFIFO_elt(sizeof(struct testData), 12345678, NULL, NULL)); + displayList(&myFifo); + abortNotifiedFIFO(&myFifo,12345678); + printf("aborted 12345678\n"); + displayList(&myFifo); + + do { + tmp=pollNotifiedFIFO(&myFifo); + + if (tmp) { + printf("pulled: %lu\n", tmp->key); + displayList(&myFifo); + } else + printf("Empty list \n"); + } while(tmp); + + tpool_t pool; + char params[]="1,2,3,u"; + initTpool(params,&pool, true); + notifiedFIFO_t worker_back; + initNotifiedFIFO(&worker_back); + + for (int i=0; i <1000 ; i++) { + notifiedFIFO_elt_t *work=newNotifiedFIFO_elt(sizeof(struct testData), i, &worker_back, processing); + struct testData *x=(struct testData *)NotifiedFifoData(work); + x->id=i; + pushTpool(&pool, work); + } + + do { + tmp=pullTpool(&worker_back,&pool); + + if (tmp) { + struct testData *dd=NotifiedFifoData(tmp); + printf("Result: %s\n",dd->txt); + delNotifiedFIFO_elt(tmp); + } else + printf("Empty list \n"); + + abortTpool(&pool,510); + } while(tmp); + + return 0; +} +#endif diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h new file mode 100644 index 0000000000..6f34508c5a --- /dev/null +++ b/common/utils/threadPool/thread-pool.h @@ -0,0 +1,244 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#ifndef THREAD_POOL_H +#define THREAD_POOL_H +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG + #define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP +#else + #define THREADINIT PTHREAD_MUTEX_INITIALIZER +#endif +#define mutexinit(mutex) AssertFatal(pthread_mutex_init(&mutex,NULL)==0,""); +#define condinit(signal) AssertFatal(pthread_cond_init(&signal,NULL)==0,""); +#define mutexlock(mutex) AssertFatal(pthread_mutex_lock(&mutex)==0,""); +#define mutextrylock(mutex) pthread_mutex_trylock(&mutex) +#define mutexunlock(mutex) AssertFatal(pthread_mutex_unlock(&mutex)==0,""); +#define condwait(condition, mutex) AssertFatal(pthread_cond_wait(&condition, &mutex)==0,""); +#define condbroadcast(signal) AssertFatal(pthread_cond_broadcast(&signal)==0,""); +#define condsignal(signal) AssertFatal(pthread_cond_broadcast(&signal)==0,""); + +typedef struct notifiedFIFO_elt_s { + struct notifiedFIFO_elt_s *next; + uint64_t key; //To filter out elements + struct notifiedFIFO_s *reponseFifo; + void (*processingFunc)(void *); + bool malloced; + uint64_t creationTime; + uint64_t startProcessingTime; + uint64_t endProcessingTime; + uint64_t returnTime; + void *msgData; +} notifiedFIFO_elt_t; + +typedef struct notifiedFIFO_s { + notifiedFIFO_elt_t *outF; + notifiedFIFO_elt_t *inF; + pthread_mutex_t lockF; + pthread_cond_t notifF; +} notifiedFIFO_t; + +// You can use this allocator or use any piece of memory +static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size, + uint64_t key, + notifiedFIFO_t *reponseFifo, + void (*processingFunc)(void *)) { + notifiedFIFO_elt_t *ret; + AssertFatal( NULL != (ret=(notifiedFIFO_elt_t *) malloc(sizeof(notifiedFIFO_elt_t)+size+32)), ""); + ret->next=NULL; + ret->key=key; + ret->reponseFifo=reponseFifo; + ret->processingFunc=processingFunc; + // We set user data piece aligend 32 bytes to be able to process it with SIMD + ret->msgData=(void *)ret+(sizeof(notifiedFIFO_elt_t)/32+1)*32; + ret->malloced=true; + return ret; +} + +static inline void *NotifiedFifoData(notifiedFIFO_elt_t *elt) { + return elt->msgData; +} + +static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt) { + if (elt->malloced) { + elt->malloced=false; + free(elt); + } else + printf("delNotifiedFIFO on something not allocated by newNotifiedFIFO\n"); + + //LOG_W(UTIL,"delNotifiedFIFO on something not allocated by newNotifiedFIFO\n"); +} + +static inline void initNotifiedFIFO(notifiedFIFO_t *nf) { + mutexinit(nf->lockF); + condinit (nf->notifF); + nf->inF=NULL; + nf->outF=NULL; + // No delete function: the creator has only to free the memory +} + +static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { + mutexlock(nf->lockF); + msg->next=NULL; + + if (nf->outF == NULL) + nf->outF = msg; + + if (nf->inF) + nf->inF->next = msg; + + nf->inF = msg; + condbroadcast(nf->notifF); + mutexunlock(nf->lockF); +} + +static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) { + mutexlock(nf->lockF); + + while(!nf->outF) + condwait(nf->notifF, nf->lockF); + + notifiedFIFO_elt_t *ret=nf->outF; + nf->outF=nf->outF->next; + + if (nf->outF==NULL) + nf->inF=NULL; + + mutexunlock(nf->lockF); + return ret; +} + +static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) { + int tmp=mutextrylock(nf->lockF); + + if (tmp != 0 ) + return NULL; + + notifiedFIFO_elt_t *ret=nf->outF; + + if (ret!=NULL) + nf->outF=nf->outF->next; + + if (nf->outF==NULL) + nf->inF=NULL; + + mutexunlock(nf->lockF); + return ret; +} + +// This function aborts all messages matching the key +// If the queue is used in thread pools, it doesn't cancels already running processing +// because the message has already been picked +static inline void abortNotifiedFIFO(notifiedFIFO_t *nf, uint64_t key) { + mutexlock(nf->lockF); + notifiedFIFO_elt_t **start=&nf->outF; + + while(*start!=NULL) { + if ( (*start)->key == key ) { + notifiedFIFO_elt_t *request=*start; + *start=(*start)->next; + delNotifiedFIFO_elt(request); + } + + if (*start != NULL) + start=&(*start)->next; + } + + mutexunlock(nf->lockF); +} + +struct one_thread { + pthread_t threadID; + int id; + int coreID; + char name[256]; + uint64_t runningOnKey; + bool abortFlag; + struct thread_pool *pool; + struct one_thread *next; +}; + +typedef struct thread_pool { + int activated; + bool measurePerf; + int traceFd; + int dummyTraceFd; + uint64_t cpuCyclesMicroSec; + uint64_t startProcessingUE; + int nbThreads; + bool restrictRNTI; + notifiedFIFO_t incomingFifo; + struct one_thread *allthreads; +} tpool_t; + +static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { + if (t->measurePerf) msg->creationTime=rdtsc(); + + pushNotifiedFIFO(&t->incomingFifo, msg); +} + +static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { + notifiedFIFO_elt_t *msg= pullNotifiedFIFO(responseFifo); + + if (t->measurePerf) + msg->returnTime=rdtsc(); + + if (t->traceFd) + if(write(t->traceFd, msg, sizeof(*msg))); + + return msg; +} + +static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { + notifiedFIFO_elt_t *msg= pollNotifiedFIFO(responseFifo); + + if (msg == NULL) + return NULL; + + if (t->measurePerf) + msg->returnTime=rdtsc(); + + if (t->traceFd) + if(write(t->traceFd, msg, sizeof(*msg))); + + return msg; +} + +static inline void abortTpool(tpool_t *t, uint64_t key) { + notifiedFIFO_t *nf=&t->incomingFifo; + mutexlock(nf->lockF); + notifiedFIFO_elt_t **start=&nf->outF; + + while(*start!=NULL) { + if ( (*start)->key == key ) { + notifiedFIFO_elt_t *request=*start; + *start=(*start)->next; + delNotifiedFIFO_elt(request); + } + + if (*start != NULL) + start=&(*start)->next; + } + + struct one_thread *ptr=t->allthreads; + + while(ptr!=NULL) { + if (ptr->runningOnKey==key) + ptr->abortFlag=true; + + ptr=ptr->next; + } + + mutexunlock(nf->lockF); +} +void initTpool(char *params,tpool_t *pool, bool performanceMeas); + +#endif diff --git a/common/utils/threadPool/thread-pool.md b/common/utils/threadPool/thread-pool.md new file mode 100644 index 0000000000..2b6336fb60 --- /dev/null +++ b/common/utils/threadPool/thread-pool.md @@ -0,0 +1,71 @@ +# Thread pool + +The thread pool is a working server, made of a set of worker threads that can be mapped on CPU cores. + +Each worker loop on pick from the same input queue jobs to do. +When a job is done, the worker sends a return if a return is defined. + +A selective abort allows to cancel parallel jobs (usage: a client pushed jobs, but from a response of one job, the other linked jobs becomes useless). + +All the thread pool functions are thread safe, nevertheless the working functions are implemented by the thread pool client, so the client has to tackle the parallel execution of his functions called "processingFunc" hereafter. + +## license +Author: Laurent Thomas, Open cells project +The owner share this piece code to Openairsoftware alliance as per OSA license terms + +# jobs + +A job is a message (notifiedFIFO_elt_t): +next: internal FIFO chain, do not set it +key: a long int that the client can use to identify a message or a group of messages +responseFifo: if the client defines a response FIFO, the message will be posted back after processing +processingFunc: any funtion (type void processingFunc(void *)) that the worker will launch +msgData: the data passed to processingFunc. It can be added automatically, or you can set it to a buffer you are managing +malloced: a boolean that enable internal free in these cases: no return Fifo or Abort feature + +The job messages can be created with newNotifiedFIFO_elt() and delNotifiedFIFO_elt() or managed by the client. + +# Queues of jobs + +Queues are type of: notifiedFIFO_t that must be initialized by init_notifiedFIFO() +No delete function is required, the creator has only to free the data of type notifiedFIFO_t + +push_notifiedFIFO() add a job in the queue +pull_notifiedFIFO() is blocking, poll_notifiedFIFO() is non blocking + +abort_notifiedFIFO() allows the customer to delete all waiting jobs that match with the key (see key in jobs definition) + +# Thread pools + +## initialization +The clients can create one or more thread pools with init_tpool() +the params string structure: describes a list of cores, separated by "," that run a worker thread + +If the core exists on the CPU, the thread pool initialization sets the affinity between this thread and the related code (use negative values is allowed, so the thread will never be mapped on a specific core). + +The threads are all Linux real time scheduler, their name is set automatically is "Tpool_" + +## adding jobs +The client create their jobs messages as a notifiedFIFO_elt_t, then they push it with pushTpool() (that internally calls push_notifiedFIFO()) + +If they need a return, they have to create response queues with init_notifiedFIFO() and set this FIFO pointer in the notifiedFIFO_elt_t before pushing the job. + +## abort + +A abort service abortTpool() allows to abort all jobs that match a key (see jobs "key"). When the abort returns, it garanties no job (matching the key) response will be posted on response queues. + +Nevertheless, jobs already performed before the return of abortTpool() are pushed in the response Fifo queue. + +## Performance measurements + +A performance measurement is integrated: the pool will automacillay fill timestamps: + +* creationTime: time the request is push to the pool; +* startProcessingTime: time a worker start to run on the job +* endProcessingTime: time the worker finished the job +* returnTime: time the client reads the result + +if you set the environement variable: thread-pool-measurements to a valid file name +These measurements will be wrote to this Linux pipe. + +A tool to read the linux fifo and display it in ascii is provided: see the local directory Makefile for this tool and to compile the thread pool unitary tests. diff --git a/executables/nr-ue.c b/executables/nr-ue.c new file mode 100644 index 0000000000..402c379687 --- /dev/null +++ b/executables/nr-ue.c @@ -0,0 +1,732 @@ +/* + * 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.0 (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 "executables/nr-uesoftmodem.h" + +#include "LAYER2/NR_MAC_UE/mac.h" +//#include "RRC/LTE/rrc_extern.h" +#include "PHY_INTERFACE/phy_interface_extern.h" + +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "fapi_nr_ue_l1.h" +#include "PHY/phy_extern_nr_ue.h" +#include "PHY/INIT/phy_init.h" +#include "PHY/MODULATION/modulation_UE.h" +#include "LAYER2/NR_MAC_UE/mac_proto.h" +#include "RRC/NR_UE/rrc_proto.h" + +//#ifndef NO_RAT_NR +#include "SCHED_NR/phy_frame_config_nr.h" +//#endif +#include "SCHED_NR_UE/defs.h" + +#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" + +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "T.h" + +#ifdef XFORMS + #include "PHY/TOOLS/nr_phy_scope.h" + + extern char do_forms; +#endif + + +extern double cpuf; +//static nfapi_nr_config_request_t config_t; +//static nfapi_nr_config_request_t* config =&config_t; + +/* + * NR SLOT PROCESSING SEQUENCE + * + * Processing occurs with following steps for connected mode: + * + * - Rx samples for a slot are received, + * - PDCCH processing (including DCI extraction for downlink and uplink), + * - PDSCH processing (including transport blocks decoding), + * - PUCCH/PUSCH (transmission of acknowledgements, CSI, ... or data). + * + * Time between reception of the slot and related transmission depends on UE processing performance. + * It is defined by the value NR_UE_CAPABILITY_SLOT_RX_TO_TX. + * + * In NR, network gives the duration between Rx slot and Tx slot in the DCI: + * - for reception of a PDSCH and its associated acknowledgment slot (with a PUCCH or a PUSCH), + * - for reception of an uplink grant and its associated PUSCH slot. + * + * So duration between reception and it associated transmission depends on its transmission slot given in the DCI. + * NR_UE_CAPABILITY_SLOT_RX_TO_TX means the minimum duration but higher duration can be given by the network because UE can support it. + * + * Slot k + * -------+------------+-------- + * Frame | Tx samples | + * Subframe | buffer | + * Slot n -------+------------+-------- + * ------ +------------+-------- | + * | Rx samples | | + * | buffer | | + * -------+------------+-------- | + * | | + * V | + * +------------+ | + * | PDCCH | | + * | processing | | + * +------------+ | + * | | | + * | v | + * | +------------+ | + * | | PDSCH | | + * | | processing | decoding result | + * | +------------+ -> ACK/NACK of PDSCH | + * | | | + * | v | + * | +-------------+------------+ | + * | | PUCCH/PUSCH | Tx samples | | + * | | processing | transfer | | + * | +-------------+------------+ | + * | | + * |/___________________________________________________________\| + * \ duration between reception and associated transmission / + * + * Remark: processing is done slot by slot, it can be distribute on different threads which are executed in parallel. + * This is an architecture optimization in order to cope with real time constraints. + * By example, for LTE, subframe processing is spread over 4 different threads. + * + */ + +#ifndef NO_RAT_NR + #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */ +#else + #define DURATION_RX_TO_TX (4) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */ +#endif + +#define FRAME_PERIOD 100000000ULL +#define DAQ_PERIOD 66667ULL +#define FIFO_PRIORITY 40 + +typedef enum { + pss=0, + pbch=1, + si=2 +} sync_mode_t; + + +PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms, + uint8_t UE_id, + uint8_t abstraction_flag) + +{ + PHY_VARS_NR_UE *ue; + + if (frame_parms!=(NR_DL_FRAME_PARMS *)NULL) { // if we want to give initial frame parms, allocate the PHY_VARS_UE structure and put them in + ue = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE)); + memset(ue,0,sizeof(PHY_VARS_NR_UE)); + memcpy(&(ue->frame_parms), frame_parms, sizeof(NR_DL_FRAME_PARMS)); + } else ue = PHY_vars_UE_g[UE_id][0]; + + ue->Mod_id = UE_id; + ue->mac_enabled = 1; + // initialize all signal buffers + init_nr_ue_signal(ue,1,abstraction_flag); + // intialize transport + init_nr_ue_transport(ue,abstraction_flag); + return(ue); +} + +/*! + * It performs band scanning and synchonization. + * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. + */ + +typedef struct syncData_s { + PHY_VARS_NR_UE *UE; +} syncData_t; + +static void UE_synch(void *arg) { + syncData_t *syncD=(syncData_t *) arg; + int i, hw_slot_offset; + PHY_VARS_NR_UE *UE = syncD->UE; + int current_band = 0; + int current_offset = 0; + sync_mode_t sync_mode = pbch; + int CC_id = UE->CC_id; + int freq_offset=0; + UE->is_synchronized = 0; + + if (UE->UE_scan == 0) { + int ind; + + get_band(downlink_frequency[CC_id][0], &UE->frame_parms.eutra_band, &uplink_frequency_offset[CC_id][0], &UE->frame_parms.frame_type); + + LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", + downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0], + oai_exit, openair0_cfg[0].rx_num_channels); + + for (i=0; irf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + + if (uplink_frequency_offset[CC_id][i] != 0) // + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD; + else //FDD + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD; + } + + sync_mode = pbch; + } else { + current_band=0; + LOG_E(PHY,"Fixme!\n"); + /* + for (i=0; irf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = + bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + } + */ + } + + LOG_W(PHY, "Starting sync detection\n"); + + switch (sync_mode) { + /* + case pss: + LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + //lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + current_offset += 20000000; // increase by 20 MHz + + if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) { + current_band++; + current_offset=0; + } + + if (current_band==bands_to_scan.nbands) { + current_band=0; + oai_exit=1; + } + + for (i=0; irf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + + if (UE->UE_scan_carrier) { + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } + } + + break; + */ + + case pbch: + LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); + + if (nr_initial_sync( UE, UE->mode ) == 0) { + freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync + hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_slot; + LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", + hw_slot_offset, + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset, + UE->UE_scan_carrier ); + + // rerun with new cell parameters and frequency-offset + for (i=0; irf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + + if (freq_offset >= 0) + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); + else + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset); + + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; + downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; + } + + // reconfigure for potentially different bandwidth + switch(UE->frame_parms.N_RB_DL) { + case 6: + openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; + openair0_cfg[UE->rf_map.card].rx_bw =.96e6; + openair0_cfg[UE->rf_map.card].tx_bw =.96e6; + // openair0_cfg[0].rx_gain[0] -= 12; + break; + + case 25: + openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; + openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; + openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; + // openair0_cfg[0].rx_gain[0] -= 6; + break; + + case 50: + openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; + openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; + openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; + // openair0_cfg[0].rx_gain[0] -= 3; + break; + + case 100: + openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; + openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; + openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; + // openair0_cfg[0].rx_gain[0] -= 0; + break; + } + + if (UE->mode != loop_through_memory) { + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); + //UE->rfdevice.trx_stop_func(&UE->rfdevice); + // sleep(1); + //nr_init_frame_parms_ue(&UE->frame_parms); + /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { + LOG_E(HW,"Could not start the device\n"); + oai_exit=1; + }*/ + } + + if (UE->UE_scan_carrier == 1) { + UE->UE_scan_carrier = 0; + } else { + UE->is_synchronized = 1; + } + } else { + // initial sync failed + // calculate new offset and try again + if (UE->UE_scan_carrier == 1) { + if (freq_offset >= 0) + freq_offset += 100; + + freq_offset *= -1; + LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); + + for (i=0; irf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + + if (UE->UE_scan_carrier==1) + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } + + if (UE->mode != loop_through_memory) + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + }// initial_sync=0 + + break; + + case si: + default: + break; + } + } +} + +void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { + // 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.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); + printf("Processing slot %d\n",proc->nr_tti_rx); +#ifdef UE_SLOT_PARALLELISATION + phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); +#else + phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode); + // printf(">>> nr_ue_pdcch_procedures ended\n"); +#endif + } + + if (UE->mac_enabled==1) { + // trigger L2 to run ue_scheduler thru IF module + // [TODO] mapping right after NR initial sync + if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) { + UE->ul_indication.module_id = 0; + UE->ul_indication.gNB_index = 0; + UE->ul_indication.cc_id = 0; + UE->ul_indication.frame = proc->frame_rx; + UE->ul_indication.slot = proc->nr_tti_rx; + UE->if_inst->ul_indication(&UE->ul_indication); + } + } +} + +/*! + * \brief This is the UE thread for RX subframe n and TX subframe n+4. + * This thread performs the phy_procedures_UE_RX() on every received slot. + * then, if TX is enabled it performs TX for n+4. + * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ + +typedef struct processingData_s { + UE_nr_rxtx_proc_t proc; + PHY_VARS_NR_UE *UE; +} processingData_t; + +void UE_processing(void *arg) { + processingData_t *rxtxD=(processingData_t *) arg; + UE_nr_rxtx_proc_t *proc = &rxtxD->proc; + PHY_VARS_NR_UE *UE = rxtxD->UE; + processSubframeRX(UE, proc); + //printf(">>> mac ended\n"); + // Prepare the future Tx data +#if 0 +#ifndef NO_RAT_NR + + if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_UPLINK_SLOT) +#else + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || + (UE->frame_parms.frame_type == FDD) ) +#endif + if (UE->mode != loop_through_memory) + phy_procedures_nrUE_TX(UE,proc,0,0,UE->mode,no_relay); + + //phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay); +#endif +#if 0 + + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) && + (UE->frame_parms.frame_type == TDD)) + if (UE->mode != loop_through_memory) + //phy_procedures_UE_S_TX(UE,0,0,no_relay); + updateTimes(current, &t3, 10000, timing_proc_name); + +#endif +} + +void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + void *rxp[NB_ANTENNAS_RX]; + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); + + for(int x=0; x<10; x++) { + for (int i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe; + + AssertFatal( UE->frame_parms.samples_per_subframe == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + rxp, + UE->frame_parms.samples_per_subframe, + UE->frame_parms.nb_antennas_rx), ""); + } + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + free(dummy_tx[i]); +} + +void trashFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); + + void *dummy_rx[UE->frame_parms.nb_antennas_rx]; + + for (int i=0; iframe_parms.nb_antennas_rx; i++) + dummy_rx[i]=malloc16(UE->frame_parms.samples_per_subframe*4); + + for (int sf=0; sfrfdevice.trx_read_func(&UE->rfdevice, + timestamp, + dummy_rx, + UE->frame_parms.samples_per_subframe, + UE->frame_parms.nb_antennas_rx); + } + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + free(dummy_tx[i]); + + for (int i=0; iframe_parms.nb_antennas_rx; i++) + free(dummy_rx[i]); +} + +void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + if (UE->no_timing_correction==0) { + LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); + + for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { + int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; + AssertFatal(unitTransfer == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx),""); + } + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + free(dummy_tx[i]); + } +} + +int computeSamplesShift(PHY_VARS_NR_UE *UE) { + if ( getenv("RFSIMULATOR") != 0) { + LOG_E(PHY,"SET rx_offset %d \n",UE->rx_offset); + //UE->rx_offset_diff=0; + return 0; + } + + // compute TO compensation that should be applied for this frame + if ( UE->rx_offset < 5*UE->frame_parms.samples_per_slot && + UE->rx_offset > 0 ) + return -1 ; + + if ( UE->rx_offset > 5*UE->frame_parms.samples_per_slot && + UE->rx_offset < 10*UE->frame_parms.samples_per_slot ) + return 1; + + return 0; +} + +void *UE_thread(void *arg) { + PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; + // int tx_enabled = 0; + openair0_timestamp timestamp; + void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX]; + int start_rx_stream = 0; + const uint16_t table_sf_slot[20] = {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9}; + AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); + UE->rfdevice.host_type = RAU_HOST; + AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); + notifiedFIFO_t nf; + initNotifiedFIFO(&nf); + bool syncRunning=false; + notifiedFIFO_elt_t *syncMsg=newNotifiedFIFO_elt(sizeof(syncData_t),0,&nf,UE_synch); + syncData_t *syncD=(syncData_t *)NotifiedFifoData(syncMsg); + syncD->UE=UE; + int nbSlotProcessing=0; + int thread_idx=0; + notifiedFIFO_elt_t *processingMsg[RX_NB_TH]; + + for (int i=0; iUE=UE; + } + + const int nb_slot_frame = 10*UE->frame_parms.slots_per_subframe; + int absolute_slot=-1; + + while (!oai_exit) { + if (!syncD->UE->is_synchronized) { + if (syncRunning) { + notifiedFIFO_elt_t *res=tryPullTpool(&nf, Tpool); + + if (res) { + syncRunning=false; + } else + trashFrame(UE, ×tamp); + } else { + readFrame(UE, ×tamp); + pushTpool(Tpool, syncMsg); + syncRunning=true; + } + + continue; + } + + if (start_rx_stream==0) { + start_rx_stream=1; + syncInFrame(UE, ×tamp); + UE->rx_offset=0; + UE->time_sync_cell=0; + //printf("first stream frame rx %d\n",UE->proc.proc_rxtx[0].frame_rx); + // read in first symbol + AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void **)UE->common_vars.rxdata, + UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx),""); + continue; + } + + absolute_slot++; + thread_idx = absolute_slot % RX_NB_TH; + int slot_nr=absolute_slot % nb_slot_frame; + UE_nr_rxtx_proc_t *proc=&(((processingData_t *)NotifiedFifoData(processingMsg[thread_idx]))->proc); + // update thread index for received subframe + proc->nr_tti_rx= slot_nr; + UE->current_thread_id[slot_nr] = thread_idx; + proc->subframe_rx=table_sf_slot[slot_nr]; + proc->nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame; + proc->subframe_tx=proc->nr_tti_rx; + proc->frame_rx = ( absolute_slot/nb_slot_frame ) % MAX_FRAME_NUMBER; + proc->frame_tx = ( (absolute_slot + DURATION_RX_TO_TX) /nb_slot_frame ) % MAX_FRAME_NUMBER; + LOG_D(PHY,"Process slot %d thread Idx %d \n", slot_nr, thread_idx); + + for (int i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+ + UE->frame_parms.nb_prefix_samples0+ + slot_nr*UE->frame_parms.samples_per_slot]; + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + txp[i] = (void *)&UE->common_vars.txdata[i][proc->nr_tti_tx*UE->frame_parms.samples_per_slot]; + + int readBlockSize, writeBlockSize; + + if (slot_nr<(nb_slot_frame - 1)) { + readBlockSize=UE->frame_parms.samples_per_slot; + writeBlockSize=UE->frame_parms.samples_per_slot; + } else { + UE->rx_offset_diff = computeSamplesShift(UE); + readBlockSize=UE->frame_parms.samples_per_slot - + UE->frame_parms.ofdm_symbol_size - + UE->frame_parms.nb_prefix_samples0 - + UE->rx_offset_diff; + writeBlockSize=UE->frame_parms.samples_per_slot - + UE->rx_offset_diff; + } + + AssertFatal(readBlockSize == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + readBlockSize, + UE->frame_parms.nb_antennas_rx),""); + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+ + (2*UE->frame_parms.samples_per_slot) - + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - + openair0_cfg[0].tx_sample_advance, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + 1),""); + + if( slot_nr==(nb_slot_frame-1)) { + // read in first symbol of next frame and adjust for timing drift + int first_symbols=writeBlockSize-readBlockSize; + + if ( first_symbols > 0 ) + AssertFatal(first_symbols == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void **)UE->common_vars.rxdata, + first_symbols, + UE->frame_parms.nb_antennas_rx),""); + else + LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols); + } + + proc->timestamp_tx = timestamp+ + (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot)- + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; + + if (getenv("RFSIMULATOR")) { + // FixMe: Wait previous thread is done, because race conditions seems too bad + // in case of actual RF board, the overlap between threads mitigate the issue + while (!tryPullTpool(&nf, Tpool)) { + nbSlotProcessing--; + usleep(200); + } + } + + while (nbSlotProcessing >= RX_NB_TH && !tryPullTpool(&nf, Tpool)) { + nbSlotProcessing--; + usleep(200); + } + + pushTpool(Tpool, processingMsg[thread_idx]); + } // while !oai_exit + + return NULL; +} + +void init_UE(int nb_inst) { + int inst; + NR_UE_MAC_INST_t *mac_inst; + pthread_t threads[nb_inst]; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedpolicy(&attr, SCHED_RR); + struct sched_param sched; + sched.sched_priority = sched_get_priority_max(SCHED_RR)-1; + pthread_attr_setschedparam(&attr, &sched); + + for (inst=0; inst < nb_inst; inst++) { + // UE->rfdevice.type = NONE_DEV; + //PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; + LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]); + PHY_vars_UE_g[inst][0] = init_nr_ue_vars(NULL,inst,0); + PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; + AssertFatal((UE->if_inst = nr_ue_if_module_init(inst)) != NULL, "can not initial IF module\n"); + nr_l3_init_ue(); + nr_l2_init_ue(); + mac_inst = get_mac_inst(0); + mac_inst->if_module = UE->if_inst; + UE->if_inst->scheduled_response = nr_ue_scheduled_response; + UE->if_inst->phy_config_request = nr_ue_phy_config_request; + LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]); + //init_UE_threads(inst); + //UE = PHY_vars_UE_g[inst][0]; + AssertFatal(0 == pthread_create(&threads[inst], + &attr, + UE_thread, + (void *)UE), ""); + } + + printf("UE threads created by %ld\n", gettid()); +} + diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c new file mode 100644 index 0000000000..e6a97c8f28 --- /dev/null +++ b/executables/nr-uesoftmodem.c @@ -0,0 +1,831 @@ +/* + * 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 + */ + + +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include + +#include "T.h" +#include "assertions.h" +#include "PHY/types.h" +#include "PHY/defs_nr_UE.h" +#include "common/ran_context.h" +#include "common/config/config_userapi.h" +#include "common/utils/load_module_shlib.h" +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "../../ARCH/COMMON/common_lib.h" +#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" + +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "PHY/phy_vars_nr_ue.h" +#include "PHY/LTE_TRANSPORT/transport_vars.h" +#include "SCHED/sched_common_vars.h" +#include "PHY/MODULATION/modulation_vars.h" +//#include "../../SIMU/USER/init_lte.h" + +#include "LAYER2/MAC/mac_vars.h" +#include "LAYER2/MAC/mac_proto.h" +#include "RRC/LTE/rrc_vars.h" +#include "PHY_INTERFACE/phy_interface_vars.h" + +#ifdef SMBV +#include "PHY/TOOLS/smbv.h" +unsigned short config_frames[4] = {2,9,11,13}; +#endif +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "UTIL/OPT/opt.h" +#include "enb_config.h" +//#include "PHY/TOOLS/time_meas.h" + +#ifndef OPENAIR2 + #include "UTIL/OTG/otg_vars.h" +#endif + +#include "intertask_interface.h" +#include "create_tasks.h" + +#include "PHY/INIT/phy_init.h" +#include "system.h" +#include +#include +#include +#include +#include + +#ifdef XFORMS +#include + +/* Callbacks, globals and object handlers */ + +extern void reset_stats( FL_OBJECT *, long ); + +/* Forms and Objects */ + +typedef struct { + FL_FORM *stats_form; + void *vdata; + char *cdata; + long ldata; + FL_OBJECT *stats_text; + FL_OBJECT *stats_button; +} FD_stats_form; + +extern FD_stats_form *create_form_stats_form( void ); + +#include "PHY/TOOLS/nr_phy_scope.h" +//#include "stats.h" +// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) +// at eNB 0, an UL scope for every UE +FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX]; +//FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; +//FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; +char title[255]; +//unsigned char scope_enb_num_ue = 2; +static pthread_t forms_thread; //xforms +#endif //XFORMS +#include + +RAN_CONTEXT_t RC; +volatile int start_eNB = 0; +volatile int start_UE = 0; +volatile int oai_exit = 0; + +static clock_source_t clock_source = internal; +int single_thread_flag=1; + +int threequarter_fs=0; + +uint32_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +extern int16_t nr_dlsch_demod_shift; + +int UE_scan = 0; +int UE_scan_carrier = 0; +int UE_fo_compensation = 0; +runmode_t mode = normal_txrx; +openair0_config_t openair0_cfg[MAX_CARDS]; + +#if MAX_NUM_CCs == 1 +rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}}; +double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}}; +double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}}; +#else +rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}}; +double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}}; +double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; +#endif + +double rx_gain_off = 0.0; + +double sample_rate=30.72e6; +double bw = 10.0e6; + +static int tx_max_power[MAX_NUM_CCs] = {0}; + +char rf_config_file[1024]; + +int chain_offset=0; +int phy_test = 0; +uint8_t usim_test = 0; + +uint8_t dci_Format = 0; +uint8_t agregation_Level =0xFF; + +uint8_t nb_antenna_tx = 1; +uint8_t nb_antenna_rx = 1; + +char ref[128] = "internal"; +char channels[128] = "0"; + +char *parallel_config = NULL; +char *worker_config = NULL; + +static THREAD_STRUCT thread_struct; +void set_parallel_conf(char *parallel_conf) { + if(strcmp(parallel_conf,"PARALLEL_SINGLE_THREAD")==0) thread_struct.parallel_conf = PARALLEL_SINGLE_THREAD; + else if(strcmp(parallel_conf,"PARALLEL_RU_L1_SPLIT")==0) thread_struct.parallel_conf = PARALLEL_RU_L1_SPLIT; + else if(strcmp(parallel_conf,"PARALLEL_RU_L1_TRX_SPLIT")==0) thread_struct.parallel_conf = PARALLEL_RU_L1_TRX_SPLIT; + + printf("[CONFIG] parallel conf is set to %d\n",thread_struct.parallel_conf); +} +void set_worker_conf(char *worker_conf) { + if(strcmp(worker_conf,"WORKER_DISABLE")==0) thread_struct.worker_conf = WORKER_DISABLE; + else if(strcmp(worker_conf,"WORKER_ENABLE")==0) thread_struct.worker_conf = WORKER_ENABLE; + + printf("[CONFIG] worker conf is set to %d\n",thread_struct.worker_conf); +} +PARALLEL_CONF_t get_thread_parallel_conf(void) { + return thread_struct.parallel_conf; +} +WORKER_CONF_t get_thread_worker_conf(void) { + return thread_struct.worker_conf; +} +int rx_input_level_dBm; + +//static int online_log_messages=0; + +#ifdef XFORMS + extern int otg_enabled; + int do_forms=0; +#else + int otg_enabled; +#endif +//int number_of_cards = 1; + +static NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; +static nfapi_nr_config_request_t *config[MAX_NUM_CCs]; +int16_t node_synch_ref[MAX_NUM_CCs]; + +uint32_t target_dl_mcs = 28; //maximum allowed mcs +uint32_t target_ul_mcs = 20; +uint32_t timing_advance = 0; +uint8_t exit_missed_slots=1; +uint64_t num_missed_slots=0; // counter for the number of missed slots + + +int transmission_mode=1; +int numerology = 0; + +/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */ +//uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; +/* struct for ethernet specific parameters given in eNB conf file */ +//eth_params_t *eth_params; + +double cpuf; + +char uecap_xer[1024],uecap_xer_in=0; + +int oaisim_flag=0; +int emulate_rf = 0; + +tpool_t *Tpool; + +char *usrp_args=NULL; +char *usrp_clksrc=NULL; + +/* forward declarations */ +void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); + + +/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed + * this is very hackish - find a proper solution + */ +uint8_t abstraction_flag=0; + +/*---------------------BMC: timespec helpers -----------------------------*/ + +struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; +struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + +struct timespec clock_difftime(struct timespec start, struct timespec end) { + struct timespec temp; + + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + + return temp; +} + +void print_difftimes(void) { + LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +} + +void exit_function(const char *file, const char *function, const int line, const char *s) { + int CC_id; + + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + + oai_exit = 1; + + if (PHY_vars_UE_g && PHY_vars_UE_g[0]) { + for(CC_id=0; CC_idrfdevice.trx_end_func) + PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } + } + + sleep(1); //allow lte-softmodem threads to exit first + itti_terminate_tasks (TASK_UNKNOWN); +} + +#ifdef XFORMS + + +void reset_stats(FL_OBJECT *button, long arg) { + //int i,j,k; + /*PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0]; + + for (i=0; idlsch[i][0]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0; + } + + phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0; + + for (j=0; julsch[i]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0; + } + } + + phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0; + phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0; + phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0; + }*/ +} + +static void *scope_thread(void *arg) { + struct sched_param sched_param; + sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; + sched_setscheduler(0, SCHED_FIFO,&sched_param); + printf("Scope thread has priority %d\n",sched_param.sched_priority); + //wait the modem is runnign + sleep(5); + + while (!oai_exit) { + phy_scope_UE(form_ue[0], + PHY_vars_UE_g[0][0], + 0,0,1); + usleep(100*1000); + } + + pthread_exit((void *)arg); +} +#endif + +void init_scope(void) { +#ifdef XFORMS + int ret; + int fl_argc=1; + + if (do_forms==1) { + char *name="5G-UE-scope"; + fl_initialize (&fl_argc, &name, NULL, 0, 0); + int UE_id = 0; + form_ue[UE_id] = create_lte_phy_scope_ue(); + sprintf (title, "NR DL SCOPE UE"); + fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + fl_set_button(form_ue[UE_id]->button_0,0); + fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); + ret = pthread_create(&forms_thread, NULL, scope_thread, NULL); + + if (ret == 0) + pthread_setname_np( forms_thread, "xforms" ); + + printf("Scope thread created, ret=%d\n",ret); + } + +#endif +} + + +#if defined(ENABLE_ITTI) +void *l2l1_task(void *arg) { + MessageDef *message_p = NULL; + int result; + itti_set_task_real_time(TASK_L2L1); + itti_mark_task_ready(TASK_L2L1); + + do { + // Wait for a message + itti_receive_msg (TASK_L2L1, &message_p); + + switch (ITTI_MSG_ID(message_p)) { + case TERMINATE_MESSAGE: + oai_exit=1; + itti_exit_task (); + break; + + case ACTIVATE_MESSAGE: + start_UE = 1; + break; + + case DEACTIVATE_MESSAGE: + start_UE = 0; + break; + + case MESSAGE_TEST: + LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); + break; + + default: + LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } while(!oai_exit); + + return NULL; +} +#endif + +int16_t dlsch_demod_shift; + +static void get_options(void) { + int CC_id; + int tddflag=0, nonbiotflag; + char *loopfile=NULL; + int dumpframe=0; + uint32_t online_log_messages; + uint32_t glog_level, glog_verbosity; + uint32_t start_telnetsrv=0; + paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ; + paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ; + config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); + + if (strlen(in_path) > 0) { + opt_type = OPT_PCAP; + opt_enabled=1; + printf("Enabling OPT for PCAP with the following file %s \n",in_path); + } + + if (strlen(in_ip) > 0) { + opt_enabled=1; + opt_type = OPT_WIRESHARK; + printf("Enabling OPT for wireshark for local interface"); + } + + config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL); + + if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) { + set_glog_onlinelog(online_log_messages); + } + + if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) { + set_glog(glog_level); + } + + if (start_telnetsrv) { + load_module_shlib("telnetsrv",NULL,0,NULL); + } + + paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC; + paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC; + config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL); + config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL); + + if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue; + + if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med; + + if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp; + + if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) + if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach; + + if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) + if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0) mode = no_L2_connect; + + if (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) + if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx; + + if (dumpframe > 0) mode = rx_dump_frame; + + for (CC_id=0; CC_iddl_CarrierFreq = downlink_frequency[0][0]; + } + + UE_scan=0; + + if (tddflag > 0) { + for (CC_id=0; CC_idframe_type = TDD; + } + + /*if (frame_parms[0]->N_RB_DL !=0) { + if ( frame_parms[0]->N_RB_DL < 6 ) { + frame_parms[0]->N_RB_DL = 6; + printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL); + } + if ( frame_parms[0]->N_RB_DL > 100 ) { + frame_parms[0]->N_RB_DL = 100; + printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL); + } + if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) { + frame_parms[0]->N_RB_DL = 50; + printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL); + } + if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) { + frame_parms[0]->N_RB_DL = 25; + printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL); + } + UE_scan = 0; + frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL; + for (CC_id=1; CC_idN_RB_DL=frame_parms[0]->N_RB_DL; + frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL; + } + }*/ + + for (CC_id=1; CC_idsubframe_config.numerology_index_mu.value =1; + config[CC_id]->subframe_config.duplex_mode.value = 1; //FDD + config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL + config[CC_id]->rf_config.dl_carrier_bandwidth.value = 106; + config[CC_id]->rf_config.ul_carrier_bandwidth.value = 106; + config[CC_id]->sch_config.physical_cell_id.value = 0; + + frame_parms[CC_id]->eutra_band = 78; + frame_parms[CC_id]->frame_type = FDD; + frame_parms[CC_id]->tdd_config = 3; + //frame_parms[CC_id]->tdd_config_S = 0; + frame_parms[CC_id]->N_RB_DL = 106; + frame_parms[CC_id]->N_RB_UL = 106; + frame_parms[CC_id]->Ncp = NORMAL; + //frame_parms[CC_id]->Ncp_UL = NORMAL; + frame_parms[CC_id]->Nid_cell = 0; + //frame_parms[CC_id]->num_MBSFN_config = 0; + frame_parms[CC_id]->nb_antenna_ports_eNB = 1; + frame_parms[CC_id]->nb_antennas_tx = 1; + frame_parms[CC_id]->nb_antennas_rx = 1; + //frame_parms[CC_id]->nushift = 0; + ///frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; + //frame_parms[CC_id]->phich_config_common.phich_duration = normal; + // UL RS Config + /*frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 1;//n_DMRS1 set to 0 + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + + frame_parms[CC_id]->pusch_config_common.n_SB = 1; + frame_parms[CC_id]->pusch_config_common.hoppingMode = 0; + frame_parms[CC_id]->pusch_config_common.pusch_HoppingOffset = 0; + frame_parms[CC_id]->pusch_config_common.enable64QAM = 0; + + frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;*/ + // NR: Init to legacy LTE 20Mhz params + frame_parms[CC_id]->numerology_index = 0; + frame_parms[CC_id]->ttis_per_subframe = 1; + frame_parms[CC_id]->slots_per_tti = 2; + } +} + +void init_openair0(void) { + int card; + int i; + + for (card=0; cardN_RB_DL == 106) { + if (numerology==0) { + if (frame_parms[0]->threequarter_fs) { + openair0_cfg[card].sample_rate=23.04e6; + openair0_cfg[card].samples_per_frame = 230400; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } else { + openair0_cfg[card].sample_rate=30.72e6; + openair0_cfg[card].samples_per_frame = 307200; + 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==2) { + openair0_cfg[card].sample_rate=122.88e6; + openair0_cfg[card].samples_per_frame = 307200; + 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 == 50) { + openair0_cfg[card].sample_rate=15.36e6; + openair0_cfg[card].samples_per_frame = 153600; + openair0_cfg[card].tx_bw = 5e6; + openair0_cfg[card].rx_bw = 5e6; + } else if (frame_parms[0]->N_RB_DL == 25) { + openair0_cfg[card].sample_rate=7.68e6; + openair0_cfg[card].samples_per_frame = 76800; + openair0_cfg[card].tx_bw = 2.5e6; + openair0_cfg[card].rx_bw = 2.5e6; + } else if (frame_parms[0]->N_RB_DL == 6) { + openair0_cfg[card].sample_rate=1.92e6; + openair0_cfg[card].samples_per_frame = 19200; + openair0_cfg[card].tx_bw = 1.5e6; + openair0_cfg[card].rx_bw = 1.5e6; + } + + if (frame_parms[0]->frame_type==TDD) + openair0_cfg[card].duplex_mode = duplex_mode_TDD; + else //FDD + openair0_cfg[card].duplex_mode = duplex_mode_FDD; + + printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, + PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx, + PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); + openair0_cfg[card].Mod_id = 0; + openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; + openair0_cfg[card].clock_source = clock_source; + openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx); + openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); + + for (i=0; i<4; i++) { + if (irx_total_gain_dB - rx_gain_off; + openair0_cfg[card].configFilename = rf_config_file; + printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n", + card,i, openair0_cfg[card].tx_gain[i], + openair0_cfg[card].rx_gain[i], + openair0_cfg[card].tx_freq[i], + openair0_cfg[card].rx_freq[i]); + } + + if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args; + + if (usrp_clksrc) { + if (strcmp(usrp_clksrc, "internal") == 0) { + openair0_cfg[card].clock_source = internal; + LOG_D(PHY, "USRP clock source set as internal\n"); + } else if (strcmp(usrp_clksrc, "external") == 0) { + openair0_cfg[card].clock_source = external; + LOG_D(PHY, "USRP clock source set as external\n"); + } else if (strcmp(usrp_clksrc, "gpsdo") == 0) { + openair0_cfg[card].clock_source = gpsdo; + LOG_D(PHY, "USRP clock source set as gpsdo\n"); + } else { + openair0_cfg[card].clock_source = internal; + LOG_I(PHY, "USRP clock source unknown ('%s'). defaulting to internal\n", usrp_clksrc); + } + } else { + openair0_cfg[card].clock_source = internal; + LOG_I(PHY, "USRP clock source not specified. defaulting to internal\n"); + } + } +} + + +int main( int argc, char **argv ) { + //uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; + PHY_VARS_NR_UE *UE[MAX_NUM_CCs]; + start_background_system(); + + if ( load_configmodule(argc,argv) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + set_default_frame_parms(frame_parms); + mode = normal_txrx; + memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS); + memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); + // initialize logging + logInit(); + // get options and fill parameters from configuration file + get_options (); //Command-line options, enb_properties +#if T_TRACER + T_Config_Init(); +#endif + //randominit (0); + set_taus_seed (0); + tpool_t pool; + Tpool = &pool; + char params[]="-1,-1,-1,-1"; + initTpool(params, Tpool, false); + cpuf=get_cpu_freq_GHz(); + itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + + if (opt_type != OPT_NONE) { + if (init_opt(in_path, in_ip) == -1) + LOG_E(OPT,"failed to run OPT \n"); + } + +#ifdef PDCP_USE_NETLINK + netlink_init(); +#if defined(PDCP_USE_NETLINK_QUEUES) + pdcp_netlink_init(); +#endif +#endif +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + + // init the parameters + for (int CC_id=0; CC_idnb_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 + 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); + + } + + NB_UE_INST=1; + NB_INST=1; + PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE **)); + PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE *)*MAX_NUM_CCs); + + for (int CC_id=0; CC_idofdm_symbol_size); + nr_init_frame_parms_ue(frame_parms[CC_id],numerology,NORMAL,frame_parms[CC_id]->N_RB_DL,(frame_parms[CC_id]->N_RB_DL-20)>>1,0); + PHY_vars_UE_g[0][CC_id] = init_nr_ue_vars(frame_parms[CC_id], 0,abstraction_flag); + UE[CC_id] = PHY_vars_UE_g[0][CC_id]; + + if (phy_test==1) + UE[CC_id]->mac_enabled = 0; + else + UE[CC_id]->mac_enabled = 1; + + if (UE[CC_id]->mac_enabled == 0) { //set default UL parameters for testing mode + for (int i=0; ipusch_config_dedicated[i] = malloc(sizeof(PUSCH_CONFIG_DEDICATED)); + //UE[CC_id]->scheduling_request_config[i] = malloc(sizeof(SCHEDULING_REQUEST_CONFIG)); + /*UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; + UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; + UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; + + UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0; + UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3); + UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;*/ + } + } + + UE[CC_id]->UE_scan = UE_scan; + UE[CC_id]->UE_scan_carrier = UE_scan_carrier; + UE[CC_id]->UE_fo_compensation = UE_fo_compensation; + UE[CC_id]->mode = mode; + printf("UE[%d]->mode = %d\n",CC_id,mode); + + for (uint8_t i=0; imac_enabled == 1) + UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1234; + else + UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1235; + } + + UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; + UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; + + if (frame_parms[CC_id]->frame_type==FDD) { + UE[CC_id]->N_TA_offset = 0; + } else { + if (frame_parms[CC_id]->N_RB_DL == 100) + UE[CC_id]->N_TA_offset = 624; + else if (frame_parms[CC_id]->N_RB_DL == 50) + UE[CC_id]->N_TA_offset = 624/2; + else if (frame_parms[CC_id]->N_RB_DL == 25) + UE[CC_id]->N_TA_offset = 624/4; + } + } + + // printf("tx_max_power = %d -> amp %d\n",tx_max_power[0],get_tx_amp(tx_max_poHwer,tx_max_power)); + init_openair0(); + // init UE_PF_PO and mutex lock + pthread_mutex_init(&ue_pf_po_mutex, NULL); + memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); + mlockall(MCL_CURRENT | MCL_FUTURE); + init_scope(); + number_of_cards = 1; + + for(int CC_id=0; CC_idrf_map.card=0; + PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; +#if defined(OAI_USRP) || defined(OAI_ADRV9371_ZC706) + PHY_vars_UE_g[0][CC_id]->hw_timing_advance = timing_advance; +#else + PHY_vars_UE_g[0][CC_id]->hw_timing_advance = 160; +#endif + } + + // wait for end of program + printf("TYPE TO TERMINATE\n"); + init_UE(1); + + while(true) + sleep(3600); + + return 0; +} diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h new file mode 100644 index 0000000000..df6b2f7282 --- /dev/null +++ b/executables/nr-uesoftmodem.h @@ -0,0 +1,246 @@ +#ifndef NR_UESOFTMODEM_H +#define NR_UESOFTMODEM_H + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../../ARCH/COMMON/common_lib.h" +#undef MALLOC +#include "assertions.h" +#include "PHY/types.h" +#include "PHY/defs_nr_UE.h" +#include "SIMULATION/ETH_TRANSPORT/proto.h" +#include + + +#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 */ + + +/*------------------------------------------------------------------------------------------------------------------------------------------*/ +/* 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 +/*------------------------------------------------------------------------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters specific to UE */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*--------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_UEPARAMS_DESC { \ + {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ + {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \ + {"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ + {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \ + {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \ + {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&UE_fo_compensation, defintval:0, TYPE_INT, 0}, \ + {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ + {"r" , CONFIG_HLP_PRB, 0, iptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ + {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ + {"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200", TYPE_STRING, 0}, \ + {"usrp-clksrc", CONFIG_HLP_USRP_CLK_SRC,0, strptr:(char **)&usrp_clksrc, defstrval:"internal", TYPE_STRING, 0} \ + } + +#define DEFAULT_DLF 2680000000 + +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters common to eNodeB and UE */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_PARAMS_DESC { \ + {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \ + {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ + {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \ + {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&usim_test, defintval:0, TYPE_UINT8, 0}, \ + {"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \ + {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ + {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \ + {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ + {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, iptr:&do_forms, defintval:0, TYPE_INT, 0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0}, \ + {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ + {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ + {"W" , CONFIG_HLP_L2MONW, 0, strptr:(char **)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, sizeof(in_ip)}, \ + {"P" , CONFIG_HLP_L2MONP, 0, strptr:(char **)&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, sizeof(in_path)}, \ + {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ + {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ + {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ + {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ + {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ + {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0} \ + } + +#define CONFIG_HLP_FLOG "Enable online log \n" +#define CONFIG_HLP_LOGL "Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n" +#define CONFIG_HLP_LOGV "Set the global log verbosity \n" +#define CONFIG_HLP_TELN "Start embedded telnet server \n" +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters for LOG utility */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_LOGPARAMS_DESC { \ + {"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \ + {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ + {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \ + {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ + } +#define CMDLINE_ONLINELOG_IDX 0 +#define CMDLINE_GLOGLEVEL_IDX 1 +#define CMDLINE_GLOGVERBO_IDX 2 +#define CMDLINE_STARTTELN_IDX 3 + + +extern int T_port; +extern int T_nowait; +extern int T_dont_fork; + + + +/***************************************************************************************************************************************/ + +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; + + +extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; +extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +extern int rx_input_level_dBm; +extern uint8_t exit_missed_slots; +extern uint64_t num_missed_slots; // counter for the number of missed slots + +extern int oaisim_flag; +extern volatile int oai_exit; + +extern openair0_config_t openair0_cfg[MAX_CARDS]; +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; +extern int transmission_mode; +extern double cpuf; + +#if defined(ENABLE_ITTI) + extern volatile int start_eNB; + extern volatile int start_UE; +#endif + +// In nr-ue.c +extern int setup_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg); +extern void fill_ue_band_info(void); +extern void init_UE(int); +extern void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char *name); +extern void reset_opp_meas(void); +extern void print_opp_meas(void); +void *UE_thread(void *arg); +PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms, + uint8_t UE_id, + uint8_t abstraction_flag); +extern tpool_t *Tpool; +#endif diff --git a/maketags b/maketags index ac8d4151d4..eb7c474a38 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=openair2/RRC/CELLULAR/ --exclude=openair2/NAS/DRIVER/CELLULAR/ --exclude=openair2/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 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 36c865be01..d53e91f666 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -13,6 +13,9 @@ #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 +#define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 +#define NFAPI_NR_MAX_NB_CORESETS 12 +#define NFAPI_NR_MAX_NB_SEARCH_SPACES 40 // Extension to the generic structures for single tlv values typedef struct { @@ -28,12 +31,12 @@ typedef struct { /*typedef struct { nfapi_tl_t tl; int64_t value; -} nfapi_int64_tlv_t; +} nfapi_int64_tlv_t;*/ typedef struct { nfapi_tl_t tl; uint64_t value; -} nfapi_uint64_tlv_t;*/ +} nfapi_uint64_tlv_t; // nFAPI enums typedef enum { @@ -175,8 +178,8 @@ typedef struct { nfapi_uint16_tlv_t physical_cell_id; nfapi_uint16_tlv_t half_frame_index; nfapi_uint16_tlv_t ssb_subcarrier_offset; - nfapi_uint16_tlv_t ssb_sib1_position_in_burst; - nfapi_uint16_tlv_t ssb_scg_position_in_burst; + nfapi_uint16_tlv_t ssb_sib1_position_in_burst; // in sib1 + nfapi_uint64_tlv_t ssb_scg_position_in_burst; // in servingcellconfigcommon nfapi_uint16_tlv_t ssb_periodicity; nfapi_uint16_tlv_t ss_pbch_block_power; nfapi_uint16_tlv_t n_ssb_crb; @@ -356,7 +359,8 @@ typedef enum { typedef enum { NFAPI_NR_CSET_CONFIG_MIB_SIB1=0, - NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG + NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG, // implicit assumption of coreset Id other than 0 + NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG_CSET_0 } nfapi_nr_coreset_config_type_e; typedef enum { @@ -364,6 +368,31 @@ typedef enum { NFAPI_NR_CSET_ALL_CONTIGUOUS_RBS } nfapi_nr_coreset_precoder_granularity_type_e; +typedef enum { + NFAPI_NR_QCL_TYPE_A=0, + NFAPI_NR_QCL_TYPE_B, + NFAPI_NR_QCL_TYPE_C, + NFAPI_NR_QCL_TYPE_D +} nfapi_nr_qcl_type_e; + +typedef enum { + NFAPI_NR_SS_PERIODICITY_SL1=1, + NFAPI_NR_SS_PERIODICITY_SL2=2, + NFAPI_NR_SS_PERIODICITY_SL4=4, + NFAPI_NR_SS_PERIODICITY_SL5=5, + NFAPI_NR_SS_PERIODICITY_SL8=8, + NFAPI_NR_SS_PERIODICITY_SL10=10, + NFAPI_NR_SS_PERIODICITY_SL16=16, + NFAPI_NR_SS_PERIODICITY_SL20=20, + NFAPI_NR_SS_PERIODICITY_SL40=40, + NFAPI_NR_SS_PERIODICITY_SL80=80, + NFAPI_NR_SS_PERIODICITY_SL160=160, + NFAPI_NR_SS_PERIODICITY_SL320=320, + NFAPI_NR_SS_PERIODICITY_SL640=640, + NFAPI_NR_SS_PERIODICITY_SL1280=1280, + NFAPI_NR_SS_PERIODICITY_SL2560=2560 +} nfapi_nr_search_space_monitoring_periodicity_e; + typedef enum { NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_A=0, NFAPI_NR_PDSCH_TIME_DOMAIN_ALLOC_TYPE_DEFAULT_B, @@ -496,9 +525,9 @@ typedef struct{ uint8_t css_format_2_2; uint8_t css_format_2_3; uint8_t uss_dci_formats; - uint8_t srs_monitoring_periodicity; - uint8_t slot_monitoring_periodicity; - uint8_t slot_monitoring_offset; + uint16_t srs_monitoring_periodicity; + uint16_t slot_monitoring_periodicity; + uint16_t slot_monitoring_offset; uint16_t monitoring_symbols_in_slot; uint16_t number_of_candidates[NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS]; } nfapi_nr_search_space_t; @@ -516,7 +545,7 @@ typedef struct { uint8_t aggregation_level; uint8_t n_rb; uint8_t n_symb; - uint8_t rb_offset; + int8_t rb_offset; uint8_t cr_mapping_type; uint8_t reg_bundle_size; uint8_t interleaver_size; @@ -644,4 +673,45 @@ typedef struct { nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_dl_config_request_t; + +typedef enum {nr_pusch_freq_hopping_disabled = 0 , + nr_pusch_freq_hopping_enabled = 1 + } nr_pusch_freq_hopping_t; + +typedef struct{ + uint8_t aperiodicSRS_ResourceTrigger; +} nfapi_nr_ul_srs_config_t; + +typedef struct { + uint8_t bandwidth_part_ind; + uint16_t number_rbs; + uint16_t start_rb; + uint8_t frame_offset; + uint16_t number_symbols; + uint16_t start_symbol; + 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; + uint8_t tpmi; + uint8_t n_dmrs_cdm_groups; + uint8_t dmrs_ports[4]; + uint8_t n_front_load_symb; + nfapi_nr_ul_srs_config_t srs_config; + uint8_t csi_reportTriggerSize; + uint8_t maxCodeBlockGroupsPerTransportBlock; + uint8_t ptrs_dmrs_association_port; + uint8_t beta_offset_ind; +} nfapi_nr_ul_config_ulsch_pdu_rel15_t; + +typedef struct { + uint16_t rnti; + nfapi_nr_ul_config_ulsch_pdu_rel15_t ulsch_pdu_rel15; +} nfapi_nr_ul_config_ulsch_pdu; + #endif diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c index 72ef16907c..ddcc3ce826 100644 --- a/openair1/PHY/CODING/TESTBENCH/polartest.c +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -20,7 +20,7 @@ //#define DEBUG_POLARTEST uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, - 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31}; + 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31}; void nr_init_pbch_interleaver(uint8_t *interleaver) { uint8_t j_sfn=0, j_hrf=10, j_ssb=11, j_other=14; @@ -28,7 +28,7 @@ void nr_init_pbch_interleaver(uint8_t *interleaver) { for (uint8_t i=0; idci_format, params_rel15->rnti_type, &fp->initial_bwp_dl, cfg); - testLength = 41; //20; - coderLength = 108*8; //to be changed by aggregate level function. - } else if (polarMessageType == -1) { //UCI - //testLength = ; - //coderLength = ; - } + case 'K': + testLength=atoi(optarg); + if (testLength <12 || testLength > 60) { + printf("Illegal packet bitlength\n",testLength); + exit(-1); + } + break; - //Logging - time_t currentTime; - time (¤tTime); - char fileName[512], currentTimeInfo[25]; - char folderName[] = "."; + case 'h': + printf("./polartest -s SNRstart -d SNRinc -f SNRstop -m [0=PBCH|1=DCI|2=UCI] -i iterations -l decoderListSize -a pathMetricAppr -L aggregation level (for DCI) -K packet_length (bits) for DCI/UCI\n"); + exit(-1); + break; - /* - folderName=getenv("HOME"); - strcat(folderName,"/Desktop/polartestResults"); - */ - - #ifdef DEBUG_POLAR_TIMING - sprintf(fileName,"%s/TIMING_ListSize_%d_pmAppr_%d_Payload_%d_Itr_%d",folderName,decoderListSize,pathMetricAppr,testLength,iterations); - #else - sprintf(fileName,"%s/_ListSize_%d_pmAppr_%d_Payload_%d_Itr_%d",folderName,decoderListSize,pathMetricAppr,testLength,iterations); - #endif - strftime(currentTimeInfo, 25, "_%Y-%m-%d-%H-%M-%S.csv", localtime(¤tTime)); - strcat(fileName,currentTimeInfo); + default: + perror("[polartest.c] Problem at argument parsing with getopt"); + exit(-1); + break; + } - //Create "~/Desktop/polartestResults" folder if it doesn't already exist. - /* - struct stat folder = {0}; - if (stat(folderName, &folder) == -1) mkdir(folderName, S_IRWXU | S_IRWXG | S_IRWXO); - */ - - FILE* logFile; - logFile = fopen(fileName, "w"); - if (logFile==NULL) { - fprintf(stderr,"[polartest.c] Problem creating file %s with fopen\n",fileName); - exit(-1); - } + if (polarMessageType == 0) { //PBCH + } else if (polarMessageType == 1) { //DCI + coderLength = 108*aggregation_level; + } else if (polarMessageType == -1) { //UCI + printf("UCI testing not supported yet\n"); + exit(-1); + } + //Logging + time_t currentTime; + time (¤tTime); + char fileName[512], currentTimeInfo[25]; + char folderName[] = "."; + /* + folderName=getenv("HOME"); + strcat(folderName,"/Desktop/polartestResults"); + */ #ifdef DEBUG_POLAR_TIMING - fprintf(logFile,",timeEncoderCRCByte[us],timeEncoderCRCBit[us],timeEncoderInterleaver[us],timeEncoderBitInsertion[us],timeEncoder1[us],timeEncoder2[us],timeEncoderRateMatching[us],timeEncoderByte2Bit[us]\n"); + sprintf(fileName,"%s/TIMING_ListSize_%d_pmAppr_%d_Payload_%d_Itr_%d",folderName,decoderListSize,pathMetricAppr,testLength,iterations); #else - fprintf(logFile,",SNR,nBitError,blockErrorState,t_encoder[us],t_decoder[us]\n"); + sprintf(fileName,"%s/_ListSize_%d_pmAppr_%d_Payload_%d_Itr_%d",folderName,decoderListSize,pathMetricAppr,testLength,iterations); #endif + strftime(currentTimeInfo, 25, "_%Y-%m-%d-%H-%M-%S.csv", localtime(¤tTime)); + strcat(fileName,currentTimeInfo); + //Create "~/Desktop/polartestResults" folder if it doesn't already exist. + /* + struct stat folder = {0}; + if (stat(folderName, &folder) == -1) mkdir(folderName, S_IRWXU | S_IRWXG | S_IRWXO); + */ + FILE *logFile; + logFile = fopen(fileName, "w"); - uint8_t testArrayLength = ceil(testLength / 32.0); - uint8_t coderArrayLength = ceil(coderLength / 32.0); - - uint32_t testInput[testArrayLength]; //generate randomly - uint32_t encoderOutput[coderArrayLength]; - uint32_t estimatedOutput[testArrayLength]; //decoder output - memset(testInput,0,sizeof(uint32_t) * testArrayLength); - memset(encoderOutput,0,sizeof(uint32_t) * coderArrayLength); - memset(estimatedOutput,0,sizeof(uint32_t) * testArrayLength); - - uint8_t encoderOutputByte[coderLength]; - double modulatedInput[coderLength]; //channel input - double channelOutput[coderLength]; //add noise - - int16_t channelOutput_int16[coderLength]; - - t_nrPolar_paramsPtr nrPolar_params = NULL, currentPtr = NULL; - nr_polar_init(&nrPolar_params, polarMessageType, testLength, aggregation_level); - currentPtr = nr_polar_params(nrPolar_params, polarMessageType, testLength, aggregation_level); - -#ifdef DEBUG_DCI_POLAR_PARAMS - uint32_t dci_pdu[4]; - memset(dci_pdu,0,sizeof(uint32_t)*4); - dci_pdu[0]=0x01189400; - printf("dci_pdu: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", - dci_pdu[0], dci_pdu[1], dci_pdu[2], dci_pdu[3]); - uint32_t encoder_output[54]; - memset(encoder_output,0,sizeof(uint32_t)*54); - uint16_t size=41; - uint16_t rnti=3; - aggregation_level=8; - nr_polar_init(&nrPolar_params, 1, size, aggregation_level); - t_nrPolar_paramsPtr currentPtrDCI=nr_polar_params(nrPolar_params, 1, size, aggregation_level); - - polar_encoder_dci(dci_pdu, encoder_output, currentPtrDCI, rnti); - for (int i=0;i<54;i++) - printf("encoder_output: [%2d]->0x%08x \n",i, encoder_output[i]); - - uint8_t *encoder_outputByte = malloc(sizeof(uint8_t) * currentPtrDCI->encoderLength); - double *channel_output = malloc (sizeof(double) * currentPtrDCI->encoderLength); - uint32_t dci_estimation[4]; - memset(dci_estimation,0,sizeof(uint32_t)*4); - printf("dci_estimation: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", - dci_estimation[0], dci_estimation[1], dci_estimation[2], dci_estimation[3]); - nr_bit2byte_uint32_8(encoder_output, currentPtrDCI->encoderLength, encoder_outputByte); - printf("[polartest] encoder_outputByte: "); - for (int i = 0; i < currentPtrDCI->encoderLength; i++) printf("%d-", encoder_outputByte[i]); - printf("\n"); - for(int i=0; iencoderLength; i++) { - if (encoder_outputByte[i] == 0) { - channel_output[i]=1/sqrt(2); - } - else { - channel_output[i]=(-1)/sqrt(2); - } - } - - decoderState = polar_decoder_dci(channel_output, - dci_estimation, - currentPtrDCI, - NR_POLAR_DECODER_LISTSIZE, - NR_POLAR_DECODER_PATH_METRIC_APPROXIMATION, - rnti); - printf("dci_estimation: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", - dci_estimation[0], dci_estimation[1], dci_estimation[2], dci_estimation[3]); - free(encoder_outputByte); - free(channel_output); - return 0; -#endif - -#ifdef DEBUG_CRC - uint32_t crc; - unsigned int poly24c = 0xb2b11700; - uint32_t testInputCRC[4]; - testInputCRC[0]=0x00291880; - //testInputCRC[0]=0x01189400; - testInputCRC[1]=0x00000000; - testInputCRC[2]=0x00000000; - testInputCRC[3]=0x00000000; - - uint32_t testInputcrc=0x01189400; - uint32_t testInputcrc2=0x00291880; - - uint8_t testInputCRC2[8]; - nr_crc_bit2bit_uint32_8(testInputCRC, 32, testInputCRC2); - printf("testInputCRC2: [0]->%x \t [1]->%x \t [2]->%x \t [3]->%x\n" - " [4]->%x \t [5]->%x \t [6]->%x \t [7]->%x\n", - testInputCRC2[0], testInputCRC2[1], testInputCRC2[2], testInputCRC2[3], - testInputCRC2[4], testInputCRC2[5], testInputCRC2[6], testInputCRC2[7]); - unsigned int crc41 = crc24c(testInputCRC, 32); - unsigned int crc65 = crc24c(testInputCRC, 56); - printf("crc41: [0]->0x%08x\tcrc65: [0]->0x%08x\n",crc41, crc65); - for (int i=0;i<32;i++) printf("crc41[%d]=%d\tcrc65[%d]=%d\n",i,(crc41>>i)&1,i,(crc65>>i)&1); - - crc = crc24c(testInputCRC, testLength)>>8; - for (int i=0;i<24;i++) printf("[i]=%d\n",(crc>>i)&1); - printf("crc: [0]->0x%08x\n",crc); - //crcbit(testInputCRC, sizeof(test) - 1, poly24c)); - - testInputCRC[testLength>>3] = ((uint8_t*)&crc)[2]; - testInputCRC[1+(testLength>>3)] = ((uint8_t*)&crc)[1]; - testInputCRC[2+(testLength>>3)] = ((uint8_t*)&crc)[0]; - printf("testInputCRC: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", - testInputCRC[0], testInputCRC[1], testInputCRC[2], testInputCRC[3]); - - - //uint32_t trial32 = 0xffffffff; - uint32_t trial32 = 0xf10fffff; - uint8_t a[4]; - //memcpy(a, &trial32, sizeof(trial32)); - *(uint32_t *)a = trial32; - unsigned char trial[4]; - trial[0]=0xff; trial[1]=0xff; trial[2]=0x0f; trial[3]=0xf1; - uint32_t trialcrc = crc24c(trial, 32); - uint32_t trialcrc32 = crc24c((uint8_t *)&trial32, 32); - //uint32_t trialcrc32 = crc24c(a, 32); - printf("crcbit(trial = %x\n", crcbit(trial, 4, poly24c)); - printf("trialcrc = %x\n", trialcrc); - printf("trialcrc32 = %x\n", trialcrc32); - for (int i=0;i<32;i++) printf("trialcrc[%2d]=%d\ttrialcrc32[%2d]=%d\n",i,(trialcrc>>i)&1,i,(trialcrc32>>i)&1); - - - //uint8_t nr_polar_A[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - uint8_t nr_polar_A[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1}; - uint8_t nr_polar_crc[24]; - uint8_t **crc_generator_matrix = crc24c_generator_matrix(32); - nr_matrix_multiplication_uint8_1D_uint8_2D(nr_polar_A, - crc_generator_matrix, - nr_polar_crc, - 32, - 24); - for (uint8_t i = 0; i < 24; i++){ - nr_polar_crc[i] = (nr_polar_crc[i] % 2); - printf("nr_polar_crc[%d]=%d\n",i,nr_polar_crc[i]); - } - return 0; -#endif + if (logFile==NULL) { + fprintf(stderr,"[polartest.c] Problem creating file %s with fopen\n",fileName); + exit(-1); + } #ifdef DEBUG_POLAR_TIMING - for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) { - SNR_lin = pow(10, SNR / 10); - for (itr = 1; itr <= iterations; itr++) { - for (int j=0; j0x%08x \n", testInput[0]); - polar_encoder_timing(testInput, encoderOutput, currentPtr, cpu_freq_GHz, logFile); - } - } - fclose(logFile); - free(testInput); - free(encoderOutput); - free(modulatedInput); - free(channelOutput); - free(estimatedOutput); - return (0); + fprintf(logFile, + ",timeEncoderCRCByte[us],timeEncoderCRCBit[us],timeEncoderInterleaver[us],timeEncoderBitInsertion[us],timeEncoder1[us],timeEncoder2[us],timeEncoderRateMatching[us],timeEncoderByte2Bit[us]\n"); +#else + fprintf(logFile,",SNR,nBitError,blockErrorState,t_encoder[us],t_decoder[us]\n"); #endif + uint8_t testArrayLength = ceil(testLength / 32.0); + uint8_t coderArrayLength = ceil(coderLength / 32.0); + uint32_t testInput[testArrayLength]; //generate randomly + uint32_t encoderOutput[coderArrayLength]; + uint32_t estimatedOutput[testArrayLength]; //decoder output + memset(testInput,0,sizeof(uint32_t) * testArrayLength); + memset(encoderOutput,0,sizeof(uint32_t) * coderArrayLength); + memset(estimatedOutput,0,sizeof(uint32_t) * testArrayLength); + uint8_t encoderOutputByte[coderLength]; + double modulatedInput[coderLength]; //channel input + double channelOutput[coderLength]; //add noise + int16_t channelOutput_int16[coderLength]; + t_nrPolar_params *currentPtr = nr_polar_params(polarMessageType, testLength, aggregation_level); +#ifdef DEBUG_DCI_POLAR_PARAMS + uint32_t dci_pdu[4]; + memset(dci_pdu,0,sizeof(uint32_t)*4); + dci_pdu[0]=0x01189400; + printf("dci_pdu: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", + dci_pdu[0], dci_pdu[1], dci_pdu[2], dci_pdu[3]); + uint32_t encoder_output[54]; + memset(encoder_output,0,sizeof(uint32_t)*54); + uint16_t size=41; + uint16_t rnti=3; + aggregation_level=8; + t_nrPolar_params *currentPtrDCI=nr_polar_params(1, size, aggregation_level); + polar_encoder_dci(dci_pdu, encoder_output, currentPtrDCI, rnti); - // We assume no a priori knowledge available about the payload. - double aPrioriArray[currentPtr->payloadBits]; - for (int i=0; ipayloadBits; i++) aPrioriArray[i] = NAN; + for (int i=0; i<54; i++) + printf("encoder_output: [%2d]->0x%08x \n",i, encoder_output[i]); - for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) { - printf("SNR %f\n",SNR); - SNR_lin = pow(10, SNR/10); - for (itr = 1; itr <= iterations; itr++) { + uint8_t *encoder_outputByte = malloc(sizeof(uint8_t) * currentPtrDCI->encoderLength); + double *channel_output = malloc (sizeof(double) * currentPtrDCI->encoderLength); + uint32_t dci_estimation[4]; + memset(dci_estimation,0,sizeof(uint32_t)*4); + printf("dci_estimation: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", + dci_estimation[0], dci_estimation[1], dci_estimation[2], dci_estimation[3]); + nr_bit2byte_uint32_8(encoder_output, currentPtrDCI->encoderLength, encoder_outputByte); + printf("[polartest] encoder_outputByte: "); - for (int i = 0; i < testArrayLength; i++) { - for (int j = 0; j < (sizeof(testInput[0])*8)-1; j++) { - testInput[i] |= ( ((uint32_t) (rand()%2)) &1); - testInput[i]<<=1; - } - testInput[i] |= ( ((uint32_t) (rand()%2)) &1); - } + for (int i = 0; i < currentPtrDCI->encoderLength; i++) printf("%d-", encoder_outputByte[i]); -#ifdef DEBUG_POLARTEST - printf("testInput: "); - for (int i = 0; i < testArrayLength; i++) printf("[%d]->0x%08x\t",i, testInput[i]); - printf("\n"); + printf("\n"); - printf("testInput[0]: "); - for (int i=0; i<32; i++) printf("[%d]=%d-",i,(testInput[0]>>i)&1); - printf("\n"); - printf("testInput[1]: "); - for (int i=0; i<32; i++) printf("[%d]=%d-",i,(testInput[1]>>i)&1); - printf("\n"); + for(int i=0; iencoderLength; i++) { + if (encoder_outputByte[i] == 0) { + channel_output[i]=1/sqrt(2); + } else { + channel_output[i]=(-1)/sqrt(2); + } + } + + decoderState = polar_decoder_dci(channel_output, + dci_estimation, + currentPtrDCI, + NR_POLAR_DECODER_LISTSIZE, + NR_POLAR_DECODER_PATH_METRIC_APPROXIMATION, + rnti); + printf("dci_estimation: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", + dci_estimation[0], dci_estimation[1], dci_estimation[2], dci_estimation[3]); + free(encoder_outputByte); + free(channel_output); + return 0; #endif +#ifdef DEBUG_CRC + uint32_t crc; + unsigned int poly24c = 0xb2b11700; + uint32_t testInputCRC[4]; + testInputCRC[0]=0x00291880; + //testInputCRC[0]=0x01189400; + testInputCRC[1]=0x00000000; + testInputCRC[2]=0x00000000; + testInputCRC[3]=0x00000000; + uint32_t testInputcrc=0x01189400; + uint32_t testInputcrc2=0x00291880; + uint8_t testInputCRC2[8]; + nr_crc_bit2bit_uint32_8(testInputCRC, 32, testInputCRC2); + printf("testInputCRC2: [0]->%x \t [1]->%x \t [2]->%x \t [3]->%x\n" + " [4]->%x \t [5]->%x \t [6]->%x \t [7]->%x\n", + testInputCRC2[0], testInputCRC2[1], testInputCRC2[2], testInputCRC2[3], + testInputCRC2[4], testInputCRC2[5], testInputCRC2[6], testInputCRC2[7]); + unsigned int crc41 = crc24c(testInputCRC, 32); + unsigned int crc65 = crc24c(testInputCRC, 56); + printf("crc41: [0]->0x%08x\tcrc65: [0]->0x%08x\n",crc41, crc65); - int len_mod64=currentPtr->payloadBits&63; - ((uint64_t*)testInput)[currentPtr->payloadBits/64]&=((((uint64_t)1)<>i)&1,i,(crc65>>i)&1); -#ifdef DEBUG_POLARTEST - printf("testInput: "); - for (int i = 0; i < testArrayLength; i++) printf("[%d]->0x%08x\t",i, testInput[i]); - printf("\n"); + crc = crc24c(testInputCRC, testLength)>>8; - printf("testInput[0]: "); - for (int i=0; i<32; i++) printf("[%d]=%d-",i,(testInput[0]>>i)&1); - printf("\n"); - printf("testInput[1]: "); - for (int i=0; i<32; i++) printf("[%d]=%d-",i,(testInput[1]>>i)&1); - printf("\n"); + for (int i=0; i<24; i++) printf("[i]=%d\n",(crc>>i)&1); + + printf("crc: [0]->0x%08x\n",crc); + //crcbit(testInputCRC, sizeof(test) - 1, poly24c)); + testInputCRC[testLength>>3] = ((uint8_t *)&crc)[2]; + testInputCRC[1+(testLength>>3)] = ((uint8_t *)&crc)[1]; + testInputCRC[2+(testLength>>3)] = ((uint8_t *)&crc)[0]; + printf("testInputCRC: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", + testInputCRC[0], testInputCRC[1], testInputCRC[2], testInputCRC[3]); + //uint32_t trial32 = 0xffffffff; + uint32_t trial32 = 0xf10fffff; + uint8_t a[4]; + //memcpy(a, &trial32, sizeof(trial32)); + *(uint32_t *)a = trial32; + unsigned char trial[4]; + trial[0]=0xff; + trial[1]=0xff; + trial[2]=0x0f; + trial[3]=0xf1; + uint32_t trialcrc = crc24c(trial, 32); + uint32_t trialcrc32 = crc24c((uint8_t *)&trial32, 32); + //uint32_t trialcrc32 = crc24c(a, 32); + printf("crcbit(trial = %x\n", crcbit(trial, 4, poly24c)); + printf("trialcrc = %x\n", trialcrc); + printf("trialcrc32 = %x\n", trialcrc32); + + for (int i=0; i<32; i++) printf("trialcrc[%2d]=%d\ttrialcrc32[%2d]=%d\n",i,(trialcrc>>i)&1,i,(trialcrc32>>i)&1); + + //uint8_t nr_polar_A[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; + uint8_t nr_polar_A[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1}; + uint8_t nr_polar_crc[24]; + uint8_t **crc_generator_matrix = crc24c_generator_matrix(32); + nr_matrix_multiplication_uint8_1D_uint8_2D(nr_polar_A, + crc_generator_matrix, + nr_polar_crc, + 32, + 24); + + for (uint8_t i = 0; i < 24; i++) { + nr_polar_crc[i] = (nr_polar_crc[i] % 2); + printf("nr_polar_crc[%d]=%d\n",i,nr_polar_crc[i]); + } + + return 0; #endif +#ifdef DEBUG_POLAR_TIMING + for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) { + SNR_lin = pow(10, SNR / 10); - if (matlabDebug == 1){ - memset(testInput,0,sizeof(uint32_t) * testArrayLength); - /*testInput[0] |= ((uint32_t)1 << 31); testInput[0] |= ((uint32_t)1 << 28); testInput[0] |= ((uint32_t)1 << 26); - testInput[0] |= ((uint32_t)1 << 25); testInput[0] |= ((uint32_t)1 << 22); testInput[0] |= ((uint32_t)1 << 21); - testInput[0] |= ((uint32_t)1 << 19); testInput[0] |= ((uint32_t)1 << 17); testInput[0] |= ((uint32_t)1 << 15); - testInput[0] |= ((uint32_t)1 << 14); testInput[0] |= ((uint32_t)1 << 12); testInput[0] |= ((uint32_t)1 << 10); - testInput[0] |= ((uint32_t)1 << 8); testInput[0] |= ((uint32_t)1 << 5); testInput[0] |= ((uint32_t)1 << 3); - testInput[0] |= ((uint32_t)1 << 2); testInput[0] |= ((uint32_t)1 << 1);*/ + for (itr = 1; itr <= iterations; itr++) { + for (int j=0; j0x%08x \n", testInput[0]); + polar_encoder_timing(testInput, encoderOutput, currentPtr, cpu_freq_GHz, logFile); + } + } + fclose(logFile); + free(testInput); + free(encoderOutput); + free(modulatedInput); + free(channelOutput); + free(estimatedOutput); + return (0); +#endif + // We assume no a priori knowledge available about the payload. + double aPrioriArray[currentPtr->payloadBits]; - testInput[0] |= ((uint32_t)1 << 30); testInput[0] |= ((uint32_t)1 << 29); testInput[0] |= ((uint32_t)1 << 28); - testInput[0] |= ((uint32_t)1 << 26); testInput[0] |= ((uint32_t)1 << 23); testInput[0] |= ((uint32_t)1 << 21); - testInput[0] |= ((uint32_t)1 << 19); testInput[0] |= ((uint32_t)1 << 17); testInput[0] |= ((uint32_t)1 << 16); - testInput[0] |= ((uint32_t)1 << 14); testInput[0] |= ((uint32_t)1 << 12); testInput[0] |= ((uint32_t)1 << 10); - testInput[0] |= ((uint32_t)1 << 9); testInput[0] |= ((uint32_t)1 << 6); testInput[0] |= ((uint32_t)1 << 5); - testInput[0] |= ((uint32_t)1 << 3); testInput[0] |= ((uint32_t)1); + for (int i=0; ipayloadBits; i++) aPrioriArray[i] = NAN; + for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) { + printf("SNR %f\n",SNR); + SNR_lin = pow(10, SNR/10); - /*printf("testInput (a_31,..., a_0): "); - for (int i=31; i>=0; i--) printf("%d-",(testInput[0]>>i)&1); //a_31, a_30, ..., a_0 - printf("testInput = 0x%llx\n", testInput[0]); - printf("\n");*/ + for (itr = 1; itr <= iterations; itr++) { + for (int i = 0; i < testArrayLength; i++) { + for (int j = 0; j < (sizeof(testInput[0])*8)-1; j++) { + testInput[i] |= ( ((uint32_t) (rand()%2)) &1); + testInput[i]<<=1; + } + testInput[i] |= ( ((uint32_t) (rand()%2)) &1); + } - /*for (int i=0;i<32;i++){ - memset(testInput,0,sizeof(uint32_t) * testArrayLength); - testInput[0] |= ((uint32_t)1 << i); - int crc = crc24c(testInput,32); - printf("[i=%d]testInput = 0x%08lx, crc = 0x%lx\n", i,testInput[0], crc); - } - memset(testInput,0,sizeof(uint32_t) * testArrayLength); - int crc = crc24c(testInput,32); - printf("testInput = 0x%08lx, crc = 0x%lx\n", testInput[0], crc);*/ + /*printf("testInput: [0]->0x%08x\n", testInput[0]); + for (int i=0; i<32; i++) + printf("%d\n",(testInput[0]>>i)&1);*/ + int len_mod64=currentPtr->payloadBits&63; + ((uint64_t *)testInput)[currentPtr->payloadBits/64]&=((((uint64_t)1)<0x%08x\n", encoderOutput[0]); + printf("encoderOutput: [1]->0x%08x\n", encoderOutput[1]);*/ + //Bit-to-byte: + nr_bit2byte_uint32_8(encoderOutput, coderLength, encoderOutputByte); - for (int i=0; i0x%08x\n", encoderOutput[0]); - printf("encoderOutput: [1]->0x%08x\n", encoderOutput[1]);*/ + if (decoder_int16==1) { + if (channelOutput[i] > 15) channelOutput_int16[i] = 127; + else if (channelOutput[i] < -16) channelOutput_int16[i] = -128; + else channelOutput_int16[i] = (int16_t) (8*channelOutput[i]); + } + } - //Bit-to-byte: - nr_bit2byte_uint32_8(encoderOutput, coderLength, encoderOutputByte); + start_meas(&timeDecoder); - //BPSK modulation - for(int i=0; i0x%08x\n", testInput[0]); + printf("estimatedOutput: [0]->0x%08x\n", estimatedOutput[0]);*/ - channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0,1.0) * (1/sqrt(SNR_lin))); - //channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0,1.0) * (1/sqrt(2*SNR_lin))); + //calculate errors + if (decoderState!=0) { + blockErrorState=-1; + nBitError=-1; + } else { + for (int j = 0; j < currentPtr->payloadBits; j++) { + if (((estimatedOutput[0]>>j) & 1) != ((testInput[0]>>j) & 1)) nBitError++; - if (decoder_int16==1) { - if (channelOutput[i] > 15) - channelOutput_int16[i] = 127; - else if (channelOutput[i] < -16) - channelOutput_int16[i] = -128; - else - channelOutput_int16[i] = (int16_t) (8*channelOutput[i]); - } - } + // printf("bit %d: %d => %d\n",j,(testInput[0]>>j)&1,(estimatedOutput[0]>>j)&1); + } - start_meas(&timeDecoder); - /*decoderState = polar_decoder(channelOutput, - estimatedOutput, - currentPtr, - NR_POLAR_DECODER_LISTSIZE, - aPrioriArray, - NR_POLAR_DECODER_PATH_METRIC_APPROXIMATION);*/ - if (decoder_int16 == 1) - decoderState = polar_decoder_int16(channelOutput_int16, - (uint64_t*) estimatedOutput, - currentPtr); - else - decoderState = polar_decoder_aPriori(channelOutput, - estimatedOutput, currentPtr, - NR_POLAR_DECODER_LISTSIZE, - NR_POLAR_DECODER_PATH_METRIC_APPROXIMATION, - aPrioriArray); - - stop_meas(&timeDecoder); - /*printf("testInput: [0]->0x%08x\n", testInput[0]); - printf("estimatedOutput: [0]->0x%08x\n", estimatedOutput[0]);*/ + if (nBitError>0) { + blockErrorState=1; + // printf("Error: Input %x, Output %x\n",testInput[0],estimatedOutput[0]); + } + } - //calculate errors - if (decoderState!=0) { - blockErrorState=-1; - nBitError=-1; - } else { - for (int j = 0; j < currentPtr->payloadBits; j++) { - if (((estimatedOutput[0]>>j) & 1) != ((testInput[0]>>j) & 1)) - nBitError++; - // printf("bit %d: %d => %d\n",j,(testInput[0]>>j)&1,(estimatedOutput[0]>>j)&1); - } - if (nBitError>0) { - blockErrorState=1; - //printf("Error: Input %x, Output %x\n",testInput[0],estimatedOutput[0]); - } - } + //Iteration times are in microseconds. + timeEncoderCumulative+=(timeEncoder.diff/(cpu_freq_GHz*1000.0)); + timeDecoderCumulative+=(timeDecoder.diff/(cpu_freq_GHz*1000.0)); + fprintf(logFile,",%f,%d,%d,%f,%f\n", SNR, nBitError, blockErrorState, + (timeEncoder.diff/(cpu_freq_GHz*1000.0)), (timeDecoder.diff/(cpu_freq_GHz*1000.0))); - //Iteration times are in microseconds. - fprintf(logFile,",%f,%d,%d,%f,%f\n", SNR, nBitError, blockErrorState, - (timeEncoder.diff/(cpu_freq_GHz*1000.0)), (timeDecoder.diff/(cpu_freq_GHz*1000.0))); + if (nBitError<0) { + blockErrorCumulative++; + bitErrorCumulative+=testLength; + } else { + blockErrorCumulative+=blockErrorState; + bitErrorCumulative+=nBitError; + } - if (nBitError<0) { - blockErrorCumulative++; - bitErrorCumulative+=testLength; - } else { - blockErrorCumulative+=blockErrorState; - bitErrorCumulative+=nBitError; - } + decoderState=0; + nBitError=0; + blockErrorState=0; + } - decoderState=0; - nBitError=0; - blockErrorState=0; + //Calculate error statistics for the SNR. + printf("[ListSize=%d, Appr=%d] SNR=%+8.3f, BLER=%9.6f, BER=%12.9f, t_Encoder=%9.3fus, t_Decoder=%9.3fus\n", + decoderListSize, pathMetricAppr, SNR, ((double)blockErrorCumulative/iterations), + ((double)bitErrorCumulative / (iterations*testLength)), + (double)timeEncoder.diff/timeEncoder.trials/(cpu_freq_GHz*1000.0),(double)timeDecoder.diff/timeDecoder.trials/(cpu_freq_GHz*1000.0)); + //(timeEncoderCumulative/iterations),timeDecoderCumulative/iterations); - } - //Calculate error statistics for the SNR. - printf("[ListSize=%d, Appr=%d] SNR=%+8.3f, BLER=%9.6f, BER=%12.9f, t_Encoder=%12.6fus, t_Decoder=%12.6fus\n", - decoderListSize, pathMetricAppr, SNR, ((double)blockErrorCumulative/iterations), - ((double)bitErrorCumulative / (iterations*testLength)), - (double)timeEncoder.diff/timeEncoder.trials/(cpu_freq_GHz*1000.0), - (double)timeDecoder.diff/timeDecoder.trials/(cpu_freq_GHz*1000.0)); + if (blockErrorCumulative==0 && bitErrorCumulative==0) + break; - if (blockErrorCumulative==0 && bitErrorCumulative==0) - break; + blockErrorCumulative = 0; + bitErrorCumulative = 0; + timeEncoderCumulative = 0; + timeDecoderCumulative = 0; + } - blockErrorCumulative = 0; bitErrorCumulative = 0; - } - - print_meas(&timeEncoder,"polar_encoder",NULL,NULL); - print_meas(&timeDecoder,"polar_decoder",NULL,NULL); - - fclose(logFile); - return (0); + print_meas(&timeEncoder,"polar_encoder",NULL,NULL); + print_meas(&timeDecoder,"polar_decoder",NULL,NULL); + fclose(logFile); + return (0); } diff --git a/openair1/PHY/CODING/TESTBENCH/smallblocktest.c b/openair1/PHY/CODING/TESTBENCH/smallblocktest.c index 7ffa3900a6..0b863d2cbf 100644 --- a/openair1/PHY/CODING/TESTBENCH/smallblocktest.c +++ b/openair1/PHY/CODING/TESTBENCH/smallblocktest.c @@ -99,7 +99,6 @@ int main(int argc, char *argv[]) { testInput<<=1; } testInput |= ( ((uint32_t) (rand()%2)) &1); - //Encoding start_meas(&timeEncoder); encoderOutput = encodeSmallBlock((uint16_t*)&testInput, (uint8_t)messageLength); diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 1b23de1cb9..2277826a66 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -455,7 +455,7 @@ int32_t nr_segmentation(unsigned char *input_buffer, unsigned int B, unsigned int *C, unsigned int *K, - unsigned int *Zout, + unsigned int *Zout, unsigned int *F); uint32_t nr_compute_tbs(uint8_t mcs, diff --git a/openair1/PHY/CODING/crc_byte.c b/openair1/PHY/CODING/crc_byte.c index 67190698e1..bf8d63fb39 100644 --- a/openair1/PHY/CODING/crc_byte.c +++ b/openair1/PHY/CODING/crc_byte.c @@ -32,6 +32,7 @@ #include "coding_defs.h" +#include "assertions.h" /*ref 36-212 v8.6.0 , pp 8-9 */ /* the highest degree is set by default */ @@ -275,7 +276,7 @@ int check_crc(uint8_t* decoded_bytes, uint32_t n, uint32_t F, uint8_t crc_type) break; default: - crc_len=3; + AssertFatal(1,"Invalid crc_type \n"); } for (int i=0; i>24; break; + + default: + AssertFatal(1,"Invalid crc_type \n"); } if (crc == oldcrc) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index bbcd34c368..af84205481 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -54,7 +54,7 @@ int32_t nrLDPC_decoder(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* t_nrLDPC_lut lut; t_nrLDPC_lut* p_lut = &lut; - printf("p_procBuf->cnProcBuf = %p\n", p_procBuf->cnProcBuf); + //printf("p_procBuf->cnProcBuf = %p\n", p_procBuf->cnProcBuf); // Initialize decoder core(s) with correct LUTs numLLR = nrLDPC_init(p_decParams, p_lut); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c index b754bda1f9..5cf044309e 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c @@ -39,760 +39,1101 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" #include "assertions.h" -int8_t polar_decoder(double *input, - uint8_t *out, - t_nrPolar_paramsPtr polarParams, - uint8_t listSize, - uint8_t pathMetricAppr) -{ - //Assumes no a priori knowledge. +int8_t polar_decoder( + double *input, + uint8_t *out, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr) { + //Assumes no a priori knowledge. + uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **bitUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + uint8_t **llrUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **crcChecksum = nr_alloc_uint8_2D_array(polarParams->crcParityBits, 2*listSize); + double *pathMetric = malloc(sizeof(double)*(2*listSize)); + uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True - uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); - uint8_t **bitUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True - uint8_t **llrUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True - double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); - uint8_t **crcChecksum = nr_alloc_uint8_2D_array(polarParams->crcParityBits, 2*listSize); - double *pathMetric = malloc(sizeof(double)*(2*listSize)); - uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True + for (int i=0; i<(2*listSize); i++) { + pathMetric[i] = 0; + crcState[i]=1; + } - for (int i=0; i<(2*listSize); i++) { - pathMetric[i] = 0; - crcState[i]=1; - } - for (int i=0; iN; i++) { - llrUpdated[i][polarParams->n]=1; - bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); - } + for (int i=0; iN; i++) { + llrUpdated[i][polarParams->n]=1; + bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); + } - uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3 - uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2 - for (int i = 0; i < polarParams->K; i++){ - extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); - tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); - } + uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3 + uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2 - for (int i=0; ipayloadBits; i++) { - for (int j=0; jcrcParityBits; j++) { - tempECGM[i][j]=polarParams->crc_generator_matrix[i][j]; - } - } - for (int i=polarParams->payloadBits; iK; i++) { - for (int j=0; jcrcParityBits; j++) { - if( (i-polarParams->payloadBits) == j ){ - tempECGM[i][j]=1; - } else { - tempECGM[i][j]=0; - } - } - } + for (int i = 0; i < polarParams->K; i++) { + extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + } - for (int i=0; iK; i++) { - for (int j=0; jcrcParityBits; j++) { - extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; - } - } + for (int i=0; ipayloadBits; i++) { + for (int j=0; jcrcParityBits; j++) { + tempECGM[i][j]=polarParams->crc_generator_matrix[i][j]; + } + } - //The index of the last 1-valued bit that appears in each column. - uint16_t last1ind[polarParams->crcParityBits]; - for (int j=0; jcrcParityBits; j++) { - for (int i=0; iK; i++) { - if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; - } - } + for (int i=polarParams->payloadBits; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + if( (i-polarParams->payloadBits) == j ) { + tempECGM[i][j]=1; + } else { + tempECGM[i][j]=0; + } + } + } - double *d_tilde = malloc(sizeof(double) * polarParams->N); - nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; + for (int i=0; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; + } + } + //The index of the last 1-valued bit that appears in each column. + uint16_t last1ind[polarParams->crcParityBits]; - /* - * SCL polar decoder. - */ + for (int j=0; jcrcParityBits; j++) { + for (int i=0; iK; i++) { + if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; + } + } - uint32_t nonFrozenBit=0; - uint8_t currentListSize=1; - uint8_t decoderIterationCheck=0; - int16_t checkCrcBits=-1; - uint8_t listIndex[2*listSize], copyIndex; + double *d_tilde = malloc(sizeof(double) * polarParams->N); + nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - for (uint16_t currentBit=0; currentBitN; currentBit++){ - updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); - if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. - updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 - } else { //Information or CRC bit. - updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); + for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; - for (int i = 0; i < currentListSize; i++) { - for (int j = 0; j < polarParams->N; j++) { - for (int k = 0; k < (polarParams->n+1); k++) { - bit[j][k][i+currentListSize]=bit[j][k][i]; - llr[j][k][i+currentListSize]=llr[j][k][i];}}} - for (int i = 0; i < currentListSize; i++) { - bit[currentBit][0][i]=0; - crcState[i+currentListSize]=crcState[i]; - } - for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; - bitUpdated[currentBit][0]=1; - updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); - currentListSize*=2; + /* + * SCL polar decoder. + */ + uint32_t nonFrozenBit=0; + uint8_t currentListSize=1; + uint8_t decoderIterationCheck=0; + int16_t checkCrcBits=-1; + uint8_t listIndex[2*listSize], copyIndex; - //Keep only the best "listSize" number of entries. - if (currentListSize > listSize) { - for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + for (uint16_t currentBit=0; currentBitN; currentBit++) { + updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); - //sort listIndex[listSize, ..., 2*listSize-1] in descending order. - uint8_t swaps, tempInd; - for (uint8_t i = 0; i < listSize; i++) { - swaps = 0; - for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { - if (listIndex[j+1] > listIndex[j]) { - tempInd = listIndex[j]; - listIndex[j] = listIndex[j + 1]; - listIndex[j + 1] = tempInd; - swaps++; - } - } - if (swaps == 0) - break; - } + if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 + } else { //Information or CRC bit. + updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); - //First, backup the best "listSize" number of entries. - for (int k=(listSize-1); k>0; k--) { - for (int i=0; iN; i++) { - for (int j=0; j<(polarParams->n+1); j++) { - bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; - llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; - } - } - } - for (int k=(listSize-1); k>0; k--) { - for (int i = 0; i < polarParams->crcParityBits; i++) { - crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; - } - } - for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; + for (int i = 0; i < currentListSize; i++) { + for (int j = 0; j < polarParams->N; j++) { + for (int k = 0; k < (polarParams->n+1); k++) { + bit[j][k][i+currentListSize]=bit[j][k][i]; + llr[j][k][i+currentListSize]=llr[j][k][i]; + } + } + } - //Copy the best "listSize" number of entries to the first indices. - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - for (int i = 0; i < polarParams->N; i++) { - for (int j = 0; j < (polarParams->n + 1); j++) { - bit[i][j][k] = bit[i][j][copyIndex]; - llr[i][j][k] = llr[i][j][copyIndex]; - } - } - } - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - for (int i = 0; i < polarParams->crcParityBits; i++) { - crcChecksum[i][k]=crcChecksum[i][copyIndex]; - } - } - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - crcState[k]=crcState[copyIndex]; - } - currentListSize = listSize; - } + for (int i = 0; i < currentListSize; i++) { + bit[currentBit][0][i]=0; + crcState[i+currentListSize]=crcState[i]; + } + for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; - for (int i=0; icrcParityBits; i++) { - if (last1ind[i]==nonFrozenBit) { - checkCrcBits=i; - break; - } - } + bitUpdated[currentBit][0]=1; + updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); + currentListSize*=2; - if ( checkCrcBits > (-1) ) { - for (uint8_t i = 0; i < currentListSize; i++) { - if (crcChecksum[checkCrcBits][i]==1) { - crcState[i]=0; //0=False, 1=True - } - } - } + //Keep only the best "listSize" number of entries. + if (currentListSize > listSize) { + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; - if (decoderIterationCheck==0) { - //perror("[SCL polar decoder] All list entries have failed the CRC checks."); - free(d_tilde); - free(pathMetric); - free(crcState); - nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); - nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); - nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); - return(-1); - } + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + //sort listIndex[listSize, ..., 2*listSize-1] in descending order. + uint8_t swaps, tempInd; - nonFrozenBit++; - decoderIterationCheck=0; - checkCrcBits=-1; - } - } + for (uint8_t i = 0; i < listSize; i++) { + swaps = 0; - for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { + if (listIndex[j+1] > listIndex[j]) { + tempInd = listIndex[j]; + listIndex[j] = listIndex[j + 1]; + listIndex[j + 1] = tempInd; + swaps++; + } + } - for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { - if ( crcState[listIndex[i]] == 1 ) { - for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + if (swaps == 0) + break; + } - //Extract the information bits (û to ĉ) - nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + //First, backup the best "listSize" number of entries. + for (int k=(listSize-1); k>0; k--) { + for (int i=0; iN; i++) { + for (int j=0; j<(polarParams->n+1); j++) { + bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; + llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; + } + } + } - //Deinterleaving (ĉ to b) - nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); + for (int k=(listSize-1); k>0; k--) { + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; + } + } - - //Remove the CRC (â) - for (int j = 0; j < polarParams->payloadBits; j++) polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; + for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; - break; - } - } + //Copy the best "listSize" number of entries to the first indices. + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } - free(d_tilde); - free(pathMetric); - free(crcState); - nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); - nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); - nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); - nr_free_uint8_2D_array(extended_crc_generator_matrix, polarParams->K); - nr_free_uint8_2D_array(tempECGM, polarParams->K); + for (int i = 0; i < polarParams->N; i++) { + for (int j = 0; j < (polarParams->n + 1); j++) { + bit[i][j][k] = bit[i][j][copyIndex]; + llr[i][j][k] = llr[i][j][copyIndex]; + } + } + } - /* - * Return bits. - */ - //nr_byte2bit_uint8_32(polarParams->nr_polar_A, polarParams->payloadBits, out); - return(0); + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][k]=crcChecksum[i][copyIndex]; + } + } + + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + crcState[k]=crcState[copyIndex]; + } + + currentListSize = listSize; + } + + for (int i=0; icrcParityBits; i++) { + if (last1ind[i]==nonFrozenBit) { + checkCrcBits=i; + break; + } + } + + if ( checkCrcBits > (-1) ) { + for (uint8_t i = 0; i < currentListSize; i++) { + if (crcChecksum[checkCrcBits][i]==1) { + crcState[i]=0; //0=False, 1=True + } + } + } + + for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; + + if (decoderIterationCheck==0) { + //perror("[SCL polar decoder] All list entries have failed the CRC checks."); + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + return(-1); + } + + nonFrozenBit++; + decoderIterationCheck=0; + checkCrcBits=-1; + } + } + + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + + for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { + if ( crcState[listIndex[i]] == 1 ) { + for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + + //Extract the information bits (û to ĉ) + nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + //Deinterleaving (ĉ to b) + nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); + + //Remove the CRC (â) + for (int j = 0; j < polarParams->payloadBits; j++) polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; + + break; + } + } + + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + nr_free_uint8_2D_array(extended_crc_generator_matrix, polarParams->K); + nr_free_uint8_2D_array(tempECGM, polarParams->K); + /* + * Return bits. + */ + //nr_byte2bit_uint8_32_t(polarParams->nr_polar_A, polarParams->payloadBits, out); + return(0); } int8_t polar_decoder_aPriori(double *input, - uint32_t *out, - t_nrPolar_paramsPtr polarParams, - uint8_t listSize, - uint8_t pathMetricAppr, - double *aPrioriPayload) -{ - uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); - uint8_t **bitUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True - uint8_t **llrUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True - double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); - uint8_t **crcChecksum = nr_alloc_uint8_2D_array(polarParams->crcParityBits, 2*listSize); - double *pathMetric = malloc(sizeof(double)*(2*listSize)); - uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True + uint32_t *out, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr, + double *aPrioriPayload) { + uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **bitUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + uint8_t **llrUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **crcChecksum = nr_alloc_uint8_2D_array(polarParams->crcParityBits, 2*listSize); + double *pathMetric = malloc(sizeof(double)*(2*listSize)); + uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True - for (int i=0; i<(2*listSize); i++) { - pathMetric[i] = 0; - crcState[i]=1; - } - for (int i=0; iN; i++) { - llrUpdated[i][polarParams->n]=1; - bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); - } + for (int i=0; i<(2*listSize); i++) { + pathMetric[i] = 0; + crcState[i]=1; + } - uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3 - uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2 - for (int i = 0; i < polarParams->K; i++){ - extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); - tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); - } + for (int i=0; iN; i++) { + llrUpdated[i][polarParams->n]=1; + bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); + } - for (int i=0; ipayloadBits; i++) { - for (int j=0; jcrcParityBits; j++) { - tempECGM[i][j]=polarParams->crc_generator_matrix[i][j]; - } - } - for (int i=polarParams->payloadBits; iK; i++) { - for (int j=0; jcrcParityBits; j++) { - if( (i-polarParams->payloadBits) == j ){ - tempECGM[i][j]=1; - } else { - tempECGM[i][j]=0; - } - } - } + uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3 + uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2 - for (int i=0; iK; i++) { - for (int j=0; jcrcParityBits; j++) { - extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; - } - } + for (int i = 0; i < polarParams->K; i++) { + extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + } - //The index of the last 1-valued bit that appears in each column. - uint16_t last1ind[polarParams->crcParityBits]; - for (int j=0; jcrcParityBits; j++) { - for (int i=0; iK; i++) { - if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; - } - } + for (int i=0; ipayloadBits; i++) { + for (int j=0; jcrcParityBits; j++) { + tempECGM[i][j]=polarParams->crc_generator_matrix[i][j]; + } + } - double *d_tilde = malloc(sizeof(double) * polarParams->N); - nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; + for (int i=polarParams->payloadBits; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + if( (i-polarParams->payloadBits) == j ) { + tempECGM[i][j]=1; + } else { + tempECGM[i][j]=0; + } + } + } + + for (int i=0; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; + } + } + + //The index of the last 1-valued bit that appears in each column. + uint16_t last1ind[polarParams->crcParityBits]; + + for (int j=0; jcrcParityBits; j++) { + for (int i=0; iK; i++) { + if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; + } + } + + double *d_tilde = malloc(sizeof(double) * polarParams->N); + nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); + + for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; + + /* + * SCL polar decoder. + */ + uint32_t nonFrozenBit=0; + uint8_t currentListSize=1; + uint8_t decoderIterationCheck=0; + int16_t checkCrcBits=-1; + uint8_t listIndex[2*listSize], copyIndex; + + for (uint16_t currentBit=0; currentBitN; currentBit++) { + updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); + + if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 + } else { //Information or CRC bit. + if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && + (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 0) ) { + //Information bit with known value of "0". + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); + bitUpdated[currentBit][0]=1; //0=False, 1=True + } else if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && + (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 1) ) { + //Information bit with known value of "1". + updatePathMetric(pathMetric, llr, currentListSize, 1, currentBit, pathMetricAppr); + + for (uint8_t i=0; icrcParityBits); + } else { + updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); + + for (int i = 0; i < currentListSize; i++) { + for (int j = 0; j < polarParams->N; j++) { + for (int k = 0; k < (polarParams->n+1); k++) { + bit[j][k][i+currentListSize]=bit[j][k][i]; + llr[j][k][i+currentListSize]=llr[j][k][i]; + } + } + } + + for (int i = 0; i < currentListSize; i++) { + bit[currentBit][0][i]=0; + crcState[i+currentListSize]=crcState[i]; + } + + for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; + + bitUpdated[currentBit][0]=1; + updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); + currentListSize*=2; + + //Keep only the best "listSize" number of entries. + if (currentListSize > listSize) { + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + //sort listIndex[listSize, ..., 2*listSize-1] in descending order. + uint8_t swaps, tempInd; + + for (uint8_t i = 0; i < listSize; i++) { + swaps = 0; + + for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { + if (listIndex[j+1] > listIndex[j]) { + tempInd = listIndex[j]; + listIndex[j] = listIndex[j + 1]; + listIndex[j + 1] = tempInd; + swaps++; + } + } + + if (swaps == 0) + break; + } + + //First, backup the best "listSize" number of entries. + for (int k=(listSize-1); k>0; k--) { + for (int i=0; iN; i++) { + for (int j=0; j<(polarParams->n+1); j++) { + bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; + llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; + } + } + } + + for (int k=(listSize-1); k>0; k--) { + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; + } + } + + for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; + + //Copy the best "listSize" number of entries to the first indices. + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + for (int i = 0; i < polarParams->N; i++) { + for (int j = 0; j < (polarParams->n + 1); j++) { + bit[i][j][k] = bit[i][j][copyIndex]; + llr[i][j][k] = llr[i][j][copyIndex]; + } + } + } + + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][k]=crcChecksum[i][copyIndex]; + } + } + + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + crcState[k]=crcState[copyIndex]; + } + + currentListSize = listSize; + } + } + + for (int i=0; icrcParityBits; i++) { + if (last1ind[i]==nonFrozenBit) { + checkCrcBits=i; + break; + } + } + + if ( checkCrcBits > (-1) ) { + for (uint8_t i = 0; i < currentListSize; i++) { + if (crcChecksum[checkCrcBits][i]==1) { + crcState[i]=0; //0=False, 1=True + } + } + } + + for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; + + if (decoderIterationCheck==0) { + //perror("[SCL polar decoder] All list entries have failed the CRC checks."); + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + return(-1); + } + + nonFrozenBit++; + decoderIterationCheck=0; + checkCrcBits=-1; + } + } + + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + + for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { + if ( crcState[listIndex[i]] == 1 ) { + for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + + //Extract the information bits (û to ĉ) + nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + //Deinterleaving (ĉ to b) + nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); + + //Remove the CRC (â) + for (int j = 0; j < polarParams->payloadBits; j++) + polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; + + break; + } + } + + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + nr_free_uint8_2D_array(extended_crc_generator_matrix, polarParams->K); + nr_free_uint8_2D_array(tempECGM, polarParams->K); + /* + * Return bits. + */ + nr_byte2bit_uint8_32(polarParams->nr_polar_A, polarParams->payloadBits, out); + return(0); +} - /* - * SCL polar decoder. - */ - uint32_t nonFrozenBit=0; - uint8_t currentListSize=1; - uint8_t decoderIterationCheck=0; - int16_t checkCrcBits=-1; - uint8_t listIndex[2*listSize], copyIndex; +int8_t polar_decoder_aPriori_timing(double *input, + uint32_t *out, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr, + double *aPrioriPayload, + double cpuFreqGHz, + FILE *logFile) { + uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **bitUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + uint8_t **llrUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **crcChecksum = nr_alloc_uint8_2D_array(polarParams->crcParityBits, 2*listSize); + double *pathMetric = malloc(sizeof(double)*(2*listSize)); + uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True - for (uint16_t currentBit=0; currentBitN; currentBit++){ + for (int i=0; i<(2*listSize); i++) { + pathMetric[i] = 0; + crcState[i]=1; + } - updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); - if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. - updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 - } else { //Information or CRC bit. - if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && - (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 0) ) { - //Information bit with known value of "0". - updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); - bitUpdated[currentBit][0]=1; //0=False, 1=True - } else if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && - (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 1) ) { - //Information bit with known value of "1". - updatePathMetric(pathMetric, llr, currentListSize, 1, currentBit, pathMetricAppr); - for (uint8_t i=0; icrcParityBits); - } else { - updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); + for (int i=0; iN; i++) { + llrUpdated[i][polarParams->n]=1; + bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); + } - for (int i = 0; i < currentListSize; i++) { - for (int j = 0; j < polarParams->N; j++) { - for (int k = 0; k < (polarParams->n+1); k++) { - bit[j][k][i+currentListSize]=bit[j][k][i]; - llr[j][k][i+currentListSize]=llr[j][k][i];}}} - for (int i = 0; i < currentListSize; i++) { - bit[currentBit][0][i]=0; - crcState[i+currentListSize]=crcState[i]; - } - for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; - bitUpdated[currentBit][0]=1; - updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); - currentListSize*=2; + uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3 + uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2 - //Keep only the best "listSize" number of entries. - if (currentListSize > listSize) { - for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + for (int i = 0; i < polarParams->K; i++) { + extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + } - //sort listIndex[listSize, ..., 2*listSize-1] in descending order. - uint8_t swaps, tempInd; - for (uint8_t i = 0; i < listSize; i++) { - swaps = 0; - for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { - if (listIndex[j+1] > listIndex[j]) { - tempInd = listIndex[j]; - listIndex[j] = listIndex[j + 1]; - listIndex[j + 1] = tempInd; - swaps++; - } - } - if (swaps == 0) - break; - } + for (int i=0; ipayloadBits; i++) { + for (int j=0; jcrcParityBits; j++) { + tempECGM[i][j]=polarParams->crc_generator_matrix[i][j]; + } + } - //First, backup the best "listSize" number of entries. - for (int k=(listSize-1); k>0; k--) { - for (int i=0; iN; i++) { - for (int j=0; j<(polarParams->n+1); j++) { - bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; - llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; - } - } - } - for (int k=(listSize-1); k>0; k--) { - for (int i = 0; i < polarParams->crcParityBits; i++) { - crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; - } - } - for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; + for (int i=polarParams->payloadBits; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + if( (i-polarParams->payloadBits) == j ) { + tempECGM[i][j]=1; + } else { + tempECGM[i][j]=0; + } + } + } - //Copy the best "listSize" number of entries to the first indices. - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - for (int i = 0; i < polarParams->N; i++) { - for (int j = 0; j < (polarParams->n + 1); j++) { - bit[i][j][k] = bit[i][j][copyIndex]; - llr[i][j][k] = llr[i][j][copyIndex]; - } - } - } - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - for (int i = 0; i < polarParams->crcParityBits; i++) { - crcChecksum[i][k]=crcChecksum[i][copyIndex]; - } - } - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - crcState[k]=crcState[copyIndex]; - } - currentListSize = listSize; - } - } + for (int i=0; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; + } + } - for (int i=0; icrcParityBits; i++) { - if (last1ind[i]==nonFrozenBit) { - checkCrcBits=i; - break; - } - } + //The index of the last 1-valued bit that appears in each column. + uint16_t last1ind[polarParams->crcParityBits]; - if ( checkCrcBits > (-1) ) { - for (uint8_t i = 0; i < currentListSize; i++) { - if (crcChecksum[checkCrcBits][i]==1) { - crcState[i]=0; //0=False, 1=True - } - } - } + for (int j=0; jcrcParityBits; j++) { + for (int i=0; iK; i++) { + if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; + } + } - for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; - if (decoderIterationCheck==0) { - //perror("[SCL polar decoder] All list entries have failed the CRC checks."); - free(d_tilde); - free(pathMetric); - free(crcState); - nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); - nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); - nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); - return(-1); - } + double *d_tilde = malloc(sizeof(double) * polarParams->N); + nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - nonFrozenBit++; - decoderIterationCheck=0; - checkCrcBits=-1; - } - } + for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; - for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + /* + * SCL polar decoder. + */ + uint32_t nonFrozenBit=0; + uint8_t currentListSize=1; + uint8_t decoderIterationCheck=0; + int16_t checkCrcBits=-1; + uint8_t listIndex[2*listSize], copyIndex; - for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { - if ( crcState[listIndex[i]] == 1 ) { - for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + for (uint16_t currentBit=0; currentBitN; currentBit++) { + updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); - //Extract the information bits (û to ĉ) - nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 + } else { //Information or CRC bit. + if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && + (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 0) ) { + //Information bit with known value of "0". + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); + bitUpdated[currentBit][0]=1; //0=False, 1=True + } else if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && + (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 1) ) { + //Information bit with known value of "1". + updatePathMetric(pathMetric, llr, currentListSize, 1, currentBit, pathMetricAppr); - //Deinterleaving (ĉ to b) - nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); + for (uint8_t i=0; ipayloadBits; j++) - polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; - break; - } - } + bitUpdated[currentBit][0]=1; + updateCrcChecksum(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); + } else { + updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); - free(d_tilde); - free(pathMetric); - free(crcState); - nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); - nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); - nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); - nr_free_uint8_2D_array(extended_crc_generator_matrix, polarParams->K); - nr_free_uint8_2D_array(tempECGM, polarParams->K); + for (int i = 0; i < currentListSize; i++) { + for (int j = 0; j < polarParams->N; j++) { + for (int k = 0; k < (polarParams->n+1); k++) { + bit[j][k][i+currentListSize]=bit[j][k][i]; + llr[j][k][i+currentListSize]=llr[j][k][i]; + } + } + } - /* - * Return bits. - */ - nr_byte2bit_uint8_32(polarParams->nr_polar_A, polarParams->payloadBits, out); - return(0); + for (int i = 0; i < currentListSize; i++) { + bit[currentBit][0][i]=0; + crcState[i+currentListSize]=crcState[i]; + } + + for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; + + bitUpdated[currentBit][0]=1; + updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); + currentListSize*=2; + + //Keep only the best "listSize" number of entries. + if (currentListSize > listSize) { + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + //sort listIndex[listSize, ..., 2*listSize-1] in descending order. + uint8_t swaps, tempInd; + + for (uint8_t i = 0; i < listSize; i++) { + swaps = 0; + + for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { + if (listIndex[j+1] > listIndex[j]) { + tempInd = listIndex[j]; + listIndex[j] = listIndex[j + 1]; + listIndex[j + 1] = tempInd; + swaps++; + } + } + + if (swaps == 0) + break; + } + + //First, backup the best "listSize" number of entries. + for (int k=(listSize-1); k>0; k--) { + for (int i=0; iN; i++) { + for (int j=0; j<(polarParams->n+1); j++) { + bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; + llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; + } + } + } + + for (int k=(listSize-1); k>0; k--) { + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; + } + } + + for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; + + //Copy the best "listSize" number of entries to the first indices. + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + for (int i = 0; i < polarParams->N; i++) { + for (int j = 0; j < (polarParams->n + 1); j++) { + bit[i][j][k] = bit[i][j][copyIndex]; + llr[i][j][k] = llr[i][j][copyIndex]; + } + } + } + + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][k]=crcChecksum[i][copyIndex]; + } + } + + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + crcState[k]=crcState[copyIndex]; + } + + currentListSize = listSize; + } + } + + for (int i=0; icrcParityBits; i++) { + if (last1ind[i]==nonFrozenBit) { + checkCrcBits=i; + break; + } + } + + if ( checkCrcBits > (-1) ) { + for (uint8_t i = 0; i < currentListSize; i++) { + if (crcChecksum[checkCrcBits][i]==1) { + crcState[i]=0; //0=False, 1=True + } + } + } + + for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; + + if (decoderIterationCheck==0) { + //perror("[SCL polar decoder] All list entries have failed the CRC checks."); + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + return(-1); + } + + nonFrozenBit++; + decoderIterationCheck=0; + checkCrcBits=-1; + } + } + + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + + for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { + if ( crcState[listIndex[i]] == 1 ) { + for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + + //Extract the information bits (û to ĉ) + nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + //Deinterleaving (ĉ to b) + nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); + + //Remove the CRC (â) + for (int j = 0; j < polarParams->payloadBits; j++) polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; + + break; + } + } + + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + nr_free_uint8_2D_array(extended_crc_generator_matrix, polarParams->K); + nr_free_uint8_2D_array(tempECGM, polarParams->K); + /* + * Return bits. + */ + nr_byte2bit_uint8_32(polarParams->nr_polar_A, polarParams->payloadBits, out); + return(0); } int8_t polar_decoder_dci(double *input, - uint32_t *out, - t_nrPolar_paramsPtr polarParams, - uint8_t listSize, - uint8_t pathMetricAppr, - uint16_t n_RNTI) -{ - uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); - uint8_t **bitUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True - uint8_t **llrUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True - double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); - uint8_t **crcChecksum = nr_alloc_uint8_2D_array(polarParams->crcParityBits, 2*listSize); - double *pathMetric = malloc(sizeof(double)*(2*listSize)); - uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True - uint8_t extended_crc_scrambling_pattern[polarParams->crcParityBits]; + uint32_t *out, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr, + uint16_t n_RNTI) { + uint8_t ***bit = nr_alloc_uint8_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **bitUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + uint8_t **llrUpdated = nr_alloc_uint8_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **crcChecksum = nr_alloc_uint8_2D_array(polarParams->crcParityBits, 2*listSize); + double *pathMetric = malloc(sizeof(double)*(2*listSize)); + uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True + uint8_t extended_crc_scrambling_pattern[polarParams->crcParityBits]; - for (int i=0; i<(2*listSize); i++) { - pathMetric[i] = 0; - crcState[i]=1; - } - for (int i=0; iN; i++) { - llrUpdated[i][polarParams->n]=1; - bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); - } + for (int i=0; i<(2*listSize); i++) { + pathMetric[i] = 0; + crcState[i]=1; + } - uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3: K-by-P - uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2: K-by-P - for (int i = 0; i < polarParams->K; i++){ - extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); - tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); - } + for (int i=0; iN; i++) { + llrUpdated[i][polarParams->n]=1; + bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); + } - for (int i=0; ipayloadBits; i++) { - for (int j=0; jcrcParityBits; j++) { - tempECGM[i][j]=polarParams->crc_generator_matrix[i+polarParams->crcParityBits][j]; - } - } - for (int i=polarParams->payloadBits; iK; i++) { - for (int j=0; jcrcParityBits; j++) { - if( (i-polarParams->payloadBits) == j ){ - tempECGM[i][j]=1; - } else { - tempECGM[i][j]=0; - } - } - } + uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3: K-by-P + uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2: K-by-P - for (int i=0; iK; i++) { - for (int j=0; jcrcParityBits; j++) { - extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; - } - } + for (int i = 0; i < polarParams->K; i++) { + extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + } - //The index of the last 1-valued bit that appears in each column. - uint16_t last1ind[polarParams->crcParityBits]; - for (int j=0; jcrcParityBits; j++) { - for (int i=0; iK; i++) { - if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; - } - } + for (int i=0; ipayloadBits; i++) { + for (int j=0; jcrcParityBits; j++) { + tempECGM[i][j]=polarParams->crc_generator_matrix[i+polarParams->crcParityBits][j]; + } + } - for (int i=0;i<8;i++) extended_crc_scrambling_pattern[i]=0; - for (int i=8; icrcParityBits; i++) { - extended_crc_scrambling_pattern[i]=(n_RNTI>>(23-i))&1; - } + for (int i=polarParams->payloadBits; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + if( (i-polarParams->payloadBits) == j ) { + tempECGM[i][j]=1; + } else { + tempECGM[i][j]=0; + } + } + } - double *d_tilde = malloc(sizeof(double) * polarParams->N); - nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; + for (int i=0; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; + } + } - /* - * SCL polar decoder. - */ + //The index of the last 1-valued bit that appears in each column. + uint16_t last1ind[polarParams->crcParityBits]; - for (int i=0; icrcParityBits; i++) { - for (int j=0; jcrcParityBits; j++) crcChecksum[i][0]=crcChecksum[i][0]+polarParams->crc_generator_matrix[j][i]; - crcChecksum[i][0]=(crcChecksum[i][0]%2); - } + for (int j=0; jcrcParityBits; j++) { + for (int i=0; iK; i++) { + if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; + } + } - uint32_t nonFrozenBit=0; - uint8_t currentListSize=1; - uint8_t decoderIterationCheck=0; - int16_t checkCrcBits=-1; - uint8_t listIndex[2*listSize], copyIndex; + for (int i=0; i<8; i++) extended_crc_scrambling_pattern[i]=0; - for (uint16_t currentBit=0; currentBitN; currentBit++){ - updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); - if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. - updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 - } else { //Information or CRC bit. - updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); + for (int i=8; icrcParityBits; i++) { + extended_crc_scrambling_pattern[i]=(n_RNTI>>(23-i))&1; + } - for (int i = 0; i < currentListSize; i++) { - for (int j = 0; j < polarParams->N; j++) { - for (int k = 0; k < (polarParams->n+1); k++) { - bit[j][k][i+currentListSize]=bit[j][k][i]; - llr[j][k][i+currentListSize]=llr[j][k][i];}}} - for (int i = 0; i < currentListSize; i++) { - bit[currentBit][0][i]=0; - crcState[i+currentListSize]=crcState[i]; - } - for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; - bitUpdated[currentBit][0]=1; - updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); - currentListSize*=2; + double *d_tilde = malloc(sizeof(double) * polarParams->N); + nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - //Keep only the best "listSize" number of entries. - if (currentListSize > listSize) { - for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; - //sort listIndex[listSize, ..., 2*listSize-1] in descending order. - uint8_t swaps, tempInd; - for (uint8_t i = 0; i < listSize; i++) { - swaps = 0; - for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { - if (listIndex[j+1] > listIndex[j]) { - tempInd = listIndex[j]; - listIndex[j] = listIndex[j + 1]; - listIndex[j + 1] = tempInd; - swaps++; - } - } - if (swaps == 0) - break; - } + /* + * SCL polar decoder. + */ - //First, backup the best "listSize" number of entries. - for (int k=(listSize-1); k>0; k--) { - for (int i=0; iN; i++) { - for (int j=0; j<(polarParams->n+1); j++) { - bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; - llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; - } - } - } - for (int k=(listSize-1); k>0; k--) { - for (int i = 0; i < polarParams->crcParityBits; i++) { - crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; - } - } - for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; + for (int i=0; icrcParityBits; i++) { + for (int j=0; jcrcParityBits; j++) crcChecksum[i][0]=crcChecksum[i][0]+polarParams->crc_generator_matrix[j][i]; - //Copy the best "listSize" number of entries to the first indices. - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - for (int i = 0; i < polarParams->N; i++) { - for (int j = 0; j < (polarParams->n + 1); j++) { - bit[i][j][k] = bit[i][j][copyIndex]; - llr[i][j][k] = llr[i][j][copyIndex]; - } - } - } - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - for (int i = 0; i < polarParams->crcParityBits; i++) { - crcChecksum[i][k]=crcChecksum[i][copyIndex]; - } - } - for (int k = 0; k < listSize; k++) { - if (k > listIndex[k]) { - copyIndex = listIndex[(2*listSize-1)-k]; - } else { //Use the backup. - copyIndex = listIndex[k]; - } - crcState[k]=crcState[copyIndex]; - } - currentListSize = listSize; - } + crcChecksum[i][0]=(crcChecksum[i][0]%2); + } - for (int i=0; icrcParityBits; i++) { - if (last1ind[i]==nonFrozenBit) { - checkCrcBits=i; - break; - } - } + uint32_t nonFrozenBit=0; + uint8_t currentListSize=1; + uint8_t decoderIterationCheck=0; + int16_t checkCrcBits=-1; + uint8_t listIndex[2*listSize], copyIndex; - if ( checkCrcBits > (-1) ) { - for (uint8_t i = 0; i < currentListSize; i++) { - if (crcChecksum[checkCrcBits][i]!=extended_crc_scrambling_pattern[checkCrcBits]) { - crcState[i]=0; //0=False, 1=True - } - } - } + for (uint16_t currentBit=0; currentBitN; currentBit++) { + updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); - for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; - if (decoderIterationCheck==0) { - //perror("[SCL polar decoder] All list entries have failed the CRC checks."); - free(d_tilde); - free(pathMetric); - free(crcState); - nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); - nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); - nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); - return(-1); - } + if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 + } else { //Information or CRC bit. + updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); - nonFrozenBit++; - decoderIterationCheck=0; - checkCrcBits=-1; - } - } + for (int i = 0; i < currentListSize; i++) { + for (int j = 0; j < polarParams->N; j++) { + for (int k = 0; k < (polarParams->n+1); k++) { + bit[j][k][i+currentListSize]=bit[j][k][i]; + llr[j][k][i+currentListSize]=llr[j][k][i]; + } + } + } - for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + for (int i = 0; i < currentListSize; i++) { + bit[currentBit][0][i]=0; + crcState[i+currentListSize]=crcState[i]; + } - for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { - if ( crcState[listIndex[i]] == 1 ) { - for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; - //Extract the information bits (û to ĉ) - nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + bitUpdated[currentBit][0]=1; + updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); + currentListSize*=2; - //Deinterleaving (ĉ to b) - nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); + //Keep only the best "listSize" number of entries. + if (currentListSize > listSize) { + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; - //Remove the CRC (â) - for (int j = 0; j < polarParams->payloadBits; j++) polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + //sort listIndex[listSize, ..., 2*listSize-1] in descending order. + uint8_t swaps, tempInd; - break; - } - } + for (uint8_t i = 0; i < listSize; i++) { + swaps = 0; - free(d_tilde); - free(pathMetric); - free(crcState); - nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); - nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); - nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); - nr_free_uint8_2D_array(extended_crc_generator_matrix, polarParams->K); - nr_free_uint8_2D_array(tempECGM, polarParams->K); + for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { + if (listIndex[j+1] > listIndex[j]) { + tempInd = listIndex[j]; + listIndex[j] = listIndex[j + 1]; + listIndex[j + 1] = tempInd; + swaps++; + } + } - /* - * Return bits. - */ - nr_byte2bit_uint8_32(polarParams->nr_polar_A, polarParams->payloadBits, out); - return(0); + if (swaps == 0) + break; + } + + //First, backup the best "listSize" number of entries. + for (int k=(listSize-1); k>0; k--) { + for (int i=0; iN; i++) { + for (int j=0; j<(polarParams->n+1); j++) { + bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; + llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; + } + } + } + + for (int k=(listSize-1); k>0; k--) { + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; + } + } + + for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; + + //Copy the best "listSize" number of entries to the first indices. + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + for (int i = 0; i < polarParams->N; i++) { + for (int j = 0; j < (polarParams->n + 1); j++) { + bit[i][j][k] = bit[i][j][copyIndex]; + llr[i][j][k] = llr[i][j][copyIndex]; + } + } + } + + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][k]=crcChecksum[i][copyIndex]; + } + } + + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + + crcState[k]=crcState[copyIndex]; + } + + currentListSize = listSize; + } + + for (int i=0; icrcParityBits; i++) { + if (last1ind[i]==nonFrozenBit) { + checkCrcBits=i; + break; + } + } + + if ( checkCrcBits > (-1) ) { + for (uint8_t i = 0; i < currentListSize; i++) { + if (crcChecksum[checkCrcBits][i]!=extended_crc_scrambling_pattern[checkCrcBits]) { + crcState[i]=0; //0=False, 1=True + } + } + } + + for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; + + if (decoderIterationCheck==0) { + //perror("[SCL polar decoder] All list entries have failed the CRC checks."); + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + return(-1); + } + + nonFrozenBit++; + decoderIterationCheck=0; + checkCrcBits=-1; + } + } + + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + + for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { + if ( crcState[listIndex[i]] == 1 ) { + for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + + //Extract the information bits (û to ĉ) + nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); + //Deinterleaving (ĉ to b) + nr_polar_deinterleaver(polarParams->nr_polar_CPrime, polarParams->nr_polar_B, polarParams->interleaving_pattern, polarParams->K); + + //Remove the CRC (â) + for (int j = 0; j < polarParams->payloadBits; j++) polarParams->nr_polar_A[j]=polarParams->nr_polar_B[j]; + + break; + } + } + + free(d_tilde); + free(pathMetric); + free(crcState); + nr_free_uint8_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_2D_array(crcChecksum, polarParams->crcParityBits); + nr_free_uint8_2D_array(extended_crc_generator_matrix, polarParams->K); + nr_free_uint8_2D_array(tempECGM, polarParams->K); + /* + * Return bits. + */ + nr_byte2bit_uint8_32(polarParams->nr_polar_A, polarParams->payloadBits, out); + return(0); } void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) { - AssertFatal(polarParams->K > 32, "K = %d < 33, is not supported yet\n",polarParams->K); AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n",polarParams->K); - int bit_i,ip,ipmod64; - int numbytes = polarParams->K>>3; int residue = polarParams->K&7; int numbits; + if (residue>0) numbytes++; - for (int byte=0;byteK>>3)) numbits=8; else numbits=residue; - for (int i=0;iK - 1 - polarParams->interleaving_pattern[(8*byte)+i]; #if 0 @@ -800,53 +1141,54 @@ void init_polar_deinterleaver_table(t_nrPolar_params *polarParams) { #endif ipmod64 = ip&63; AssertFatal(ip<128,"ip = %d\n",ip); - for (int val=0;val<256;val++) { - bit_i=(val>>i)&1; - if (ip<64) polarParams->B_tab0[byte][val] |= (((uint64_t)bit_i)<B_tab1[byte][val] |= (((uint64_t)bit_i)<>i)&1; + + if (ip<64) polarParams->B_tab0[byte][val] |= (((uint64_t)bit_i)<B_tab1[byte][val] |= (((uint64_t)bit_i)<N];// = malloc(sizeof(double) * polarParams->N); - nr_polar_rate_matching_int16(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - for (int i=0;iN;i++) { - if (d_tilde[i]<-128) d_tilde[i]=-128; - else if (d_tilde[i]>127) d_tilde[i]=127; + + for (int i=0; iN; i++) { + if (d_tilde[i]<-128) d_tilde[i]=-128; + else if (d_tilde[i]>127) d_tilde[i]=128; } - memcpy((void*)&polarParams->tree.root->alpha[0],(void*)&d_tilde[0],sizeof(int16_t)*polarParams->N); - - generic_polar_decoder(polarParams, polarParams->tree.root); - + memcpy((void *)&polarParams->tree.root->alpha[0],(void *)&d_tilde[0],sizeof(int16_t)*polarParams->N); + generic_polar_decoder(polarParams,polarParams->tree.root); //Extract the information bits (û to ĉ) - uint64_t Cprime[4]={0,0,0,0}; - uint64_t B[4]={0,0,0,0}; - for (int i=0;iK;i++) Cprime[i>>6] = Cprime[i>>6] | ((uint64_t)polarParams->nr_polar_U[polarParams->Q_I_N[i]])<<(i&63); + uint64_t Cprime[4]= {0,0,0,0}; + uint64_t B[4]= {0,0,0,0}; + + for (int i=0; iK; i++) Cprime[i>>6] = Cprime[i>>6] | ((uint64_t)polarParams->nr_polar_U[polarParams->Q_I_N[i]])<<(i&63); //Deinterleaving (ĉ to b) - uint8_t *Cprimebyte = (uint8_t*)Cprime; + uint8_t *Cprimebyte = (uint8_t *)Cprime; + if (polarParams->K<65) { B[0] = polarParams->B_tab0[0][Cprimebyte[0]] | - polarParams->B_tab0[1][Cprimebyte[1]] | - polarParams->B_tab0[2][Cprimebyte[2]] | - polarParams->B_tab0[3][Cprimebyte[3]] | - polarParams->B_tab0[4][Cprimebyte[4]] | - polarParams->B_tab0[5][Cprimebyte[5]] | - polarParams->B_tab0[6][Cprimebyte[6]] | - polarParams->B_tab0[7][Cprimebyte[7]]; - } - else if (polarParams->K<129) { + polarParams->B_tab0[1][Cprimebyte[1]] | + polarParams->B_tab0[2][Cprimebyte[2]] | + polarParams->B_tab0[3][Cprimebyte[3]] | + polarParams->B_tab0[4][Cprimebyte[4]] | + polarParams->B_tab0[5][Cprimebyte[5]] | + polarParams->B_tab0[6][Cprimebyte[6]] | + polarParams->B_tab0[7][Cprimebyte[7]]; + } else if (polarParams->K<129) { int len = polarParams->K/8; + if ((polarParams->K&7) > 0) len++; - for (int k=0;kB_tab0[k][Cprimebyte[k]]; B[1] |= polarParams->B_tab1[k][Cprimebyte[k]]; } @@ -858,41 +1200,38 @@ uint32_t polar_decoder_int16(int16_t *input, uint64_t rxcrc=B[0]&((1<>crclen); uint8_t A32_flip[4]; uint32_t Aprime= (uint32_t)(Ar<<(32-len)); - A32_flip[0]=((uint8_t*)&Aprime)[3]; - A32_flip[1]=((uint8_t*)&Aprime)[2]; - A32_flip[2]=((uint8_t*)&Aprime)[1]; - A32_flip[3]=((uint8_t*)&Aprime)[0]; + A32_flip[0]=((uint8_t *)&Aprime)[3]; + A32_flip[1]=((uint8_t *)&Aprime)[2]; + A32_flip[2]=((uint8_t *)&Aprime)[1]; + A32_flip[3]=((uint8_t *)&Aprime)[0]; crc = (uint64_t)(crc24c(A32_flip,len)>>8); - } - else if (len<=64) { + } else if (len<=64) { Ar = (B[0]>>crclen) | (B[1]<<(64-crclen));; uint8_t A64_flip[8]; uint64_t Aprime= (uint32_t)(Ar<<(64-len)); - A64_flip[0]=((uint8_t*)&Aprime)[7]; - A64_flip[1]=((uint8_t*)&Aprime)[6]; - A64_flip[2]=((uint8_t*)&Aprime)[5]; - A64_flip[3]=((uint8_t*)&Aprime)[4]; - A64_flip[4]=((uint8_t*)&Aprime)[3]; - A64_flip[5]=((uint8_t*)&Aprime)[2]; - A64_flip[6]=((uint8_t*)&Aprime)[1]; - A64_flip[7]=((uint8_t*)&Aprime)[0]; + A64_flip[0]=((uint8_t *)&Aprime)[7]; + A64_flip[1]=((uint8_t *)&Aprime)[6]; + A64_flip[2]=((uint8_t *)&Aprime)[5]; + A64_flip[3]=((uint8_t *)&Aprime)[4]; + A64_flip[4]=((uint8_t *)&Aprime)[3]; + A64_flip[5]=((uint8_t *)&Aprime)[2]; + A64_flip[6]=((uint8_t *)&Aprime)[1]; + A64_flip[7]=((uint8_t *)&Aprime)[0]; crc = (uint64_t)(crc24c(A64_flip,len)>>8); } #if 0 printf("A %llx B %llx|%llx Cprime %llx|%llx (crc %x,rxcrc %llx %d)\n", - Ar, - B[1],B[0],Cprime[1],Cprime[0],crc, - rxcrc,polarParams->payloadBits); + Ar, + B[1],B[0],Cprime[1],Cprime[0],crc, + rxcrc,polarParams->payloadBits); #endif - out[0]=Ar; - return(crc^rxcrc); } diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c index 9f8fac24c5..38f78bc47b 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c @@ -184,14 +184,7 @@ void updateCrcChecksum2(uint8_t **crcChecksum, } } -void build_decoder_tree(t_nrPolar_params *polarParams) -{ - polarParams->tree.num_nodes=0; - polarParams->tree.root = add_nodes(polarParams->n,0,polarParams); -#ifdef DEBUG_NEW_IMPL - printf("root : left %p, right %p\n",polarParams->tree.root->left,polarParams->tree.root->right); -#endif -} + decoder_node_t *new_decoder_node(int first_leaf_index, int level) { @@ -253,6 +246,15 @@ decoder_node_t *add_nodes(int level, int first_leaf_index, t_nrPolar_params *pol return(new_node); } +void build_decoder_tree(t_nrPolar_params *polarParams) +{ + polarParams->tree.num_nodes=0; + polarParams->tree.root = add_nodes(polarParams->n,0,polarParams); +#ifdef DEBUG_NEW_IMPL + printf("root : left %p, right %p\n",polarParams->tree.root->left,polarParams->tree.root->right); +#endif +} + #if defined(__arm__) || defined(__aarch64__) // translate 1-1 SIMD functions from SSE to NEON #define __m128i int16x8_t @@ -512,17 +514,19 @@ void computeBeta(t_nrPolar_params *pp,decoder_node_t *node) { memcpy((void*)&betav[node->Nv/2],betar,(node->Nv/2)*sizeof(int16_t)); } -void generic_polar_decoder(t_nrPolar_params *polarParams, decoder_node_t *node) { +void generic_polar_decoder(const t_nrPolar_params *pp,decoder_node_t *node) { + // Apply F to left - applyFtoleft(polarParams, node); + applyFtoleft(pp, node); // if left is not a leaf recurse down to the left if (node->left->leaf==0) - generic_polar_decoder(polarParams, node->left); + generic_polar_decoder(pp, node->left); - applyGtoright(polarParams, node); - if (node->right->leaf==0) generic_polar_decoder(polarParams, node->right); + applyGtoright(pp, node); + if (node->right->leaf==0) generic_polar_decoder(pp, node->right); - computeBeta(polarParams, node); + computeBeta(pp, node); } + diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index 76f1c322fe..f6c66e89dc 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -80,7 +80,7 @@ struct nrPolar_params { //messageType: 0=PBCH, 1=DCI, -1=UCI int idx; //idx = (messageType * messageLength * aggregation_prime); struct nrPolar_params *nextPtr; - + uint8_t n_max; uint8_t i_il; uint8_t i_seg; @@ -95,7 +95,7 @@ struct nrPolar_params { uint16_t N; uint8_t n; uint32_t crcBit; - + uint16_t *interleaving_pattern; uint16_t *deinterleaving_pattern; uint16_t *rate_matching_pattern; @@ -106,7 +106,7 @@ struct nrPolar_params { uint8_t *information_bit_pattern; uint16_t *channel_interleaver_pattern; uint32_t crc_polynomial; - + uint8_t **crc_generator_matrix; //G_P uint8_t **G_N; uint64_t **G_N_tab; @@ -116,7 +116,7 @@ struct nrPolar_params { uint64_t cprime_tab1[32][256]; uint64_t B_tab0[32][256]; uint64_t B_tab1[32][256]; - uint32_t* crc256Table; + uint32_t *crc256Table; uint8_t **extended_crc_generator_matrix; //lowercase: bits, Uppercase: Bits stored in bytes //polar_encoder vectors @@ -125,93 +125,82 @@ struct nrPolar_params { uint8_t *nr_polar_APrime; uint8_t *nr_polar_D; uint8_t *nr_polar_E; - + //Polar Coding vectors uint8_t *nr_polar_A; uint8_t *nr_polar_CPrime; uint8_t *nr_polar_B; uint8_t *nr_polar_U; - + decoder_tree_t tree; } __attribute__ ((__packed__)); typedef struct nrPolar_params t_nrPolar_params; -typedef t_nrPolar_params *t_nrPolar_paramsPtr; void polar_encoder(uint32_t *input, - uint32_t *output, - t_nrPolar_paramsPtr polarParams); + uint32_t *output, + t_nrPolar_params *polarParams); void polar_encoder_dci(uint32_t *in, - uint32_t *out, - t_nrPolar_paramsPtr polarParams, - uint16_t n_RNTI); + uint32_t *out, + t_nrPolar_params *polarParams, + uint16_t n_RNTI); -void polar_encoder_fast(uint64_t *Aprime, - uint32_t *out, - int32_t crcmask, - t_nrPolar_paramsPtr polarParams); +void polar_encoder_fast(uint64_t *A, + uint32_t *out, + int32_t crcmask, + t_nrPolar_params *polarParams); int8_t polar_decoder(double *input, - uint8_t *output, - t_nrPolar_paramsPtr polarParams, - uint8_t listSize, - uint8_t pathMetricAppr); - -int8_t polar_decoder_aPriori(double *input, - uint32_t *output, - t_nrPolar_paramsPtr polarParams, - uint8_t listSize, - uint8_t pathMetricAppr, - double *aPrioriPayload); - -int8_t polar_decoder_dci(double *input, - uint32_t *out, - t_nrPolar_paramsPtr polarParams, - uint8_t listSize, - uint8_t pathMetricAppr, - uint16_t n_RNTI); + uint8_t *output, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr); uint32_t polar_decoder_int16(int16_t *input, - uint64_t *out, - t_nrPolar_params *polarParams); + uint64_t *out, + const t_nrPolar_params *polarParams); -void generic_polar_decoder(t_nrPolar_params *, decoder_node_t *); +int8_t polar_decoder_aPriori(double *input, + uint32_t *output, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr, + double *aPrioriPayload); -void applyFtoleft(t_nrPolar_params *polarParams, decoder_node_t *node); +int8_t polar_decoder_aPriori_timing(double *input, + uint32_t *output, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr, + double *aPrioriPayload, + double cpuFreqGHz, + FILE *logFile); -void applyGtoright(t_nrPolar_params *polarParams, decoder_node_t *node); +int8_t polar_decoder_dci(double *input, + uint32_t *out, + t_nrPolar_params *polarParams, + uint8_t listSize, + uint8_t pathMetricAppr, + uint16_t n_RNTI); -void computeBeta(t_nrPolar_params *polarParams, decoder_node_t *node); - - -void build_decoder_tree(t_nrPolar_params *polarParams); - -decoder_node_t *new_decoder_node(int first_leaf_index, int level); - -decoder_node_t *add_nodes(int level, int first_leaf_index, t_nrPolar_params *polarParams); - - -void build_polar_tables(t_nrPolar_paramsPtr polarParams); +void generic_polar_decoder(const t_nrPolar_params *, + decoder_node_t *); +void build_decoder_tree(t_nrPolar_params *pp); +void build_polar_tables(t_nrPolar_params *polarParams); void init_polar_deinterleaver_table(t_nrPolar_params *polarParams); -void nr_polar_init(t_nrPolar_paramsPtr *polarParams, - int8_t messageType, - uint16_t messageLength, - uint8_t aggregation_level); +void nr_polar_print_polarParams(t_nrPolar_params *polarParams); -void nr_polar_print_polarParams(t_nrPolar_paramsPtr polarParams); - -t_nrPolar_paramsPtr nr_polar_params (t_nrPolar_paramsPtr polarParams, - int8_t messageType, - uint16_t messageLength, - uint8_t aggregation_level); +t_nrPolar_params *nr_polar_params ( int8_t messageType, + uint16_t messageLength, + uint8_t aggregation_level); uint16_t nr_polar_aggregation_prime (uint8_t aggregation_level); -uint8_t** nr_polar_kronecker_power_matrices(uint8_t n); +uint8_t **nr_polar_kronecker_power_matrices(uint8_t n); -const uint16_t* nr_polar_sequence_pattern(uint8_t n); +const uint16_t *nr_polar_sequence_pattern(uint8_t n); /*!@fn uint32_t nr_polar_output_length(uint16_t K, uint16_t E, uint8_t n_max) * @brief Computes... @@ -219,143 +208,167 @@ const uint16_t* nr_polar_sequence_pattern(uint8_t n); * @param E * @param n_max */ uint32_t nr_polar_output_length(uint16_t K, - uint16_t E, - uint8_t n_max); + uint16_t E, + uint8_t n_max); void nr_polar_channel_interleaver_pattern(uint16_t *cip, - uint8_t I_BIL, - uint16_t E); + uint8_t I_BIL, + uint16_t E); void nr_polar_rate_matching_pattern(uint16_t *rmp, - uint16_t *J, - const uint8_t *P_i_, - uint16_t K, - uint16_t N, - uint16_t E); + uint16_t *J, + const uint8_t *P_i_, + uint16_t K, + uint16_t N, + uint16_t E); void nr_polar_rate_matching(double *input, - double *output, - uint16_t *rmp, - uint16_t K, - uint16_t N, - uint16_t E); + double *output, + uint16_t *rmp, + uint16_t K, + uint16_t N, + uint16_t E); void nr_polar_rate_matching_int16(int16_t *input, - int16_t *output, - uint16_t *rmp, - uint16_t K, - uint16_t N, - uint16_t E); + int16_t *output, + uint16_t *rmp, + uint16_t K, + uint16_t N, + uint16_t E); -void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_); +void nr_polar_interleaving_pattern(uint16_t K, + uint8_t I_IL, + uint16_t *PI_k_); void nr_polar_info_bit_pattern(uint8_t *ibp, - int16_t *Q_I_N, - int16_t *Q_F_N, - uint16_t *J, - const uint16_t *Q_0_Nminus1, - uint16_t K, - uint16_t N, - uint16_t E, - uint8_t n_PC); + int16_t *Q_I_N, + int16_t *Q_F_N, + uint16_t *J, + const uint16_t *Q_0_Nminus1, + uint16_t K, + uint16_t N, + uint16_t E, + uint8_t n_PC); void nr_polar_info_bit_extraction(uint8_t *input, - uint8_t *output, - uint8_t *pattern, - uint16_t size); + uint8_t *output, + uint8_t *pattern, + uint16_t size); -void nr_bit2byte_uint32_8(uint32_t *in, uint16_t arraySize, uint8_t *out); +void nr_bit2byte_uint32_8(uint32_t *in, + uint16_t arraySize, + uint8_t *out); -void nr_byte2bit_uint8_32(uint8_t *in, uint16_t arraySize, uint32_t *out); +void nr_byte2bit_uint8_32(uint8_t *in, + uint16_t arraySize, + uint32_t *out); -void nr_crc_bit2bit_uint32_8(uint32_t *in, uint16_t arraySize, uint8_t *out); +void nr_crc_bit2bit_uint32_8(uint32_t *in, + uint16_t arraySize, + uint8_t *out); void nr_polar_bit_insertion(uint8_t *input, - uint8_t *output, - uint16_t N, - uint16_t K, - int16_t *Q_I_N, - int16_t *Q_PC_N, - uint8_t n_PC); + uint8_t *output, + uint16_t N, + uint16_t K, + int16_t *Q_I_N, + int16_t *Q_PC_N, + uint8_t n_PC); void nr_matrix_multiplication_uint8_1D_uint8_2D(uint8_t *matrix1, - uint8_t **matrix2, - uint8_t *output, - uint16_t row, - uint16_t col); + uint8_t **matrix2, + uint8_t *output, + uint16_t row, + uint16_t col); -uint8_t ***nr_alloc_uint8_3D_array(uint16_t xlen, uint16_t ylen, uint16_t zlen); +uint8_t ***nr_alloc_uint8_3D_array(uint16_t xlen, + uint16_t ylen, + uint16_t zlen); -uint8_t **nr_alloc_uint8_2D_array(uint16_t xlen, uint16_t ylen); +uint8_t **nr_alloc_uint8_2D_array(uint16_t xlen, + uint16_t ylen); -double ***nr_alloc_double_3D_array(uint16_t xlen, uint16_t ylen, uint16_t zlen); +double ***nr_alloc_double_3D_array(uint16_t xlen, + uint16_t ylen, + uint16_t zlen); -double **nr_alloc_double_2D_array(uint16_t xlen, uint16_t ylen); +double **nr_alloc_double_2D_array(uint16_t xlen, + uint16_t ylen); -void nr_free_double_3D_array(double ***input, uint16_t xlen, uint16_t ylen); +void nr_free_double_3D_array(double ***input, + uint16_t xlen, + uint16_t ylen); -void nr_free_double_2D_array(double **input, uint16_t xlen); +void nr_free_double_2D_array(double **input, + uint16_t xlen); -void nr_free_uint8_3D_array(uint8_t ***input, uint16_t xlen, uint16_t ylen); +void nr_free_uint8_3D_array(uint8_t ***input, + uint16_t xlen, + uint16_t ylen); -void nr_free_uint8_2D_array(uint8_t **input, uint16_t xlen); +void nr_free_uint8_2D_array(uint8_t **input, + uint16_t xlen); -void nr_sort_asc_double_1D_array_ind(double *matrix, uint8_t *ind, uint8_t len); +void nr_sort_asc_double_1D_array_ind(double *matrix, + uint8_t *ind, + uint8_t len); -void nr_sort_asc_int16_1D_array_ind(int32_t *matrix, int *ind, int len); +void nr_sort_asc_int16_1D_array_ind(int32_t *matrix, + int *ind, + int len); void nr_free_double_2D_array(double **input, uint16_t xlen); void updateLLR(double ***llr, - uint8_t **llrU, - uint8_t ***bit, - uint8_t **bitU, - uint8_t listSize, - uint16_t row, - uint16_t col, - uint16_t xlen, - uint8_t ylen, - uint8_t approximation); + uint8_t **llrU, + uint8_t ***bit, + uint8_t **bitU, + uint8_t listSize, + uint16_t row, + uint16_t col, + uint16_t xlen, + uint8_t ylen, + uint8_t approximation); void updateBit(uint8_t ***bit, - uint8_t **bitU, - uint8_t listSize, - uint16_t row, - uint16_t col, - uint16_t xlen, - uint8_t ylen); + uint8_t **bitU, + uint8_t listSize, + uint16_t row, + uint16_t col, + uint16_t xlen, + uint8_t ylen); void updatePathMetric(double *pathMetric, - double ***llr, - uint8_t listSize, - uint8_t bitValue, - uint16_t row, - uint8_t approximation); + double ***llr, + uint8_t listSize, + uint8_t bitValue, + uint16_t row, + uint8_t approximation); void updatePathMetric2(double *pathMetric, - double ***llr, - uint8_t listSize, - uint16_t row, - uint8_t approximation); + double ***llr, + uint8_t listSize, + uint16_t row, + uint8_t approximation); void computeLLR(double ***llr, - uint16_t row, - uint16_t col, - uint8_t i, - uint16_t offset, - uint8_t approximation); + uint16_t row, + uint16_t col, + uint8_t i, + uint16_t offset, + uint8_t approximation); void updateCrcChecksum(uint8_t **crcChecksum, - uint8_t **crcGen, - uint8_t listSize, - uint32_t i2, - uint8_t len); + uint8_t **crcGen, + uint8_t listSize, + uint32_t i2, + uint8_t len); void updateCrcChecksum2(uint8_t **crcChecksum, - uint8_t **crcGen, - uint8_t listSize, - uint32_t i2, - uint8_t len); + uint8_t **crcGen, + uint8_t listSize, + uint32_t i2, + uint8_t len); uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits); @@ -364,14 +377,20 @@ uint8_t **crc11_generator_matrix(uint16_t payloadSizeBits); uint8_t **crc6_generator_matrix(uint16_t payloadSizeBits); //Also nr_polar_rate_matcher -static inline void nr_polar_interleaver(uint8_t *input, uint8_t *output, uint16_t *pattern, uint16_t size){ - for (int i=0; iidx == 0){//PBCH + uint32_t *out, + t_nrPolar_params *polarParams) { + if (1) {//polarParams->idx == 0 || polarParams->idx == 1) { //PBCH or PDCCH /* uint64_t B = (((uint64_t)*in)&((((uint64_t)1)<<32)-1)) | (((uint64_t)crc24c((uint8_t*)in,polarParams->payloadBits)>>8)<payloadBits); -#ifdef DEBUG_POLAR_ENCODER + #ifdef DEBUG_POLAR_ENCODER printf("polar_B %llx (crc %x)\n",B,crc24c((uint8_t*)in,polarParams->payloadBits)>>8); -#endif -nr_bit2byte_uint32_8((uint32_t*)&B, polarParams->K, polarParams->nr_polar_B);*/ - - nr_bit2byte_uint32_8((uint32_t*)in, polarParams->payloadBits, polarParams->nr_polar_A); + #endif + nr_bit2byte_uint32_8_t((uint32_t*)&B, polarParams->K, polarParams->nr_polar_B);*/ + nr_bit2byte_uint32_8((uint32_t *)in, polarParams->payloadBits, polarParams->nr_polar_A); /* * Bytewise operations */ //Calculate CRC. - - nr_matrix_multiplication_uint8_1D_uint8_2D(polarParams->nr_polar_A, - polarParams->crc_generator_matrix, - polarParams->nr_polar_crc, - polarParams->payloadBits, - polarParams->crcParityBits); - for (uint8_t i = 0; i < polarParams->crcParityBits; i++) - polarParams->nr_polar_crc[i] = (polarParams->nr_polar_crc[i] % 2); - - - //Attach CRC to the Transport Block. (a to b) - for (uint16_t i = 0; i < polarParams->payloadBits; i++) - polarParams->nr_polar_B[i] = polarParams->nr_polar_A[i]; - for (uint16_t i = polarParams->payloadBits; i < polarParams->K; i++) - polarParams->nr_polar_B[i]= polarParams->nr_polar_crc[i-(polarParams->payloadBits)]; - + nr_matrix_multiplication_uint8_1D_uint8_2D(polarParams->nr_polar_A, + polarParams->crc_generator_matrix, + polarParams->nr_polar_crc, + polarParams->payloadBits, + polarParams->crcParityBits); + + for (uint8_t i = 0; i < polarParams->crcParityBits; i++) + polarParams->nr_polar_crc[i] = (polarParams->nr_polar_crc[i] % 2); + + //Attach CRC to the Transport Block. (a to b) + for (uint16_t i = 0; i < polarParams->payloadBits; i++) + polarParams->nr_polar_B[i] = polarParams->nr_polar_A[i]; + + for (uint16_t i = polarParams->payloadBits; i < polarParams->K; i++) + polarParams->nr_polar_B[i]= polarParams->nr_polar_crc[i-(polarParams->payloadBits)]; + #ifdef DEBUG_POLAR_ENCODER uint64_t B2=0; - for (int i = 0;iK;i++) B2 = B2 | ((uint64_t)polarParams->nr_polar_B[i] << i); + + for (int i = 0; iK; i++) B2 = B2 | ((uint64_t)polarParams->nr_polar_B[i] << i); + printf("polar_B %llx\n",B2); #endif /* for (int j=0;jcrcParityBits;j++) { - for (int i=0;ipayloadBits;i++) - printf("%1d.%1d+",polarParams->crc_generator_matrix[i][j],polarParams->nr_polar_A[i]); + for (int i=0;ipayloadBits;i++) + printf("%1d.%1d+",polarParams->crc_generator_matrix[i][j],polarParams->nr_polar_A[i]); printf(" => %d\n",polarParams->nr_polar_crc[j]); }*/ - } else { //UCI - } //Interleaving (c to c') nr_polar_interleaver(polarParams->nr_polar_B, - polarParams->nr_polar_CPrime, - polarParams->interleaving_pattern, - polarParams->K); - - -#ifdef DEBUG_POLAR_ENCODER + polarParams->nr_polar_CPrime, + polarParams->interleaving_pattern, + polarParams->K); +#ifdef DEBUG_POLAR_ENCODER uint64_t Cprime=0; - for (int i = 0;iK;i++) { + + for (int i = 0; iK; i++) { Cprime = Cprime | ((uint64_t)polarParams->nr_polar_CPrime[i] << i); + if (polarParams->nr_polar_CPrime[i] == 1) printf("pos %d : %llx\n",i,Cprime); } + printf("polar_Cprime %llx\n",Cprime); -#endif +#endif //Bit insertion (c' to u) nr_polar_bit_insertion(polarParams->nr_polar_CPrime, - polarParams->nr_polar_U, - polarParams->N, - polarParams->K, - polarParams->Q_I_N, - polarParams->Q_PC_N, - polarParams->n_pc); - + polarParams->nr_polar_U, + polarParams->N, + polarParams->K, + polarParams->Q_I_N, + polarParams->Q_PC_N, + polarParams->n_pc); //Encoding (u to d) /* memset(polarParams->nr_polar_U,0,polarParams->N); polarParams->nr_polar_U[247]=1; polarParams->nr_polar_U[253]=1;*/ nr_matrix_multiplication_uint8_1D_uint8_2D(polarParams->nr_polar_U, - polarParams->G_N, - polarParams->nr_polar_D, - polarParams->N, - polarParams->N); + polarParams->G_N, + polarParams->nr_polar_D, + polarParams->N, + polarParams->N); + for (uint16_t i = 0; i < polarParams->N; i++) polarParams->nr_polar_D[i] = (polarParams->nr_polar_D[i] % 2); uint64_t D[8]; - memset((void*)D,0,8*sizeof(int64_t)); + memset((void *)D,0,8*sizeof(int64_t)); #ifdef DEBUG_POLAR_ENCODER - for (int i=0;iN;i++) D[i/64] |= ((uint64_t)polarParams->nr_polar_D[i])<<(i&63); - printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", - D[0],D[1],D[2],D[3],D[4],D[5],D[6],D[7]); -#endif + for (int i=0; iN; i++) D[i/64] |= ((uint64_t)polarParams->nr_polar_D[i])<<(i&63); + + printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", + D[0],D[1],D[2],D[3],D[4],D[5],D[6],D[7]); +#endif //Rate matching //Sub-block interleaving (d to y) and Bit selection (y to e) nr_polar_interleaver(polarParams->nr_polar_D, - polarParams->nr_polar_E, - polarParams->rate_matching_pattern, - polarParams->encoderLength); - + polarParams->nr_polar_E, + polarParams->rate_matching_pattern, + polarParams->encoderLength); /* * Return bits. */ #ifdef DEBUG_POLAR_ENCODER - for (int i=0; i< polarParams->encoderLength;i++) printf("f[%d]=%d\n", i, polarParams->nr_polar_E[i]); -#endif + for (int i=0; i< polarParams->encoderLength; i++) printf("f[%d]=%d\n", i, polarParams->nr_polar_E[i]); + +#endif nr_byte2bit_uint8_32(polarParams->nr_polar_E, polarParams->encoderLength, out); } void polar_encoder_dci(uint32_t *in, - uint32_t *out, - t_nrPolar_paramsPtr polarParams, - uint16_t n_RNTI) -{ + uint32_t *out, + t_nrPolar_params *polarParams, + uint16_t n_RNTI) { #ifdef DEBUG_POLAR_ENCODER_DCI printf("[polar_encoder_dci] in: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", in[0], in[1], in[2], in[3]); #endif - /* * Bytewise operations */ //(a to a') nr_bit2byte_uint32_8(in, polarParams->payloadBits, polarParams->nr_polar_A); + for (int i=0; icrcParityBits; i++) polarParams->nr_polar_APrime[i]=1; + for (int i=0; ipayloadBits; i++) polarParams->nr_polar_APrime[i+(polarParams->crcParityBits)]=polarParams->nr_polar_A[i]; + #ifdef DEBUG_POLAR_ENCODER_DCI printf("[polar_encoder_dci] A: "); + for (int i=0; ipayloadBits; i++) printf("%d-", polarParams->nr_polar_A[i]); + printf("\n"); printf("[polar_encoder_dci] APrime: "); + for (int i=0; iK; i++) printf("%d-", polarParams->nr_polar_APrime[i]); + printf("\n"); printf("[polar_encoder_dci] GP: "); + for (int i=0; icrcParityBits; i++) printf("%d-", polarParams->crc_generator_matrix[0][i]); + printf("\n"); #endif //Calculate CRC. nr_matrix_multiplication_uint8_1D_uint8_2D(polarParams->nr_polar_APrime, - polarParams->crc_generator_matrix, - polarParams->nr_polar_crc, - polarParams->K, - polarParams->crcParityBits); + polarParams->crc_generator_matrix, + polarParams->nr_polar_crc, + polarParams->K, + polarParams->crcParityBits); + for (uint8_t i = 0; i < polarParams->crcParityBits; i++) polarParams->nr_polar_crc[i] = (polarParams->nr_polar_crc[i] % 2); + #ifdef DEBUG_POLAR_ENCODER_DCI printf("[polar_encoder_dci] CRC: "); + for (int i=0; icrcParityBits; i++) printf("%d-", polarParams->nr_polar_crc[i]); + printf("\n"); #endif //Attach CRC to the Transport Block. (a to b) for (uint16_t i = 0; i < polarParams->payloadBits; i++) polarParams->nr_polar_B[i] = polarParams->nr_polar_A[i]; + for (uint16_t i = polarParams->payloadBits; i < polarParams->K; i++) polarParams->nr_polar_B[i]= polarParams->nr_polar_crc[i-(polarParams->payloadBits)]; + //Scrambling (b to c) for (int i=0; i<16; i++) { polarParams->nr_polar_B[polarParams->payloadBits+8+i] = ( polarParams->nr_polar_B[polarParams->payloadBits+8+i] + ((n_RNTI>>(15-i))&1) ) % 2; } - /* //(a to a') - nr_crc_bit2bit_uint32_8(in, polarParams->payloadBits, polarParams->nr_polar_aPrime); - //Parity bits computation (p) - polarParams->crcBit = crc24c(polarParams->nr_polar_aPrime, (polarParams->payloadBits+polarParams->crcParityBits)); - #ifdef DEBUG_POLAR_ENCODER_DCI - printf("[polar_encoder_dci] crc: 0x%08x\n", polarParams->crcBit); - for (int i=0; i<32; i++) - { - printf("%d\n",((polarParams->crcBit)>>i)&1); - } - #endif - //(a to b) - // - // Bytewise operations - // - uint8_t arrayInd = ceil(polarParams->payloadBits / 8.0); - for (int i=0; inr_polar_B[j+(i*8)] = ((polarParams->nr_polar_aPrime[3+i]>>(7-j)) & 1); - } - } - for (int i=0; i<((polarParams->payloadBits)%8); i++) { - polarParams->nr_polar_B[i+(arrayInd-1)*8] = ((polarParams->nr_polar_aPrime[3+(arrayInd-1)]>>(7-i)) & 1); - } - for (int i=0; i<8; i++) { - polarParams->nr_polar_B[polarParams->payloadBits+i] = ((polarParams->crcBit)>>(31-i))&1; - } - //Scrambling (b to c) - for (int i=0; i<16; i++) { - polarParams->nr_polar_B[polarParams->payloadBits+8+i] = - ( (((polarParams->crcBit)>>(23-i))&1) + ((n_RNTI>>(15-i))&1) ) % 2; - }*/ + /* //(a to a') + nr_crc_bit2bit_uint32_8_t(in, polarParams->payloadBits, polarParams->nr_polar_aPrime); + //Parity bits computation (p) + polarParams->crcBit = crc24c(polarParams->nr_polar_aPrime, (polarParams->payloadBits+polarParams->crcParityBits)); + #ifdef DEBUG_POLAR_ENCODER_DCI + printf("[polar_encoder_dci] crc: 0x%08x\n", polarParams->crcBit); + for (int i=0; i<32; i++) + { + printf("%d\n",((polarParams->crcBit)>>i)&1); + } + #endif + //(a to b) + // + // Bytewise operations + // + uint8_t arrayInd = ceil(polarParams->payloadBits / 8.0); + for (int i=0; inr_polar_B[j+(i*8)] = ((polarParams->nr_polar_aPrime[3+i]>>(7-j)) & 1); + } + } + for (int i=0; i<((polarParams->payloadBits)%8); i++) { + polarParams->nr_polar_B[i+(arrayInd-1)*8] = ((polarParams->nr_polar_aPrime[3+(arrayInd-1)]>>(7-i)) & 1); + } + for (int i=0; i<8; i++) { + polarParams->nr_polar_B[polarParams->payloadBits+i] = ((polarParams->crcBit)>>(31-i))&1; + } + //Scrambling (b to c) + for (int i=0; i<16; i++) { + polarParams->nr_polar_B[polarParams->payloadBits+8+i] = + ( (((polarParams->crcBit)>>(23-i))&1) + ((n_RNTI>>(15-i))&1) ) % 2; + }*/ #ifdef DEBUG_POLAR_ENCODER_DCI printf("[polar_encoder_dci] B: "); + for (int i = 0; i < polarParams->K; i++) printf("%d-", polarParams->nr_polar_B[i]); + printf("\n"); #endif - //Interleaving (c to c') nr_polar_interleaver(polarParams->nr_polar_B, - polarParams->nr_polar_CPrime, - polarParams->interleaving_pattern, - polarParams->K); - + polarParams->nr_polar_CPrime, + polarParams->interleaving_pattern, + polarParams->K); //Bit insertion (c' to u) nr_polar_bit_insertion(polarParams->nr_polar_CPrime, - polarParams->nr_polar_U, - polarParams->N, - polarParams->K, - polarParams->Q_I_N, - polarParams->Q_PC_N, - polarParams->n_pc); - + polarParams->nr_polar_U, + polarParams->N, + polarParams->K, + polarParams->Q_I_N, + polarParams->Q_PC_N, + polarParams->n_pc); //Encoding (u to d) nr_matrix_multiplication_uint8_1D_uint8_2D(polarParams->nr_polar_U, - polarParams->G_N, - polarParams->nr_polar_D, - polarParams->N, - polarParams->N); + polarParams->G_N, + polarParams->nr_polar_D, + polarParams->N, + polarParams->N); + for (uint16_t i = 0; i < polarParams->N; i++) polarParams->nr_polar_D[i] = (polarParams->nr_polar_D[i] % 2); //Rate matching //Sub-block interleaving (d to y) and Bit selection (y to e) nr_polar_interleaver(polarParams->nr_polar_D, - polarParams->nr_polar_E, - polarParams->rate_matching_pattern, - polarParams->encoderLength); - + polarParams->nr_polar_E, + polarParams->rate_matching_pattern, + polarParams->encoderLength); /* * Return bits. */ nr_byte2bit_uint8_32(polarParams->nr_polar_E, polarParams->encoderLength, out); #ifdef DEBUG_POLAR_ENCODER_DCI printf("[polar_encoder_dci] E: "); + for (int i = 0; i < polarParams->encoderLength; i++) printf("%d-", polarParams->nr_polar_E[i]); + uint8_t outputInd = ceil(polarParams->encoderLength / 32.0); printf("\n[polar_encoder_dci] out: "); + for (int i = 0; i < outputInd; i++) { printf("[%d]->0x%08x\t", i, out[i]); } + #endif } -static inline void polar_rate_matching(t_nrPolar_paramsPtr polarParams,void *in,void *out) __attribute__((always_inline)); +static inline void polar_rate_matching(t_nrPolar_params *polarParams,void *in,void *out) __attribute__((always_inline)); -static inline void polar_rate_matching(t_nrPolar_paramsPtr polarParams,void *in,void *out) { +static inline void polar_rate_matching(t_nrPolar_params *polarParams,void *in,void *out) { - if (polarParams->groupsize == 8) - for (int i=0;iencoderLength>>3;i++) ((uint8_t*)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]]; - else - for (int i=0;iencoderLength>>4;i++) { - ((uint16_t*)out)[i] = ((uint16_t *)in)[polarParams->rm_tab[i]]; + // handle rate matching with a single 128 bit word using bit shuffling + // can be done with SIMD intrisics if needed + if (polarParams->groupsize < 8) { + AssertFatal(polarParams->encoderLength<=128,"Need to handle groupsize<8 and N>128\n"); + uint128_t *out128=(uint128_t*)out; + uint128_t *in128=(uint128_t*)in; + *out128=0; + uint128_t tmp0; +#ifdef DEBUG_POLAR_ENCODER + uint128_t tmp1; +#endif + for (int i=0; iencoderLength; i++) { +#ifdef DEBUG_POLAR_ENCODER + printf("%u<-%u : %llx.%llx =>",i,polarParams->rate_matching_pattern[i],((uint64_t *)out)[1],((uint64_t *)out)[0]); +#endif + tmp0 = (*in128&(((uint128_t)1)<rate_matching_pattern[i])); + if (tmp0!=0) { + *out128 = *out128 | ((uint128_t)1)<%llx.%llx => %llx.%llx\n", + ((uint64_t *)&tmp0)[1],((uint64_t *)&tmp0)[0], + ((uint64_t *)&tmp1)[1],((uint64_t *)&tmp1)[0], + ((uint64_t *)out)[1],((uint64_t *)out)[0]); +#endif + } + } + + } + // These are based on LUTs for byte and short word groups + else if (polarParams->groupsize == 8) + for (int i=0; iencoderLength>>3; i++) ((uint8_t *)out)[i] = ((uint8_t *)in)[polarParams->rm_tab[i]]; + else // groupsize==16 + for (int i=0; iencoderLength>>4; i++) { + ((uint16_t *)out)[i] = ((uint16_t *)in)[polarParams->rm_tab[i]]; } } -void build_polar_tables(t_nrPolar_paramsPtr polarParams) { - +void build_polar_tables(t_nrPolar_params *polarParams) { // build table b -> c' - AssertFatal(polarParams->K > 32, "K = %d < 33, is not supported yet\n",polarParams->K); AssertFatal(polarParams->K < 129, "K = %d > 64, is not supported yet\n",polarParams->K); - int bit_i,ip; - int numbytes = polarParams->K>>3; int residue = polarParams->K&7; int numbits; + if (residue>0) numbytes++; - for (int byte=0;byteK>>3)) numbits=8; else numbits=residue; - for (int val=0;val<256;val++) { + + for (int val=0; val<256; val++) { polarParams->cprime_tab0[byte][val] = 0; polarParams->cprime_tab1[byte][val] = 0; - for (int i=0;ideinterleaving_pattern[polarParams->K-1-((8*byte)+i)]; - AssertFatal(ip<128,"ip = %d\n",ip); - bit_i=(val>>i)&1; - if (ip<64) polarParams->cprime_tab0[byte][val] |= (((uint64_t)bit_i)<cprime_tab1[byte][val] |= (((uint64_t)bit_i)<<(ip&63)); + + for (int i=0; ideinterleaving_pattern[polarParams->K-1-((8*byte)+i)]; + AssertFatal(ip<128,"ip = %d\n",ip); + bit_i=(val>>i)&1; + + if (ip<64) polarParams->cprime_tab0[byte][val] |= (((uint64_t)bit_i)<cprime_tab1[byte][val] |= (((uint64_t)bit_i)<<(ip&63)); } } } - AssertFatal(polarParams->N==512,"N = %d, not done yet\n",polarParams->N); - + AssertFatal(polarParams->N==512 || polarParams->N==256 || polarParams->N==128,"N = %d, not done yet\n",polarParams->N); // build G bit vectors for information bit positions and convert the bit as bytes tables in nr_polar_kronecker_power_matrices.c to 64 bit packed vectors. // keep only rows of G which correspond to information/crc bits - polarParams->G_N_tab = (uint64_t**)malloc(polarParams->K * sizeof(int64_t*)); + polarParams->G_N_tab = (uint64_t **)malloc(polarParams->K * sizeof(int64_t *)); int k=0; - for (int i=0;iN;i++) { + + for (int i=0; iN; i++) { if (polarParams->information_bit_pattern[i] > 0) { - polarParams->G_N_tab[k] = (uint64_t*)memalign(32,(polarParams->N/64)*sizeof(uint64_t)); - memset((void*)polarParams->G_N_tab[k],0,(polarParams->N/64)*sizeof(uint64_t)); - for (int j=0;jN;j++) - polarParams->G_N_tab[k][j/64] |= ((uint64_t)polarParams->G_N[i][j])<<(j&63); + polarParams->G_N_tab[k] = (uint64_t *)memalign(32,(polarParams->N/64)*sizeof(uint64_t)); + memset((void *)polarParams->G_N_tab[k],0,(polarParams->N/64)*sizeof(uint64_t)); + + for (int j=0; jN; j++) + polarParams->G_N_tab[k][j/64] |= ((uint64_t)polarParams->G_N[i][j])<<(j&63); + #ifdef DEBUG_POLAR_ENCODER printf("Bit %d Selecting row %d of G : ",k,i); - for (int j=0;jN;j+=4) printf("%1x",polarParams->G_N[i][j]+(polarParams->G_N[i][j+1]*2)+(polarParams->G_N[i][j+2]*4)+(polarParams->G_N[i][j+3]*8)); + + for (int j=0; jN; j+=4) printf("%1x",polarParams->G_N[i][j]+(polarParams->G_N[i][j+1]*2)+(polarParams->G_N[i][j+2]*4)+(polarParams->G_N[i][j+3]*8)); + printf("\n"); #endif k++; @@ -352,63 +403,73 @@ void build_polar_tables(t_nrPolar_paramsPtr polarParams) { int iplast=polarParams->rate_matching_pattern[0]; int ccnt=0; int groupcnt=0; +#ifdef DEBUG_POLAR_ENCODER int firstingroup_out=0; int firstingroup_in=iplast; +#endif int mingroupsize = 1024; + // compute minimum group size of rate-matching pattern for (int outpos=1; outposencoderLength; outpos++) { - ip=polarParams->rate_matching_pattern[outpos]; +#ifdef DEBUG_POLAR_ENCODER + printf("rm: outpos %d, inpos %d\n",outpos,ip); +#endif if ((ip - iplast) == 1) ccnt++; else { groupcnt++; #ifdef DEBUG_POLAR_ENCODER printf("group %d (size %d): (%d:%d) => (%d:%d)\n",groupcnt,ccnt+1, - firstingroup_in,firstingroup_in+ccnt, - firstingroup_out,firstingroup_out+ccnt); + firstingroup_in,firstingroup_in+ccnt, + firstingroup_out,firstingroup_out+ccnt); #endif + if ((ccnt+1) (%d:%d)\n",groupcnt,ccnt+1, + firstingroup_in,firstingroup_in+ccnt, + firstingroup_out,firstingroup_out+ccnt); +#endif + AssertFatal(mingroupsize==4 || mingroupsize==8 || mingroupsize==16,"mingroupsize %d, needs to be handled\n",mingroupsize); polarParams->groupsize=mingroupsize; int shift=3; + if (mingroupsize == 16) shift=4; - polarParams->rm_tab=(int*)malloc(sizeof(int)*polarParams->encoderLength/mingroupsize); + else if (mingroupsize == 4) shift=2; + + polarParams->rm_tab=(int *)malloc(sizeof(int)*polarParams->encoderLength/mingroupsize); // rerun again to create groups int tcnt=0; - for (int outpos=0;outposencoderLength; outpos+=mingroupsize,tcnt++) + + for (int outpos=0; outposencoderLength; outpos+=mingroupsize,tcnt++) polarParams->rm_tab[tcnt] = polarParams->rate_matching_pattern[outpos]>>shift; - } -void polar_encoder_fast(uint64_t *Aprime, - uint32_t *out, - int32_t crcmask, - t_nrPolar_paramsPtr polarParams) { - +void polar_encoder_fast(uint64_t *A, + uint32_t *out, + int32_t crcmask, + t_nrPolar_params *polarParams) { AssertFatal(polarParams->K > 32, "K = %d < 33, is not supported yet\n",polarParams->K); AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n",polarParams->K); AssertFatal(polarParams->payloadBits < 65, "payload bits = %d > 64, is not supported yet\n",polarParams->payloadBits); - - uint64_t B[4]={0,0,0,0}, Cprime[4]={0,0,0,0}; + uint64_t B[4]= {0,0,0,0},Cprime[4]= {0,0,0,0}; int bitlen = polarParams->payloadBits; - -#ifdef DEBUG_POLAR_MATLAB - if (polarParams->K<65) printf("[polar_encoder_fast]A[0] = 0x%llx\n", (unsigned long long)(Aprime[0])); //(unsigned long long)(Aprime[0]&(((uint64_t)1<crcParityBits == 24,"support for 24-bit crc only for now\n"); - //int bitlen0=bitlen; - uint64_t tcrc=0; // A bit string should be stored as 0, 0, ..., 0, a'_0, a'_1, ..., a'_A-1, @@ -418,42 +479,43 @@ void polar_encoder_fast(uint64_t *Aprime, // CRC reads in each byte in bit positions 7 down to 0, for PBCH/PDCCH we need to read in a_{A-1} down to a_{0}, A = length of bit string (e.g. 32 for PBCH) if (bitlen<=32) { uint8_t A32_flip[4]; - uint32_t AprimeTmp= (uint32_t)(((uint32_t)*Aprime)<<(32-bitlen)); - A32_flip[0]=((uint8_t*)&AprimeTmp)[3]; //a'_0, a'_1, ..., a'_7 - A32_flip[1]=((uint8_t*)&AprimeTmp)[2]; - A32_flip[2]=((uint8_t*)&AprimeTmp)[1]; - A32_flip[3]=((uint8_t*)&AprimeTmp)[0]; + uint32_t Aprime= (uint32_t)(((uint32_t)*A)<<(32-bitlen)); + A32_flip[0]=((uint8_t *)&Aprime)[3]; + A32_flip[1]=((uint8_t *)&Aprime)[2]; + A32_flip[2]=((uint8_t *)&Aprime)[1]; + A32_flip[3]=((uint8_t *)&Aprime)[0]; tcrc = (uint64_t)((crcmask^(crc24c(A32_flip,bitlen)>>8))); - } - else if (bitlen<=64) { + } else if (bitlen<=64) { uint8_t A64_flip[8]; - uint64_t AprimeTmp= (uint32_t)(((uint64_t)*Aprime)<<(64-bitlen)); - A64_flip[0]=((uint8_t*)&AprimeTmp)[7]; - A64_flip[1]=((uint8_t*)&AprimeTmp)[6]; - A64_flip[2]=((uint8_t*)&AprimeTmp)[5]; - A64_flip[3]=((uint8_t*)&AprimeTmp)[4]; - A64_flip[4]=((uint8_t*)&AprimeTmp)[3]; - A64_flip[5]=((uint8_t*)&AprimeTmp)[2]; - A64_flip[6]=((uint8_t*)&AprimeTmp)[1]; - A64_flip[7]=((uint8_t*)&AprimeTmp)[0]; + uint64_t Aprime= (uint32_t)(((uint64_t)*A)<<(64-bitlen)); + A64_flip[0]=((uint8_t *)&Aprime)[7]; + A64_flip[1]=((uint8_t *)&Aprime)[6]; + A64_flip[2]=((uint8_t *)&Aprime)[5]; + A64_flip[3]=((uint8_t *)&Aprime)[4]; + A64_flip[4]=((uint8_t *)&Aprime)[3]; + A64_flip[5]=((uint8_t *)&Aprime)[2]; + A64_flip[6]=((uint8_t *)&Aprime)[1]; + A64_flip[7]=((uint8_t *)&Aprime)[0]; tcrc = (uint64_t)((crcmask^(crc24c(A64_flip,bitlen)>>8))); } else if (bitlen<=128) { - uint8_t A128_flip[16]; - uint128_t AprimeTmp= (uint32_t)(((uint128_t)*Aprime)<<(128-bitlen)); - A128_flip[0]=((uint8_t*)&AprimeTmp)[15]; A128_flip[1]=((uint8_t*)&AprimeTmp)[14]; - A128_flip[2]=((uint8_t*)&AprimeTmp)[13]; A128_flip[3]=((uint8_t*)&AprimeTmp)[12]; - A128_flip[4]=((uint8_t*)&AprimeTmp)[11]; A128_flip[5]=((uint8_t*)&AprimeTmp)[10]; - A128_flip[6] =((uint8_t*)&AprimeTmp)[9]; A128_flip[7] =((uint8_t*)&AprimeTmp)[8]; - A128_flip[8] =((uint8_t*)&AprimeTmp)[7]; A128_flip[9] =((uint8_t*)&AprimeTmp)[6]; - A128_flip[10]=((uint8_t*)&AprimeTmp)[5]; A128_flip[11]=((uint8_t*)&AprimeTmp)[4]; - A128_flip[12]=((uint8_t*)&AprimeTmp)[3]; A128_flip[13]=((uint8_t*)&AprimeTmp)[2]; - A128_flip[14]=((uint8_t*)&AprimeTmp)[1]; A128_flip[15]=((uint8_t*)&AprimeTmp)[0]; - tcrc = (uint64_t)((crcmask^(crc24c(A128_flip,bitlen)>>8))); + uint8_t A128_flip[16]; + uint128_t Aprime= (uint32_t)(((uint128_t)*A)<<(128-bitlen)); + A128_flip[0]=((uint8_t*)&Aprime)[15]; A128_flip[1]=((uint8_t*)&Aprime)[14]; + A128_flip[2]=((uint8_t*)&Aprime)[13]; A128_flip[3]=((uint8_t*)&Aprime)[12]; + A128_flip[4]=((uint8_t*)&Aprime)[11]; A128_flip[5]=((uint8_t*)&Aprime)[10]; + A128_flip[6] =((uint8_t*)&Aprime)[9]; A128_flip[7] =((uint8_t*)&Aprime)[8]; + A128_flip[8] =((uint8_t*)&Aprime)[7]; A128_flip[9] =((uint8_t*)&Aprime)[6]; + A128_flip[10]=((uint8_t*)&Aprime)[5]; A128_flip[11]=((uint8_t*)&Aprime)[4]; + A128_flip[12]=((uint8_t*)&Aprime)[3]; A128_flip[13]=((uint8_t*)&Aprime)[2]; + A128_flip[14]=((uint8_t*)&Aprime)[1]; A128_flip[15]=((uint8_t*)&Aprime)[0]; + tcrc = (uint64_t)((crcmask^(crc24c(A128_flip,bitlen)>>8))); } int n; - int quadwlen = (polarParams->K>>6); // this is number of quadwords (64-bits) in the bit string + // this is number of quadwords in the bit string + int quadwlen = (polarParams->K>>6); + if ((polarParams->K&63) > 0) quadwlen++; // Create the B bit string as @@ -462,17 +524,13 @@ void polar_encoder_fast(uint64_t *Aprime, //??? b_{N'-1} b_{N'-2} ... b_{N'-A} b_{N'-A-1} ... b_{N'-A-Nparity} = a_{N-1} a_{N-2} ... a_{N-A} p_{N_parity-1} ... p_0 - for (n=0;ncrcParityBits) | tcrc; - else B[n] = (Aprime[n] << polarParams->crcParityBits) | (Aprime[n-1]>>(64-polarParams->crcParityBits)); - -#ifdef DEBUG_POLAR_MATLAB - // B = pbchB - for (int i = 0; i < quadwlen; i++) printf("[polar_encoder_fast]B[%d] = 0x%llx\n", i, (unsigned long long)(B[i])); -#endif + for (n=0; ncrcParityBits) | tcrc; + else B[n] = (A[n] << polarParams->crcParityBits) | (A[n-1]>>(64-polarParams->crcParityBits)); + + uint8_t *Bbyte = (uint8_t *)B; - uint8_t *Bbyte = (uint8_t*)B; // for each byte of B, lookup in corresponding table for 64-bit word corresponding to that byte and its position - if (polarParams->K<65) + if (polarParams->K<65) Cprime[0] = polarParams->cprime_tab0[0][Bbyte[0]] | polarParams->cprime_tab0[1][Bbyte[1]] | polarParams->cprime_tab0[2][Bbyte[2]] | @@ -481,9 +539,8 @@ void polar_encoder_fast(uint64_t *Aprime, polarParams->cprime_tab0[5][Bbyte[5]] | polarParams->cprime_tab0[6][Bbyte[6]] | polarParams->cprime_tab0[7][Bbyte[7]]; - else if (polarParams->K < 129) { - for (int i=0;i<1+(polarParams->K/8);i++) { + for (int i=0; i<1+(polarParams->K/8); i++) { Cprime[0] |= polarParams->cprime_tab0[i][Bbyte[i]]; Cprime[1] |= polarParams->cprime_tab1[i][Bbyte[i]]; } @@ -495,80 +552,155 @@ void polar_encoder_fast(uint64_t *Aprime, #endif #ifdef DEBUG_POLAR_ENCODER - if (polarParams->K<65) + + if (polarParams->K<65) printf("A %llx B %llx Cprime %llx (payload bits %d,crc %x)\n", - (unsigned long long)(Aprime[0]&(((uint64_t)1<payloadBits, - tcrc); + (unsigned long long)(A[0]&(((uint64_t)1<payloadBits, + tcrc); else if (polarParams->K<129) { if (bitlen<64) printf("A %llx B %llx|%llx Cprime %llx|%llx (payload bits %d,crc %x)\n", - (unsigned long long)(Aprime[0]&(((uint64_t)1<payloadBits, - tcrc); - else + (unsigned long long)(A[0]&(((uint64_t)1<payloadBits, + tcrc); + else printf("A %llx|%llx B %llx|%llx Cprime %llx|%llx (payload bits %d,crc %x)\n", - (unsigned long long)(Aprime[1]&(((uint64_t)1<<(bitlen-64))-1)),(unsigned long long)(Aprime[0]), - (unsigned long long)(B[1]),(unsigned long long)(B[0]), - (unsigned long long)(Cprime[1]),(unsigned long long)(Cprime[0]), - polarParams->payloadBits, - crc24c((uint8_t*)Aprime,bitlen)>>8); + (unsigned long long)(A[1]&(((uint64_t)1<<(bitlen-64))-1)),(unsigned long long)(A[0]), + (unsigned long long)(B[1]),(unsigned long long)(B[0]), + (unsigned long long)(Cprime[1]),(unsigned long long)(Cprime[0]), + polarParams->payloadBits, + crc24c((uint8_t *)A,bitlen)>>8); } + #endif - + /* printf("Bbytes : %x.%x.%x.%x.%x.%x.%x.%x\n",Bbyte[0],Bbyte[1],Bbyte[2],Bbyte[3],Bbyte[4],Bbyte[5],Bbyte[6],Bbyte[7]); + printf("%llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n",polarParams->cprime_tab[0][Bbyte[0]] , + polarParams->cprime_tab[1][Bbyte[1]] , + polarParams->cprime_tab[2][Bbyte[2]] , + polarParams->cprime_tab[3][Bbyte[3]] , + polarParams->cprime_tab[4][Bbyte[4]] , + polarParams->cprime_tab[5][Bbyte[5]] , + polarParams->cprime_tab[6][Bbyte[6]] , + polarParams->cprime_tab[7][Bbyte[7]]);*/ // now do Gu product (here using 64-bit XORs, we can also do with SIMD after) // here we're reading out the bits LSB -> MSB, is this correct w.r.t. 3GPP ? - uint64_t Cprime_i; - uint64_t D[8]={0,0,0,0,0,0,0,0}; + /* printf("%llx Cprime_0 (%llx) G %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n",Cprime_i,Cprime &1, + polarParams->G_N_tab[0][0], + polarParams->G_N_tab[0][1], + polarParams->G_N_tab[0][2], + polarParams->G_N_tab[0][3], + polarParams->G_N_tab[0][4], + polarParams->G_N_tab[0][5], + polarParams->G_N_tab[0][6], + polarParams->G_N_tab[0][7]);*/ + uint64_t D[8]= {0,0,0,0,0,0,0,0}; int off=0; int len=polarParams->K; - for (int j=0;j<(1+(polarParams->K>>6));j++,off+=64,len-=64) { - for (int i=0;i<((len>63) ? 64 : len);i++) { - - Cprime_i = -((Cprime[j]>>i)&1); // this converts bit 0 as, 0 => 0000x00, 1 => 1111x11 - - #ifdef DEBUG_POLAR_ENCODER - printf("%llx Cprime_%d (%llx) G %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", - Cprime_i,off+i,(Cprime[j]>>i) &1, - polarParams->G_N_tab[off+i][0], - polarParams->G_N_tab[off+i][1], - polarParams->G_N_tab[off+i][2], - polarParams->G_N_tab[off+i][3], - polarParams->G_N_tab[off+i][4], - polarParams->G_N_tab[off+i][5], - polarParams->G_N_tab[off+i][6], - polarParams->G_N_tab[off+i][7]); - #endif - - uint64_t *Gi=polarParams->G_N_tab[off+i]; - D[0] ^= (Cprime_i & Gi[0]); - D[1] ^= (Cprime_i & Gi[1]); - D[2] ^= (Cprime_i & Gi[2]); - D[3] ^= (Cprime_i & Gi[3]); - D[4] ^= (Cprime_i & Gi[4]); - D[5] ^= (Cprime_i & Gi[5]); - D[6] ^= (Cprime_i & Gi[6]); - D[7] ^= (Cprime_i & Gi[7]); + if (polarParams->N==512) { + for (int j=0; j<(1+(polarParams->K>>6)); j++,off+=64,len-=64) { + for (int i=0; i<((len>63) ? 64 : len); i++) { + Cprime_i = -((Cprime[j]>>i)&1); // this converts bit 0 as, 0 => 0000x00, 1 => 1111x11 + /* + #ifdef DEBUG_POLAR_ENCODER + printf("%llx Cprime_%d (%llx) G %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", + Cprime_i,off+i,(Cprime[j]>>i) &1, + polarParams->G_N_tab[off+i][0], + polarParams->G_N_tab[off+i][1], + polarParams->G_N_tab[off+i][2], + polarParams->G_N_tab[off+i][3], + polarParams->G_N_tab[off+i][4], + polarParams->G_N_tab[off+i][5], + polarParams->G_N_tab[off+i][6], + polarParams->G_N_tab[off+i][7]); + #endif + */ + uint64_t *Gi=polarParams->G_N_tab[off+i]; + D[0] ^= (Cprime_i & Gi[0]); + D[1] ^= (Cprime_i & Gi[1]); + D[2] ^= (Cprime_i & Gi[2]); + D[3] ^= (Cprime_i & Gi[3]); + D[4] ^= (Cprime_i & Gi[4]); + D[5] ^= (Cprime_i & Gi[5]); + D[6] ^= (Cprime_i & Gi[6]); + D[7] ^= (Cprime_i & Gi[7]); + +#ifdef DEBUG_POLAR_ENCODER + printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", + D[0], + D[1], + D[2], + D[3], + D[4], + D[5], + D[6], + D[7]); +#endif + } } } + else if (polarParams->N==256) { + for (int j=0; j<(1+(polarParams->K>>6)); j++,off+=64,len-=64) { + for (int i=0; i<((len>63) ? 64 : len); i++) { + Cprime_i = -((Cprime[j]>>i)&1); // this converts bit 0 as, 0 => 0000x00, 1 => 1111x11 + /* + #ifdef DEBUG_POLAR_ENCODER + printf("%llx Cprime_%d (%llx) G %llx,%llx,%llx,%llx\n", + Cprime_i,off+i,(Cprime[j]>>i) &1, + polarParams->G_N_tab[off+i][0], + polarParams->G_N_tab[off+i][1], + polarParams->G_N_tab[off+i][2], + polarParams->G_N_tab[off+i][3], + #endif + */ + uint64_t *Gi=polarParams->G_N_tab[off+i]; + D[0] ^= (Cprime_i & Gi[0]); + D[1] ^= (Cprime_i & Gi[1]); + D[2] ^= (Cprime_i & Gi[2]); + D[3] ^= (Cprime_i & Gi[3]); + + #ifdef DEBUG_POLAR_ENCODER - printf("D %llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n", D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7]); + printf("D %llx,%llx,%llx,%llx\n", + D[0], + D[1], + D[2], + D[3]); #endif - -#ifdef DEBUG_POLAR_MATLAB - // D = pbchD - for (int i = 0; i < 8; i++) printf("[polar_encoder_fast]D[%d] = 0x%016llx\n", i, (unsigned long long)(D[i])); -#endif - - polar_rate_matching(polarParams,(void*)D,(void*)out); -#ifdef DEBUG_POLAR_MATLAB - // out = pbchF - for (int i = 0; i < (NR_POLAR_PBCH_E/32); i++) printf("[polar_encoder_fast]F[%d] = 0x%08lx\n", i, (unsigned long)(out[i])); + } + } + } + else if (polarParams->N==128) { + for (int j=0; j<(1+(polarParams->K>>6)); j++,off+=64,len-=64) { + for (int i=0; i<((len>63) ? 64 : len); i++) { + Cprime_i = -((Cprime[j]>>i)&1); // this converts bit 0 as, 0 => 0000x00, 1 => 1111x11 + + #ifdef DEBUG_POLAR_ENCODER + printf("%llx Cprime_%d (%d+%d) (%llx) G %llx,%llx\n", + Cprime_i,off+i,off,i,(Cprime[j]>>i) &1, + polarParams->G_N_tab[off+i][0], + polarParams->G_N_tab[off+i][1]); + #endif + + uint64_t *Gi=polarParams->G_N_tab[off+i]; + D[0] ^= (Cprime_i & Gi[0]); + D[1] ^= (Cprime_i & Gi[1]); + + +#ifdef DEBUG_POLAR_ENCODER + printf("D %llx,%llx\n", + D[0], + D[1]); #endif + } + } + } + memset((void*)out,0,polarParams->encoderLength>>3); + polar_rate_matching(polarParams,(void *)D,(void *)out); } diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c index fd7793ca79..e78f3a85b7 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c @@ -28,322 +28,320 @@ * \email turker.yilmaz@eurecom.fr * \note * \warning -*/ + */ #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" void nr_polar_bit_insertion(uint8_t *input, - uint8_t *output, - uint16_t N, - uint16_t K, - int16_t *Q_I_N, - int16_t *Q_PC_N, - uint8_t n_PC) + uint8_t *output, + uint16_t N, + uint16_t K, + int16_t *Q_I_N, + int16_t *Q_PC_N, + uint8_t n_PC) { uint16_t k=0; uint8_t flag; - if (n_PC>0) { - /* - * - */ - } else { - for (int n=0; n<=N-1; n++) { - flag=0; - for (int m=0; m<=(K+n_PC)-1; m++) { - if ( n == Q_I_N[m]) { - flag=1; - break; - } - } - if (flag) { // n ϵ Q_I_N - output[n]=input[k]; - k++; - } else { - output[n] = 0; - } - } + if (n_PC>0) { + /* + * + */ + } else { + for (int n=0; n<=N-1; n++) { + flag=0; + for (int m=0; m<=(K+n_PC)-1; m++) { + if ( n == Q_I_N[m]) { + flag=1; + break; } + } + if (flag) { // n ϵ Q_I_N + output[n]=input[k]; + k++; + } else { + output[n] = 0; + } + } + } } uint32_t nr_polar_output_length(uint16_t K, - uint16_t E, - uint8_t n_max) + uint16_t E, + uint8_t n_max) { - uint8_t n_1, n_2, n_min=5, n; - double R_min=1.0/8; + uint8_t n_1, n_2, n_min=5, n; + double R_min=1.0/8; + + if ( (E <= (9.0/8)*pow(2,ceil(log2(E))-1)) && (K/E < 9.0/16) ) { + n_1 = ceil(log2(E))-1; + } else { + n_1 = ceil(log2(E)); + } + + n_2 = ceil(log2(K/R_min)); + + n=n_max; + if (n>n_1) n=n_1; + if (n>n_2) n=n_2; + if (nn_1) n=n_1; - if (n>n_2) n=n_2; - if (n= (3.0 / 4)) { + limit = ceil((double) (3 * N - 2 * E) / 4); + for (int n = 0; n <= limit - 1; n++) { + ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = n; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; } - - uint8_t flag; - uint16_t limit, ind; - - if (E < N) { - if ((K / (double) E) <= (7.0 / 16)) { //puncturing - for (int n = 0; n <= N - E - 1; n++) { - ind = Q_Ftmp_N[N] + 1; - Q_Ftmp_N[ind] = J[n]; - Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; - } - - if ((E / (double) N) >= (3.0 / 4)) { - limit = ceil((double) (3 * N - 2 * E) / 4); - for (int n = 0; n <= limit - 1; n++) { - ind = Q_Ftmp_N[N] + 1; - Q_Ftmp_N[ind] = n; - Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; - } - } else { - limit = ceil((double) (9 * N - 4 * E) / 16); - for (int n = 0; n <= limit - 1; n++) { - ind = Q_Ftmp_N[N] + 1; - Q_Ftmp_N[ind] = n; - Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; - } - } - } else { //shortening - for (int n = E; n <= N - 1; n++) { - ind = Q_Ftmp_N[N] + 1; - Q_Ftmp_N[ind] = J[n]; - Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; - } - } + } else { + limit = ceil((double) (9 * N - 4 * E) / 16); + for (int n = 0; n <= limit - 1; n++) { + ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = n; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; } + } + } else { //shortening + for (int n = E; n <= N - 1; n++) { + ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = J[n]; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + } + } + } - //Q_I,tmp_N = Q_0_N-1 \ Q_F,tmp_N - for (int n = 0; n <= N - 1; n++) { - flag = 1; - for (int m = 0; m <= Q_Ftmp_N[N]; m++) { - if (Q_0_Nminus1[n] == Q_Ftmp_N[m]) { - flag = 0; - break; - } - } - if (flag) { - Q_Itmp_N[Q_Itmp_N[N] + 1] = Q_0_Nminus1[n]; - Q_Itmp_N[N]++; - } - } + //Q_I,tmp_N = Q_0_N-1 \ Q_F,tmp_N + for (int n = 0; n <= N - 1; n++) { + flag = 1; + for (int m = 0; m <= Q_Ftmp_N[N]; m++) { + if (Q_0_Nminus1[n] == Q_Ftmp_N[m]) { + flag = 0; + break; + } + } + if (flag) { + Q_Itmp_N[Q_Itmp_N[N] + 1] = Q_0_Nminus1[n]; + Q_Itmp_N[N]++; + } + } - //Q_I_N comprises (K+n_PC) most reliable bit indices in Q_I,tmp_N - for (int n = 0; n <= (K + n_PC) - 1; n++) { - ind = Q_Itmp_N[N] + n - ((K + n_PC) - 1); - Q_I_N[n] = Q_Itmp_N[ind]; - } + //Q_I_N comprises (K+n_PC) most reliable bit indices in Q_I,tmp_N + for (int n = 0; n <= (K + n_PC) - 1; n++) { + ind = Q_Itmp_N[N] + n - ((K + n_PC) - 1); + Q_I_N[n] = Q_Itmp_N[ind]; + } - //Q_F_N = Q_0_N-1 \ Q_I_N - for (int n = 0; n <= N - 1; n++) { - flag = 1; - for (int m = 0; m <= (K + n_PC) - 1; m++) { - if (Q_0_Nminus1[n] == Q_I_N[m]) { - flag = 0; - break; - } - } - if (flag) { - Q_F_N[Q_F_N[N] + 1] = Q_0_Nminus1[n]; - Q_F_N[N]++; - } - } + //Q_F_N = Q_0_N-1 \ Q_I_N + for (int n = 0; n <= N - 1; n++) { + flag = 1; + for (int m = 0; m <= (K + n_PC) - 1; m++) { + if (Q_0_Nminus1[n] == Q_I_N[m]) { + flag = 0; + break; + } + } + if (flag) { + Q_F_N[Q_F_N[N] + 1] = Q_0_Nminus1[n]; + Q_F_N[N]++; + } + } - //Information Bit Pattern - for (int n = 0; n <= N - 1; n++) { - ibp[n] = 0; + //Information Bit Pattern + for (int n = 0; n <= N - 1; n++) { + ibp[n] = 0; - for (int m = 0; m <= (K + n_PC) - 1; m++) { - if (n == Q_I_N[m]) { - ibp[n] = 1; - break; - } - } - } + for (int m = 0; m <= (K + n_PC) - 1; m++) { + if (n == Q_I_N[m]) { + ibp[n] = 1; + break; + } + } + } - free(Q_Ftmp_N); - free(Q_Itmp_N); + free(Q_Ftmp_N); + free(Q_Itmp_N); } void nr_polar_info_bit_extraction(uint8_t *input, - uint8_t *output, - uint8_t *pattern, - uint16_t size) + uint8_t *output, + uint8_t *pattern, + uint16_t size) { - uint16_t j = 0; - for (int i = 0; i < size; i++) { - if (pattern[i] > 0) { - output[j] = input[i]; - j++; - } - } + uint16_t j = 0; + for (int i = 0; i < size; i++) { + if (pattern[i] > 0) { + output[j] = input[i]; + j++; + } + } } void nr_polar_rate_matching_pattern(uint16_t *rmp, - uint16_t *J, - const uint8_t *P_i_, - uint16_t K, - uint16_t N, - uint16_t E) + uint16_t *J, + const uint8_t *P_i_, + uint16_t K, + uint16_t N, + uint16_t E) { - uint8_t i; - uint16_t *d, *y, ind; - d = (uint16_t *)malloc(sizeof(uint16_t) * N); - y = (uint16_t *)malloc(sizeof(uint16_t) * N); + uint8_t i; + uint16_t *d, *y, ind; + d = (uint16_t *)malloc(sizeof(uint16_t) * N); + y = (uint16_t *)malloc(sizeof(uint16_t) * N); - for (int m=0; m<=N-1; m++) d[m]=m; + for (int m=0; m<=N-1; m++) d[m]=m; - for (int m=0; m<=N-1; m++){ - i=floor((32*m)/N); - J[m] = (P_i_[i]*(N/32)) + (m%(N/32)); - y[m] = d[J[m]]; - } + for (int m=0; m<=N-1; m++){ + i=floor((32*m)/N); + J[m] = (P_i_[i]*(N/32)) + (m%(N/32)); + y[m] = d[J[m]]; + } - if (E>=N) { //repetition - for (int k=0; k<=E-1; k++) { - ind = (k%N); - rmp[k]=y[ind]; - } - } else { - if ( (K/(double)E) <= (7.0/16) ) { //puncturing - for (int k=0; k<=E-1; k++) { - rmp[k]=y[k+N-E]; - } - } else { //shortening - for (int k=0; k<=E-1; k++) { - rmp[k]=y[k]; - } - } - } + if (E>=N) { //repetition + for (int k=0; k<=E-1; k++) { + ind = (k%N); + rmp[k]=y[ind]; + } + } else { + if ( (K/(double)E) <= (7.0/16) ) { //puncturing + for (int k=0; k<=E-1; k++) { + rmp[k]=y[k+N-E]; + } + } else { //shortening + for (int k=0; k<=E-1; k++) { + rmp[k]=y[k]; + } + } + } - free(d); - free(y); + free(d); + free(y); } void nr_polar_rate_matching(double *input, - double *output, - uint16_t *rmp, - uint16_t K, - uint16_t N, - uint16_t E) + double *output, + uint16_t *rmp, + uint16_t K, + uint16_t N, + uint16_t E) { - if (E>=N) { //repetition - for (int i=0; i<=N-1; i++) output[i]=0; - for (int i=0; i<=E-1; i++){ - output[rmp[i]]+=input[i]; - } - } else { - if ( (K/(double)E) <= (7.0/16) ) { //puncturing - for (int i=0; i<=N-1; i++) output[i]=0; - } else { //shortening - for (int i=0; i<=N-1; i++) output[i]=INFINITY; - } + if (E>=N) { //repetition + for (int i=0; i<=N-1; i++) output[i]=0; + for (int i=0; i<=E-1; i++){ + output[rmp[i]]+=input[i]; + } + } else { + if ( (K/(double)E) <= (7.0/16) ) { //puncturing + for (int i=0; i<=N-1; i++) output[i]=0; + } else { //shortening + for (int i=0; i<=N-1; i++) output[i]=INFINITY; + } - for (int i=0; i<=E-1; i++){ - output[rmp[i]]=input[i]; - } - } + for (int i=0; i<=E-1; i++){ + output[rmp[i]]=input[i]; + } + } } void nr_polar_rate_matching_int16(int16_t *input, - int16_t *output, - uint16_t *rmp, - uint16_t K, - uint16_t N, - uint16_t E) + int16_t *output, + uint16_t *rmp, + uint16_t K, + uint16_t N, + uint16_t E) { - if (E>=N) { //repetition - for (int i=0; i<=N-1; i++) output[i]=0; - for (int i=0; i<=E-1; i++){ - output[rmp[i]]+=input[i]; - } - } else { - if ( (K/(double)E) <= (7.0/16) ) { //puncturing - for (int i=0; i<=N-1; i++) output[i]=0; - } else { //shortening - for (int i=0; i<=N-1; i++) output[i]=32767;//instead of INFINITY, to prevent [-Woverflow] - } + if (E>=N) { //repetition + memset((void*)output,0,N*sizeof(int16_t)); + for (int i=0; i<=E-1; i++) output[rmp[i]]+=input[i]; + } else { + if ( (K/(double)E) <= (7.0/16) ) memset((void*)output,0,N*sizeof(int16_t)); //puncturing + else { //shortening + for (int i=0; i<=N-1; i++) output[i]=32767;//instead of INFINITY, to prevent [-Woverflow] + } - for (int i=0; i<=E-1; i++){ - output[rmp[i]]=input[i]; - } - } + for (int i=0; i<=E-1; i++) output[rmp[i]]=input[i]; + + } } diff --git a/openair1/PHY/CODING/nrSmallBlock/decodeSmallBlock.c b/openair1/PHY/CODING/nrSmallBlock/decodeSmallBlock.c index 38b9a6b13c..8b53944455 100644 --- a/openair1/PHY/CODING/nrSmallBlock/decodeSmallBlock.c +++ b/openair1/PHY/CODING/nrSmallBlock/decodeSmallBlock.c @@ -48,8 +48,8 @@ uint16_t decodeSmallBlock(int8_t *in, uint8_t len){ int16_t Rhat[NR_SMALL_BLOCK_CODED_BITS] = {0}, Rhatabs[NR_SMALL_BLOCK_CODED_BITS] = {0}; uint16_t maxVal; uint8_t maxInd = 0; - - for (int j = 0; j < NR_SMALL_BLOCK_CODED_BITS; ++j) + int jmax = (1<<(len-1)); + for (int j = 0; j < jmax; ++j) for (int k = 0; k < NR_SMALL_BLOCK_CODED_BITS; ++k) Rhat[j] += in[k] * hadamard32InterleavedTransposed[j][k]; @@ -67,7 +67,7 @@ uint16_t decodeSmallBlock(int8_t *in, uint8_t len){ } #endif maxVal = Rhatabs[0]; - for (int k = 1; k < NR_SMALL_BLOCK_CODED_BITS; ++k){ + for (int k = 1; k < jmax; ++k){ if (Rhatabs[k] > maxVal){ maxVal = Rhatabs[k]; maxInd = k; @@ -77,7 +77,7 @@ uint16_t decodeSmallBlock(int8_t *in, uint8_t len){ out = properOrderedBasis[maxInd] | ( (Rhat[maxInd] > 0) ? (uint16_t)0 : (uint16_t)1 ); #ifdef DEBUG_DECODESMALLBLOCK - for (int k = 0; k < NR_SMALL_BLOCK_CODED_BITS; ++k) + for (int k = 0; k < jmax; ++k) printf("[decodeSmallBlock]Rhat[%d]=%d %d %d %d\n",k, Rhat[k], maxVal, maxInd, ((uint32_t)out>>k)&1); printf("[decodeSmallBlock]0x%x 0x%x\n", out, properOrderedBasis[maxInd]); #endif diff --git a/openair1/PHY/CODING/nr_polar_init.c b/openair1/PHY/CODING/nr_polar_init.c index 946657a905..dd0056b3b5 100644 --- a/openair1/PHY/CODING/nr_polar_init.c +++ b/openair1/PHY/CODING/nr_polar_init.c @@ -37,201 +37,175 @@ #include "PHY/NR_TRANSPORT/nr_dci.h" static int intcmp(const void *p1,const void *p2) { - - return(*(int16_t*)p1 > *(int16_t*)p2); + return(*(int16_t *)p1 > *(int16_t *)p2); } -void nr_polar_init(t_nrPolar_paramsPtr *polarParams, - int8_t messageType, - uint16_t messageLength, - uint8_t aggregation_level) -{ - t_nrPolar_paramsPtr currentPtr = *polarParams; - uint16_t aggregation_prime = nr_polar_aggregation_prime(aggregation_level); +static void nr_polar_init(t_nrPolar_params * *polarParams, + int8_t messageType, + uint16_t messageLength, + uint8_t aggregation_level) { + t_nrPolar_params *currentPtr = *polarParams; + uint16_t aggregation_prime = nr_polar_aggregation_prime(aggregation_level); - //Parse the list. If the node is already created, return without initialization. - while (currentPtr != NULL) { - //printf("currentPtr->idx %d, (%d,%d)\n",currentPtr->idx,currentPtr->payloadBits,currentPtr->encoderLength); - if (currentPtr->idx == (messageType * messageLength * aggregation_prime)) return; - else currentPtr = currentPtr->nextPtr; - } + //Parse the list. If the node is already created, return without initialization. + while (currentPtr != NULL) { + //printf("currentPtr->idx %d, (%d,%d)\n",currentPtr->idx,currentPtr->payloadBits,currentPtr->encoderLength); + if (currentPtr->idx == (messageType * messageLength * aggregation_prime)) return; + else currentPtr = currentPtr->nextPtr; + } - // printf("currentPtr %p (polarParams %p)\n",currentPtr,polarParams); - //Else, initialize and add node to the end of the linked list. - t_nrPolar_paramsPtr newPolarInitNode = malloc(sizeof(t_nrPolar_params)); + // printf("currentPtr %p (polarParams %p)\n",currentPtr,polarParams); + //Else, initialize and add node to the end of the linked list. + t_nrPolar_params *newPolarInitNode = malloc(sizeof(t_nrPolar_params)); - if (newPolarInitNode != NULL) { + if (newPolarInitNode != NULL) { + newPolarInitNode->idx = (messageType * messageLength * aggregation_prime); + newPolarInitNode->nextPtr = NULL; + //printf("newPolarInitNode->idx %d, (%d,%d,%d:%d)\n",newPolarInitNode->idx,messageType,messageLength,aggregation_prime,aggregation_level); - newPolarInitNode->idx = (messageType * messageLength * aggregation_prime); - newPolarInitNode->nextPtr = (t_nrPolar_params *)NULL; + if (messageType == 0) { //PBCH + newPolarInitNode->n_max = NR_POLAR_PBCH_N_MAX; + newPolarInitNode->i_il = NR_POLAR_PBCH_I_IL; + newPolarInitNode->i_seg = NR_POLAR_PBCH_I_SEG; + newPolarInitNode->n_pc = NR_POLAR_PBCH_N_PC; + newPolarInitNode->n_pc_wm = NR_POLAR_PBCH_N_PC_WM; + newPolarInitNode->i_bil = NR_POLAR_PBCH_I_BIL; + newPolarInitNode->crcParityBits = NR_POLAR_PBCH_CRC_PARITY_BITS; + newPolarInitNode->payloadBits = NR_POLAR_PBCH_PAYLOAD_BITS; + newPolarInitNode->encoderLength = NR_POLAR_PBCH_E; + newPolarInitNode->crcCorrectionBits = NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS; + newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits);//G_P + //printf("Initializing polar parameters for PBCH (K %d, E %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength); + } else if (messageType == 1) { //DCI + newPolarInitNode->n_max = NR_POLAR_DCI_N_MAX; + newPolarInitNode->i_il = NR_POLAR_DCI_I_IL; + newPolarInitNode->i_seg = NR_POLAR_DCI_I_SEG; + newPolarInitNode->n_pc = NR_POLAR_DCI_N_PC; + newPolarInitNode->n_pc_wm = NR_POLAR_DCI_N_PC_WM; + newPolarInitNode->i_bil = NR_POLAR_DCI_I_BIL; + newPolarInitNode->crcParityBits = NR_POLAR_DCI_CRC_PARITY_BITS; + newPolarInitNode->payloadBits = messageLength; + newPolarInitNode->encoderLength = aggregation_level*108; + newPolarInitNode->crcCorrectionBits = NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS; + newPolarInitNode->crc_generator_matrix=crc24c_generator_matrix(newPolarInitNode->payloadBits+newPolarInitNode->crcParityBits);//G_P + //printf("Initializing polar parameters for DCI (K %d, E %d, L %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength,aggregation_level); + } else if (messageType == -1) { //UCI + } else { + AssertFatal(1 == 0, "[nr_polar_init] Incorrect Message Type(%d)", messageType); + } - //printf("newPolarInitNode->idx %d, (%d,%d,%d:%d)\n",newPolarInitNode->idx,messageType,messageLength,aggregation_prime,aggregation_level); + newPolarInitNode->K = newPolarInitNode->payloadBits + newPolarInitNode->crcParityBits; // Number of bits to encode. + newPolarInitNode->N = nr_polar_output_length(newPolarInitNode->K, newPolarInitNode->encoderLength, newPolarInitNode->n_max); + newPolarInitNode->n = log2(newPolarInitNode->N); + newPolarInitNode->G_N = nr_polar_kronecker_power_matrices(newPolarInitNode->n); + //polar_encoder vectors: + newPolarInitNode->nr_polar_crc = malloc(sizeof(uint8_t) * newPolarInitNode->crcParityBits); + newPolarInitNode->nr_polar_aPrime = malloc(sizeof(uint8_t) * ((ceil((newPolarInitNode->payloadBits)/32.0)*4)+3)); + newPolarInitNode->nr_polar_APrime = malloc(sizeof(uint8_t) * newPolarInitNode->K); + newPolarInitNode->nr_polar_D = malloc(sizeof(uint8_t) * newPolarInitNode->N); + newPolarInitNode->nr_polar_E = malloc(sizeof(uint8_t) * newPolarInitNode->encoderLength); + //Polar Coding vectors + newPolarInitNode->nr_polar_U = malloc(sizeof(uint8_t) * newPolarInitNode->N); //Decoder: nr_polar_uHat + newPolarInitNode->nr_polar_CPrime = malloc(sizeof(uint8_t) * newPolarInitNode->K); //Decoder: nr_polar_cHat + newPolarInitNode->nr_polar_B = malloc(sizeof(uint8_t) * newPolarInitNode->K); //Decoder: nr_polar_bHat + newPolarInitNode->nr_polar_A = malloc(sizeof(uint8_t) * newPolarInitNode->payloadBits); //Decoder: nr_polar_aHat + newPolarInitNode->Q_0_Nminus1 = nr_polar_sequence_pattern(newPolarInitNode->n); + newPolarInitNode->interleaving_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->K); + nr_polar_interleaving_pattern(newPolarInitNode->K, + newPolarInitNode->i_il, + newPolarInitNode->interleaving_pattern); + newPolarInitNode->deinterleaving_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->K); - if (messageType == 0) { //PBCH - newPolarInitNode->n_max = NR_POLAR_PBCH_N_MAX; - newPolarInitNode->i_il = NR_POLAR_PBCH_I_IL; - newPolarInitNode->i_seg = NR_POLAR_PBCH_I_SEG; - newPolarInitNode->n_pc = NR_POLAR_PBCH_N_PC; - newPolarInitNode->n_pc_wm = NR_POLAR_PBCH_N_PC_WM; - newPolarInitNode->i_bil = NR_POLAR_PBCH_I_BIL; - newPolarInitNode->crcParityBits = NR_POLAR_PBCH_CRC_PARITY_BITS; - newPolarInitNode->payloadBits = NR_POLAR_PBCH_PAYLOAD_BITS; - newPolarInitNode->encoderLength = NR_POLAR_PBCH_E; - newPolarInitNode->crcCorrectionBits = NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS; - newPolarInitNode->crc_generator_matrix = crc24c_generator_matrix(newPolarInitNode->payloadBits);//G_P - //printf("Initializing polar parameters for PBCH (K %d, E %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength); - } else if (messageType == 1) { //DCI - newPolarInitNode->n_max = NR_POLAR_DCI_N_MAX; - newPolarInitNode->i_il = NR_POLAR_DCI_I_IL; - newPolarInitNode->i_seg = NR_POLAR_DCI_I_SEG; - newPolarInitNode->n_pc = NR_POLAR_DCI_N_PC; - newPolarInitNode->n_pc_wm = NR_POLAR_DCI_N_PC_WM; - newPolarInitNode->i_bil = NR_POLAR_DCI_I_BIL; - newPolarInitNode->crcParityBits = NR_POLAR_DCI_CRC_PARITY_BITS; - newPolarInitNode->payloadBits = messageLength; - newPolarInitNode->encoderLength = aggregation_level*108; - newPolarInitNode->crcCorrectionBits = NR_POLAR_DCI_CRC_ERROR_CORRECTION_BITS; - newPolarInitNode->crc_generator_matrix=crc24c_generator_matrix(newPolarInitNode->payloadBits+newPolarInitNode->crcParityBits);//G_P - //printf("Initializing polar parameters for DCI (K %d, E %d, L %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength,aggregation_level); - } else if (messageType == -1) { //UCI + for (int i=0; iK; i++) + newPolarInitNode->deinterleaving_pattern[newPolarInitNode->interleaving_pattern[i]] = i; - } else { - AssertFatal(1 == 0, "[nr_polar_init] Incorrect Message Type(%d)", messageType); - } + newPolarInitNode->rate_matching_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength); + uint16_t *J = malloc(sizeof(uint16_t) * newPolarInitNode->N); + nr_polar_rate_matching_pattern(newPolarInitNode->rate_matching_pattern, + J, + nr_polar_subblock_interleaver_pattern, + newPolarInitNode->K, + newPolarInitNode->N, + newPolarInitNode->encoderLength); + newPolarInitNode->information_bit_pattern = malloc(sizeof(uint8_t) * newPolarInitNode->N); + newPolarInitNode->Q_I_N = malloc(sizeof(int16_t) * (newPolarInitNode->K + newPolarInitNode->n_pc)); + newPolarInitNode->Q_F_N = malloc( sizeof(int16_t) * (newPolarInitNode->N + 1)); // Last element shows the final array index assigned a value. + newPolarInitNode->Q_PC_N = malloc( sizeof(int16_t) * (newPolarInitNode->n_pc)); - newPolarInitNode->K = newPolarInitNode->payloadBits + newPolarInitNode->crcParityBits; // Number of bits to encode. - newPolarInitNode->N = nr_polar_output_length(newPolarInitNode->K, newPolarInitNode->encoderLength, newPolarInitNode->n_max); - newPolarInitNode->n = log2(newPolarInitNode->N); - newPolarInitNode->G_N = nr_polar_kronecker_power_matrices(newPolarInitNode->n); + for (int i = 0; i <= newPolarInitNode->N; i++) + newPolarInitNode->Q_F_N[i] = -1; // Empty array. - //polar_encoder vectors: - newPolarInitNode->nr_polar_crc = malloc(sizeof(uint8_t) * newPolarInitNode->crcParityBits); - newPolarInitNode->nr_polar_aPrime = malloc(sizeof(uint8_t) * ((ceil((newPolarInitNode->payloadBits)/32.0)*4)+3)); - newPolarInitNode->nr_polar_APrime = malloc(sizeof(uint8_t) * newPolarInitNode->K); - newPolarInitNode->nr_polar_D = malloc(sizeof(uint8_t) * newPolarInitNode->N); - newPolarInitNode->nr_polar_E = malloc(sizeof(uint8_t) * newPolarInitNode->encoderLength); + nr_polar_info_bit_pattern(newPolarInitNode->information_bit_pattern, + newPolarInitNode->Q_I_N, + newPolarInitNode->Q_F_N, + J, + newPolarInitNode->Q_0_Nminus1, + newPolarInitNode->K, + newPolarInitNode->N, + newPolarInitNode->encoderLength, + newPolarInitNode->n_pc); + // sort the Q_I_N array in ascending order (first K positions) + qsort((void *)newPolarInitNode->Q_I_N,newPolarInitNode->K,sizeof(int16_t),intcmp); + newPolarInitNode->channel_interleaver_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength); + nr_polar_channel_interleaver_pattern(newPolarInitNode->channel_interleaver_pattern, + newPolarInitNode->i_bil, + newPolarInitNode->encoderLength); + free(J); + build_decoder_tree(newPolarInitNode); + build_polar_tables(newPolarInitNode); + init_polar_deinterleaver_table(newPolarInitNode); + //printf("decoder tree nodes %d\n",newPolarInitNode->tree.num_nodes); + } else { + AssertFatal(1 == 0, "[nr_polar_init] New t_nrPolar_params * could not be created"); + } - //Polar Coding vectors - newPolarInitNode->nr_polar_U = malloc(sizeof(uint8_t) * newPolarInitNode->N); //Decoder: nr_polar_uHat - newPolarInitNode->nr_polar_CPrime = malloc(sizeof(uint8_t) * newPolarInitNode->K); //Decoder: nr_polar_cHat - newPolarInitNode->nr_polar_B = malloc(sizeof(uint8_t) * newPolarInitNode->K); //Decoder: nr_polar_bHat - newPolarInitNode->nr_polar_A = malloc(sizeof(uint8_t) * newPolarInitNode->payloadBits); //Decoder: nr_polar_aHat - - - - newPolarInitNode->Q_0_Nminus1 = nr_polar_sequence_pattern(newPolarInitNode->n); - - newPolarInitNode->interleaving_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->K); - nr_polar_interleaving_pattern(newPolarInitNode->K, - newPolarInitNode->i_il, - newPolarInitNode->interleaving_pattern); - - newPolarInitNode->deinterleaving_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->K); - for (int i=0;iK;i++) - newPolarInitNode->deinterleaving_pattern[newPolarInitNode->interleaving_pattern[i]] = i; - - newPolarInitNode->rate_matching_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength); - uint16_t *J = malloc(sizeof(uint16_t) * newPolarInitNode->N); - nr_polar_rate_matching_pattern(newPolarInitNode->rate_matching_pattern, - J, - nr_polar_subblock_interleaver_pattern, - newPolarInitNode->K, - newPolarInitNode->N, - newPolarInitNode->encoderLength); - - newPolarInitNode->information_bit_pattern = malloc(sizeof(uint8_t) * newPolarInitNode->N); - newPolarInitNode->Q_I_N = malloc(sizeof(int16_t) * (newPolarInitNode->K + newPolarInitNode->n_pc)); - newPolarInitNode->Q_F_N = malloc( sizeof(int16_t) * (newPolarInitNode->N + 1)); // Last element shows the final array index assigned a value. - newPolarInitNode->Q_PC_N = malloc( sizeof(int16_t) * (newPolarInitNode->n_pc)); - for (int i = 0; i <= newPolarInitNode->N; i++) - newPolarInitNode->Q_F_N[i] = -1; // Empty array. - nr_polar_info_bit_pattern(newPolarInitNode->information_bit_pattern, - newPolarInitNode->Q_I_N, - newPolarInitNode->Q_F_N, - J, - newPolarInitNode->Q_0_Nminus1, - newPolarInitNode->K, - newPolarInitNode->N, - newPolarInitNode->encoderLength, - newPolarInitNode->n_pc); - // sort the Q_I_N array in ascending order (first K positions) - qsort((void*)newPolarInitNode->Q_I_N,newPolarInitNode->K,sizeof(int16_t),intcmp); - - newPolarInitNode->channel_interleaver_pattern = malloc(sizeof(uint16_t) * newPolarInitNode->encoderLength); - nr_polar_channel_interleaver_pattern(newPolarInitNode->channel_interleaver_pattern, - newPolarInitNode->i_bil, - newPolarInitNode->encoderLength); - - free(J); - - build_decoder_tree(newPolarInitNode); - build_polar_tables(newPolarInitNode); - init_polar_deinterleaver_table(newPolarInitNode); - - //printf("decoder tree nodes %d\n",newPolarInitNode->tree.num_nodes); - - } else { - AssertFatal(1 == 0, "[nr_polar_init] New t_nrPolar_paramsPtr could not be created"); - } - - currentPtr = *polarParams; - //If polarParams is empty: - if (currentPtr == NULL) - { - *polarParams = newPolarInitNode; - //printf("Creating first polarParams entry index %d, %p\n",newPolarInitNode->idx,*polarParams); - return; - } - //Else, add node to the end of the linked list. - while (currentPtr->nextPtr != NULL) { - currentPtr = currentPtr->nextPtr; - } - currentPtr->nextPtr= newPolarInitNode; - printf("Adding new polarParams entry to list index %d,%p\n", newPolarInitNode->idx, currentPtr->nextPtr); - - return; + //Fixme: the list is not thread safe + //The defect is not critical: we always append (never delete items) and adding two times the same is fine + newPolarInitNode->nextPtr=*polarParams; + *polarParams=newPolarInitNode; + return; } -void nr_polar_print_polarParams(t_nrPolar_paramsPtr polarParams) -{ - uint8_t i = 0; - if (polarParams == NULL) { - printf("polarParams is empty.\n"); - } else { - while (polarParams != NULL){ - printf("polarParams[%d] = %d\n", i, polarParams->idx); - polarParams = polarParams->nextPtr; - i++; - } - } - return; +void nr_polar_print_polarParams(t_nrPolar_params *polarParams) { + uint8_t i = 0; + + if (polarParams == NULL) { + printf("polarParams is empty.\n"); + } else { + while (polarParams != NULL) { + printf("polarParams[%d] = %d\n", i, polarParams->idx); + polarParams = polarParams->nextPtr; + i++; + } + } + + return; } -t_nrPolar_paramsPtr nr_polar_params (t_nrPolar_paramsPtr polarParams, - int8_t messageType, - uint16_t messageLength, - uint8_t aggregation_level) -{ - t_nrPolar_paramsPtr currentPtr = NULL; +t_nrPolar_params *nr_polar_params ( int8_t messageType, + uint16_t messageLength, + uint8_t aggregation_level) { + static t_nrPolar_params *polarList = NULL; + nr_polar_init(&polarList, messageType,messageLength,aggregation_level); + t_nrPolar_params *polarParams=polarList; + const int tag=messageType * messageLength * nr_polar_aggregation_prime(aggregation_level); - while (polarParams != NULL) { - if (polarParams->idx == - (messageType * messageLength * (nr_polar_aggregation_prime(aggregation_level)) )) { - currentPtr = polarParams; - break; - } else { - polarParams = polarParams->nextPtr; - } - } - return currentPtr; + while (polarParams != NULL) { + if (polarParams->idx == tag) + return polarParams; + + polarParams = polarParams->nextPtr; + } + + AssertFatal(false,"Polar Init tables internal failure\n"); + return NULL; } -uint16_t nr_polar_aggregation_prime (uint8_t aggregation_level) -{ - if (aggregation_level == 0) return 0; - else if (aggregation_level == 1) return NR_POLAR_AGGREGATION_LEVEL_1_PRIME; - else if (aggregation_level == 2) return NR_POLAR_AGGREGATION_LEVEL_2_PRIME; - else if (aggregation_level == 4) return NR_POLAR_AGGREGATION_LEVEL_4_PRIME; - else if (aggregation_level == 8) return NR_POLAR_AGGREGATION_LEVEL_8_PRIME; - else return NR_POLAR_AGGREGATION_LEVEL_16_PRIME; //aggregation_level == 16 +uint16_t nr_polar_aggregation_prime (uint8_t aggregation_level) { + if (aggregation_level == 0) return 0; + else if (aggregation_level == 1) return NR_POLAR_AGGREGATION_LEVEL_1_PRIME; + else if (aggregation_level == 2) return NR_POLAR_AGGREGATION_LEVEL_2_PRIME; + else if (aggregation_level == 4) return NR_POLAR_AGGREGATION_LEVEL_4_PRIME; + else if (aggregation_level == 8) return NR_POLAR_AGGREGATION_LEVEL_8_PRIME; + else return NR_POLAR_AGGREGATION_LEVEL_16_PRIME; //aggregation_level == 16 } diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index f71535f654..0954939a58 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -183,6 +183,7 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, #endif } + if (rvidx !=0){ while(k>3)) { @@ -153,10 +154,11 @@ else s++; } - if (*F>0) - for (k=Kprime>>3; k<(*K)>>3; k++) { - output_buffers[r][k] = NR_NULL; + if (*F>0) { + for (k=Kprime>>3; k<(*K)>>3; k++) { + output_buffers[r][k] = 0; //printf("r %d filler bits [%d] = %d Kprime %d \n", r,k, output_buffers[r][k], Kprime); + } } if (*C > 1) { // add CRC @@ -165,12 +167,10 @@ else output_buffers[r][1+((Kprime-L)>>3)] = ((uint8_t*)&crc)[1]; output_buffers[r][2+((Kprime-L)>>3)] = ((uint8_t*)&crc)[0]; } - - k=0; } } - return(0); + return 0; } diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 1866eac96d..ef555c0f20 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -33,7 +33,8 @@ #include "assertions.h" #include -#include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_TRANSPORT/nr_ulsch.h" +#include "PHY/NR_REFSIG/nr_refsig.h" #include "PHY/LTE_REFSIG/lte_refsig.h" #include "SCHED_NR/fapi_nr_l1.h" @@ -41,104 +42,87 @@ extern uint32_t from_nrarfcn(int nr_bandP,uint32_t dl_nrarfcn); extern int32_t get_uldl_offset(int nr_bandP); int l1_north_init_gNB() { - int i,j; - if (RC.nb_nr_L1_inst > 0 && RC.nb_nr_L1_CC != NULL && RC.gNB != NULL) - { + if (RC.nb_nr_L1_inst > 0 && RC.nb_nr_L1_CC != NULL && RC.gNB != NULL) { AssertFatal(RC.nb_nr_L1_inst>0,"nb_nr_L1_inst=%d\n",RC.nb_nr_L1_inst); AssertFatal(RC.nb_nr_L1_CC!=NULL,"nb_nr_L1_CC is null\n"); AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n"); - LOG_I(PHY,"%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst); - for (i=0;i0,"RC.nb_nr_L1_CC[%d]=%d\n",i,RC.nb_nr_L1_CC[i]); - LOG_I(PHY,"%s() RC.nb_nr_L1_CC[%d]:%d\n", __FUNCTION__, i, RC.nb_nr_L1_CC[i]); - for (j=0;jif_inst = NR_IF_Module_init(i))<0) return(-1); + if ((RC.gNB[i][j]->if_inst = NR_IF_Module_init(i))<0) return(-1); LOG_I(PHY,"%s() RC.gNB[%d][%d] installing callbacks\n", __FUNCTION__, i, j); - RC.gNB[i][j]->if_inst->NR_PHY_config_req = nr_phy_config_request; RC.gNB[i][j]->if_inst->NR_Schedule_response = nr_schedule_response; } } - } - else - { + } else { LOG_I(PHY,"%s() Not installing PHY callbacks - RC.nb_nr_L1_inst:%d RC.nb_nr_L1_CC:%p RC.gNB:%p\n", __FUNCTION__, RC.nb_nr_L1_inst, RC.nb_nr_L1_CC, RC.gNB); } + return(0); } int phy_init_nr_gNB(PHY_VARS_gNB *gNB, - unsigned char is_secondary_gNB, - unsigned char abstraction_flag) -{ - + unsigned char is_secondary_gNB, + unsigned char abstraction_flag) { // shortcuts - 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; - LTE_eNB_PRACH* const prach_vars = &gNB->prach_vars; + 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; + LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars; - int i, UE_id; + int i, UE_id; LOG_I(PHY,"[gNB %d] %s() About to wait for gNB to be configured\n", gNB->Mod_id, __FUNCTION__); - gNB->total_dlsch_bitrate = 0; gNB->total_transmitted_bits = 0; gNB->total_system_throughput = 0; gNB->check_for_MUMIMO_transmissions=0; - + while(gNB->configured == 0) usleep(10000); init_dfts(); -/* - LOG_I(PHY,"[gNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d nb_antennas_tx:%u nb_antennas_rx:%u PRACH[rootSequenceIndex:%u prach_Config_enabled:%u configIndex:%u highSpeed:%u zeroCorrelationZoneConfig:%u freqOffset:%u]\n", - gNB->Mod_id, - fp->N_RB_DL,fp->phich_config_common.phich_resource, - fp->phich_config_common.phich_duration, - fp->nb_antennas_tx, fp->nb_antennas_rx, - fp->prach_config_common.rootSequenceIndex, - fp->prach_config_common.prach_Config_enabled, - fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - fp->prach_config_common.prach_ConfigInfo.highSpeedFlag, - fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset - );*/ + /* + LOG_I(PHY,"[gNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d nb_antennas_tx:%u nb_antennas_rx:%u PRACH[rootSequenceIndex:%u prach_Config_enabled:%u configIndex:%u highSpeed:%u zeroCorrelationZoneConfig:%u freqOffset:%u]\n", + gNB->Mod_id, + fp->N_RB_DL,fp->phich_config_common.phich_resource, + fp->phich_config_common.phich_duration, + fp->nb_antennas_tx, fp->nb_antennas_rx, + fp->prach_config_common.rootSequenceIndex, + fp->prach_config_common.prach_Config_enabled, + fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, + fp->prach_config_common.prach_ConfigInfo.highSpeedFlag, + fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, + fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset + );*/ LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_gNB][MOD %02"PRIu8"][]\n", gNB->Mod_id); - crcTableInit(); - init_dfts(); - // PBCH DMRS gold sequences generation nr_init_pbch_dmrs(gNB); - // Polar encoder init for PBCH - - nr_polar_init(&gNB->nrPolar_params, - NR_POLAR_PBCH_MESSAGE_TYPE, - NR_POLAR_PBCH_PAYLOAD_BITS, - NR_POLAR_PBCH_AGGREGATION_LEVEL); - //PDCCH DMRS init - gNB->nr_gold_pdcch_dmrs = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t**)); + gNB->nr_gold_pdcch_dmrs = (uint32_t ***)malloc16(fp->slots_per_frame*sizeof(uint32_t **)); uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs; AssertFatal(pdcch_dmrs!=NULL, "NR init: pdcch_dmrs malloc failed\n"); + for (int slot=0; slotslots_per_frame; slot++) { - pdcch_dmrs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t*)); + pdcch_dmrs[slot] = (uint32_t **)malloc16(fp->symbols_per_slot*sizeof(uint32_t *)); AssertFatal(pdcch_dmrs[slot]!=NULL, "NR init: pdcch_dmrs for slot %d - malloc failed\n", slot); - for (int symb=0; symbsymbols_per_slot; symb++){ + + for (int symb=0; symbsymbols_per_slot; symb++) { pdcch_dmrs[slot][symb] = (uint32_t *)malloc16(NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD*sizeof(uint32_t)); AssertFatal(pdcch_dmrs[slot][symb]!=NULL, "NR init: pdcch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb); } @@ -146,127 +130,117 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, nr_init_pdcch_dmrs(gNB, cfg->sch_config.physical_cell_id.value); nr_init_pbch_interleaver(gNB->nr_pbch_interleaver); + //PDSCH DMRS init + gNB->nr_gold_pdsch_dmrs = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t ***)); + uint32_t ****pdsch_dmrs = gNB->nr_gold_pdsch_dmrs; - - //PDSCH DMRS init - gNB->nr_gold_pdsch_dmrs = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t***)); - uint32_t ****pdsch_dmrs = gNB->nr_gold_pdsch_dmrs; - for (int slot=0; slotslots_per_frame; slot++) { - pdsch_dmrs[slot] = (uint32_t ***)malloc16(fp->symbols_per_slot*sizeof(uint32_t**)); + for (int slot=0; slotslots_per_frame; slot++) { + pdsch_dmrs[slot] = (uint32_t ***)malloc16(fp->symbols_per_slot*sizeof(uint32_t **)); AssertFatal(pdsch_dmrs[slot]!=NULL, "NR init: pdsch_dmrs for slot %d - malloc failed\n", slot); - for (int symb=0; symbsymbols_per_slot; symb++){ - pdsch_dmrs[slot][symb] = (uint32_t **)malloc16(NR_MAX_NB_CODEWORDS*sizeof(uint32_t*)); + + for (int symb=0; symbsymbols_per_slot; symb++) { + pdsch_dmrs[slot][symb] = (uint32_t **)malloc16(NR_MAX_NB_CODEWORDS*sizeof(uint32_t *)); AssertFatal(pdsch_dmrs[slot][symb]!=NULL, "NR init: pdsch_dmrs for slot %d symbol %d - malloc failed\n", slot, symb); + for (int q=0; qsch_config.physical_cell_id.value); + + nr_init_pdsch_dmrs(gNB, cfg->sch_config.physical_cell_id.value); + /// Transport init necessary for NR synchro init_nr_transport(gNB); - -/* - lte_gold(fp,gNB->lte_gold_table,fp->Nid_cell); - generate_pcfich_reg_mapping(fp); - generate_phich_reg_mapping(fp);*/ + + /* + lte_gold(fp,gNB->lte_gold_table,fp->Nid_cell); + generate_pcfich_reg_mapping(fp); + generate_phich_reg_mapping(fp);*/ for (UE_id=0; UE_idfirst_run_timing_advance[UE_id] = 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. - // clear whole structure bzero( &gNB->UE_stats[UE_id], sizeof(LTE_eNB_UE_stats) ); - gNB->physicalConfigDedicated[UE_id] = NULL; } - - 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. - + 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->txdataF = (int32_t **)malloc16(15*sizeof(int32_t*)); common_vars->rxdataF = (int32_t **)malloc16(64*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) ); - + + 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 + LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n", - i,common_vars->txdataF[i], - fp->samples_per_frame_wCP*sizeof(int32_t)); + i,common_vars->txdataF[i], + fp->samples_per_frame_wCP*sizeof(int32_t)); } - - + // Channel estimates for SRS for (UE_id=0; UE_idofdm_symbol_size ); - srs_vars[UE_id].srs_ch_estimates_time[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); + srs_vars[UE_id].srs_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size ); + srs_vars[UE_id].srs_ch_estimates_time[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); } } //UE_id - /*generate_ul_ref_sigs_rx(); - + init_ulsch_power_LUT();*/ // SRS for (UE_id=0; UE_idofdm_symbol_size*sizeof(int32_t)); + srs_vars[UE_id].srs = (int32_t *)malloc16_clear(2*fp->ofdm_symbol_size*sizeof(int32_t)); } // PRACH - prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) ); - + prach_vars->prachF = (int16_t *)malloc16_clear( 1024*2*sizeof(int16_t) ); // assume maximum of 64 RX antennas for PRACH receiver - prach_vars->prach_ifft[0] = (int32_t**)malloc16_clear(64*sizeof(int32_t*)); - for (i=0;i<64;i++) prach_vars->prach_ifft[0][i] = (int32_t*)malloc16_clear(1024*2*sizeof(int32_t)); + prach_vars->prach_ifft[0] = (int32_t **)malloc16_clear(64*sizeof(int32_t *)); - prach_vars->rxsigF[0] = (int16_t**)malloc16_clear(64*sizeof(int16_t*)); + for (i=0; i<64; i++) prach_vars->prach_ifft[0][i] = (int32_t *)malloc16_clear(1024*2*sizeof(int32_t)); + + prach_vars->rxsigF[0] = (int16_t **)malloc16_clear(64*sizeof(int16_t *)); for (UE_id=0; UE_idrxdataF_ext = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_ext2 = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->drs_ch_estimates_time = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->rxdataF_comp = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_mag = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - pusch_vars[UE_id]->ul_ch_magb = (int32_t**)malloc16( 2*sizeof(int32_t*) ); - + pusch_vars[UE_id] = (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 *) ); + 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[UE_id]->llr = (int16_t*)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); + pusch_vars[UE_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->drs_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->drs_ch_estimates_time[i] = (int32_t *)malloc16_clear( 2*sizeof(int32_t)*fp->ofdm_symbol_size ); + pusch_vars[UE_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12*fp->symbols_per_slot ); + pusch_vars[UE_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 ); + pusch_vars[UE_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*cfg->rf_config.ul_carrier_bandwidth.value*12 ); + } + + pusch_vars[UE_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); } //UE_id - for (UE_id=0; UE_idUE_stats_ptr[UE_id] = &gNB->UE_stats[UE_id]; - + gNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration - - return (0); - } /* void phy_config_request(PHY_Config_t *phy_config) { @@ -277,7 +251,7 @@ void phy_config_request(PHY_Config_t *phy_config) { NR_DL_FRAME_PARMS *fp; PHICH_RESOURCE_t phich_resource_table[4]={oneSixth,half,one,two}; - int eutra_band = cfg->nfapi_config.rf_bands.rf_band[0]; + int eutra_band = cfg->nfapi_config.rf_bands.rf_band[0]; int dl_Bandwidth = cfg->rf_config.dl_carrier_bandwidth.value; int ul_Bandwidth = cfg->rf_config.ul_carrier_bandwidth.value; int Nid_cell = cfg->sch_config.physical_cell_id.value; @@ -286,7 +260,7 @@ void phy_config_request(PHY_Config_t *phy_config) { uint32_t dl_CarrierFreq = cfg->nfapi_config.earfcn.value; LOG_I(PHY,"Configuring MIB for instance %d, CCid %d : (band %d,N_RB_DL %d, N_RB_UL %d, Nid_cell %d,gNB_tx_antenna_ports %d,Ncp %d,DL freq %u)\n", - Mod_id, CC_id, eutra_band, dl_Bandwidth, ul_Bandwidth, Nid_cell, p_eNB,Ncp,dl_CarrierFreq ); + Mod_id, CC_id, eutra_band, dl_Bandwidth, ul_Bandwidth, Nid_cell, p_eNB,Ncp,dl_CarrierFreq ); AssertFatal(RC.gNB != NULL, "PHY instance pointer doesn't exist\n"); AssertFatal(RC.gNB[Mod_id] != NULL, "PHY instance %d doesn't exist\n",Mod_id); @@ -312,25 +286,23 @@ void phy_config_request(PHY_Config_t *phy_config) { }*/ -void phy_free_nr_gNB(PHY_VARS_gNB *gNB) -{ +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; - LTE_eNB_PRACH* const prach_vars = &gNB->prach_vars; + 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; + LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars; uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs; - int i, UE_id; for (i = 0; i < 15; i++) { free_and_zero(common_vars->txdataF[i]); - /* rxdataF[i] is not allocated -> don't free */ + /* rxdataF[i] is not allocated -> don't free */ } + free_and_zero(common_vars->txdataF); free_and_zero(common_vars->rxdataF); - // PDCCH DMRS sequences free_and_zero(pdcch_dmrs); @@ -340,6 +312,7 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(srs_vars[UE_id].srs_ch_estimates[i]); free_and_zero(srs_vars[UE_id].srs_ch_estimates_time[i]); } + free_and_zero(srs_vars[UE_id].srs_ch_estimates); free_and_zero(srs_vars[UE_id].srs_ch_estimates_time); } //UE_id @@ -351,8 +324,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(prach_vars->prachF); for (i = 0; i < 64; i++) free_and_zero(prach_vars->prach_ifft[0][i]); - free_and_zero(prach_vars->prach_ifft[0]); + free_and_zero(prach_vars->prach_ifft[0]); free_and_zero(prach_vars->rxsigF[0]); for (UE_id=0; UE_idul_ch_mag[i]); free_and_zero(pusch_vars[UE_id]->ul_ch_magb[i]); } + free_and_zero(pusch_vars[UE_id]->rxdataF_ext); free_and_zero(pusch_vars[UE_id]->rxdataF_ext2); free_and_zero(pusch_vars[UE_id]->drs_ch_estimates); @@ -387,11 +361,11 @@ void install_schedule_handlers(IF_Module_t *if_inst) /// this function is a temporary addition for NR configuration -void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,int N_RB_DL,int N_RB_UL,int mu,int Nid_cell) -{ + +void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,int N_RB_DL,int N_RB_UL,int mu,int Nid_cell,uint64_t position_in_burst) { + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_t *gNB_config = &gNB->gNB_config; - //overwrite for new NR parameters gNB_config->nfapi_config.rf_bands.rf_band[0] = 78; gNB_config->nfapi_config.nrarfcn.value = 620000; @@ -404,31 +378,25 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,int N_RB_DL,int N_RB_UL,int mu, gNB_config->sch_config.n_ssb_crb.value = (N_RB_DL-20); gNB_config->sch_config.ssb_subcarrier_offset.value = 0; gNB_config->sch_config.physical_cell_id.value=Nid_cell; - + gNB_config->sch_config.ssb_scg_position_in_burst.value=position_in_burst; + gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED; gNB->mac_enabled = 1; - - fp->dl_CarrierFreq = from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); fp->threequarter_fs = 0; - nr_init_frame_parms(gNB_config, fp); - gNB->configured = 1; LOG_I(PHY,"gNB configured\n"); + } -void nr_phy_config_request(NR_PHY_Config_t *phy_config) -{ - +void nr_phy_config_request(NR_PHY_Config_t *phy_config) { uint8_t Mod_id = phy_config->Mod_id; int CC_id = phy_config->CC_id; - NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id][CC_id]->frame_parms; nfapi_nr_config_request_t *gNB_config = &RC.gNB[Mod_id][CC_id]->gNB_config; - - gNB_config->nfapi_config.rf_bands.rf_band[0] = phy_config->cfg->nfapi_config.rf_bands.rf_band[0]; //22 gNB_config->nfapi_config.nrarfcn.value = phy_config->cfg->nfapi_config.nrarfcn.value; //6600 gNB_config->subframe_config.numerology_index_mu.value = phy_config->cfg->subframe_config.numerology_index_mu.value;//1 @@ -438,105 +406,102 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) gNB_config->sch_config.ssb_subcarrier_offset.value = phy_config->cfg->sch_config.ssb_subcarrier_offset.value;//0; gNB_config->sch_config.n_ssb_crb.value = (phy_config->cfg->rf_config.dl_carrier_bandwidth.value-20); gNB_config->sch_config.physical_cell_id.value = phy_config->cfg->sch_config.physical_cell_id.value; + gNB_config->sch_config.ssb_scg_position_in_burst.value= phy_config->cfg->sch_config.ssb_scg_position_in_burst.value; if (phy_config->cfg->subframe_config.duplex_mode.value == 0) { gNB_config->subframe_config.duplex_mode.value = TDD; - } - else { + } else { gNB_config->subframe_config.duplex_mode.value = FDD; } RC.gNB[Mod_id][CC_id]->mac_enabled = 1; - fp->dl_CarrierFreq = from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); fp->ul_CarrierFreq = fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); fp->threequarter_fs = 0; - LOG_I(PHY,"Configuring MIB for instance %d, CCid %d : (band %d,N_RB_DL %d, N_RB_UL %d, Nid_cell %d,DL freq %u)\n", - Mod_id, - CC_id, - gNB_config->nfapi_config.rf_bands.rf_band[0], - gNB_config->rf_config.dl_carrier_bandwidth.value, - gNB_config->rf_config.ul_carrier_bandwidth.value, - gNB_config->sch_config.physical_cell_id.value, - fp->dl_CarrierFreq ); - + Mod_id, + CC_id, + gNB_config->nfapi_config.rf_bands.rf_band[0], + gNB_config->rf_config.dl_carrier_bandwidth.value, + gNB_config->rf_config.ul_carrier_bandwidth.value, + gNB_config->sch_config.physical_cell_id.value, + fp->dl_CarrierFreq ); + nr_init_frame_parms(gNB_config, fp); - if (RC.gNB[Mod_id][CC_id]->configured == 1){ + if (RC.gNB[Mod_id][CC_id]->configured == 1) { LOG_E(PHY,"Already gNB already configured, do nothing\n"); return; } RC.gNB[Mod_id][CC_id]->configured = 1; LOG_I(PHY,"gNB %d/%d configured\n",Mod_id,CC_id); - - - } void init_nr_transport(PHY_VARS_gNB *gNB) { - int i; int j; NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_t *cfg = &gNB->gNB_config; - LOG_I(PHY, "Initialise nr transport\n"); for (i=0; idlsch[i][j] = new_gNB_dlsch(1,16,NSOFT,0,fp,cfg); + if (!gNB->dlsch[i][j]) { - LOG_E(PHY,"Can't get gNB dlsch structures for UE %d \n", i); - exit(-1); + LOG_E(PHY,"Can't get gNB dlsch structures for UE %d \n", i); + exit(-1); }/* else { - 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); + gNB->dlsch[i][j]->rnti=0; + LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,gNB->dlsch[i][j], gNB->dlsch[i][j]->rnti); }*/ + + ///////////////////////// Initializing gNB ULSCH ///////////////////////// + LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); + + // ULSCH for RA + if(i==0) { + gNB->ulsch[i][j] = new_gNB_ulsch(5, fp->N_RB_UL, 0); + + if (!gNB->ulsch[i][j]) { + LOG_E(PHY,"Can't get gNB ulsch structures\n"); + exit(-1); + } + } + + // ULSCH for data + gNB->ulsch[i+1][j] = new_gNB_ulsch(5, fp->N_RB_UL, 0); + + if (!gNB->ulsch[i+1][j]) { + LOG_E(PHY,"Can't get gNB ulsch structures\n"); + exit(-1); + } + ////////////////////////////////////////////////////////////////////////// } - - //LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); - //gNB->ulsch[1+i] = new_gNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0); - - /*if (!gNB->ulsch[1+i]) { - LOG_E(PHY,"Can't get gNB ulsch structures\n"); - exit(-1); - }*/ - + // this is the transmission mode for the signalling channels // this will be overwritten with the real transmission mode by the RRC once the UE is connected //gNB->transmission_mode[i] = fp->nb_antenna_ports_gNB==1 ? 1 : 2; } - // ULSCH for RA - //gNB->ulsch[0] = new_gNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0); - - /*if (!gNB->ulsch[0]) { - LOG_E(PHY,"Can't get gNB ulsch structures\n"); - exit(-1); - }*/ + gNB->dlsch_SI = new_gNB_dlsch(1,8,NSOFT, 0, fp, cfg); LOG_D(PHY,"gNB %d.%d : SI %p\n",gNB->Mod_id,gNB->CC_id,gNB->dlsch_SI); gNB->dlsch_ra = new_gNB_dlsch(1,8,NSOFT, 0, fp, cfg); LOG_D(PHY,"gNB %d.%d : RA %p\n",gNB->Mod_id,gNB->CC_id,gNB->dlsch_ra); gNB->dlsch_MCH = new_gNB_dlsch(1,8,NSOFT, 0, fp, cfg); LOG_D(PHY,"gNB %d.%d : MCH %p\n",gNB->Mod_id,gNB->CC_id,gNB->dlsch_MCH); - - gNB->rx_total_gain_dB=130; - + for(i=0; imu_mimo_mode[i].dl_pow_off = 2; - + gNB->check_for_total_transmissions = 0; - gNB->check_for_MUMIMO_transmissions = 0; - gNB->FULL_MUMIMO_transmissions = 0; - gNB->check_for_SUMIMO_transmissions = 0; - //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 fc207cee84..986d423034 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -361,8 +361,13 @@ void phy_config_harq_ue(module_id_t Mod_id,int CC_id,uint8_t eNB_id, uint16_t max_harq_tx ) { + int num_of_threads,num_of_code_words; + PHY_VARS_NR_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; - phy_vars_ue->ulsch[eNB_id]->Mlimit = max_harq_tx; + + for (num_of_threads=0;num_of_threadsulsch[eNB_id][num_of_threads][num_of_code_words]->Mlimit = max_harq_tx; } extern uint16_t beta_cqi[16]; @@ -670,7 +675,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, // many memory allocation sizes are hard coded AssertFatal( fp->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[eNB_id]" ); - AssertFatal( ue->n_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" ); + AssertFatal( nb_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" ); // init phy_vars_ue for (i=0; i<4; i++) { @@ -919,15 +924,15 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue,int abstraction_flag) { for (i=0; idlsch[k][i][j] = new_nr_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag))!=NULL,"Can't get ue dlsch structures\n"); + for (k=0; kdlsch[k][i][j] = new_nr_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag))!=NULL,"Can't get ue dlsch structures\n"); + LOG_D(PHY,"dlsch[%d][%d][%d] => %p\n",k,i,j,ue->dlsch[k][i][j]); - LOG_D(PHY,"dlsch[%d][%d][%d] => %p\n",k,i,j,ue->dlsch[i][j]); + AssertFatal((ue->ulsch[k][i][j] = new_nr_ue_ulsch(ue->frame_parms.N_RB_UL, NUMBER_OF_HARQ_PID_MAX, abstraction_flag))!=NULL,"Can't get ue ulsch structures\n"); + LOG_D(PHY,"ulsch[%d][%d][%d] => %p\n",k,i,j,ue->ulsch[k][i][j]); } } - //AssertFatal((ue->ulsch[i] = new_ue_ulsch(ue->frame_parms.N_RB_UL, abstraction_flag))!=NULL,"Can't get ue ulsch structures\n"); - ue->dlsch_SI[i] = new_nr_ue_dlsch(1,1,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag); ue->dlsch_ra[i] = new_nr_ue_dlsch(1,1,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index f37883b388..a828804002 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -27,6 +27,59 @@ uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, uint16_t nr_slots_per_subframe[MAX_NUM_SUBCARRIER_SPACING] = {1, 2, 4, 16, 32}; +int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp, uint8_t i_ssb, uint8_t half_frame_index) +{ + + int mu = fp->numerology_index; + int symbol = 0; + uint8_t n, n_temp; + nr_ssb_type_e type = fp->ssb_type; + int case_AC[2] = {2,8}; + int case_BD[4] = {4,8,16,20}; + int case_E[8] = {8, 12, 16, 20, 32, 36, 40, 44}; + + switch(mu) { + + case NR_MU_0: // case A + n = i_ssb >> 1; + symbol = case_AC[i_ssb % 2] + 14*n; + break; + + case NR_MU_1: + if (type == 1){ // case B + n = i_ssb >> 2; + symbol = case_BD[i_ssb % 4] + 28*n; + } + if (type == 2){ // case C + n = i_ssb >> 1; + symbol = case_AC[i_ssb % 2] + 14*n; + } + break; + + case NR_MU_3: // case D + n_temp = i_ssb >> 2; + n = n_temp + (n_temp >> 2); + symbol = case_BD[i_ssb % 4] + 28*n; + break; + + case NR_MU_4: // case E + n_temp = i_ssb >> 3; + n = n_temp + (n_temp >> 2); + symbol = case_E[i_ssb % 8] + 56*n; + break; + + + default: + AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu); + } + + if (half_frame_index) + symbol += (5 * fp->symbols_per_slot * fp->slots_per_subframe); + + return symbol; +} + + int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, int mu, int Ncp, @@ -46,18 +99,29 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, fp->numerology_index = mu; fp->Ncp = Ncp; fp->N_RB_DL = N_RB_DL; - + switch(mu) { case NR_MU_0: //15kHz scs fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_0]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_0]; + fp->ssb_type = nr_ssb_type_A; break; case NR_MU_1: //30kHz scs fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_1]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_1]; + // selection of SS block pattern according to TS 38101-1 Table 5.4.3.3-1 for SCS 30kHz + if (fp->eutra_band == 5 || fp->eutra_band == 66) + fp->ssb_type = nr_ssb_type_B; + else{ + if (fp->eutra_band == 41 || ( fp->eutra_band > 76 && fp->eutra_band < 80) ) + fp->ssb_type = nr_ssb_type_C; + else + AssertFatal(1==0,"NR Operating Band n%d not available for SS block SCS with mu=%d\n", fp->eutra_band, mu); + } + switch(N_RB_DL){ case 11: case 24: @@ -144,11 +208,13 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, case NR_MU_3: fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_3]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_3]; + fp->ssb_type = nr_ssb_type_D; break; case NR_MU_4: fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_4]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_4]; + fp->ssb_type = nr_ssb_type_E; break; default: @@ -156,6 +222,9 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, } fp->slots_per_frame = 10* fp->slots_per_subframe; + + fp->nb_antenna_ports_eNB = 1; // default value until overwritten by RRCConnectionReconfiguration + fp->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP; @@ -166,6 +235,16 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp, fp->samples_per_frame = 10 * fp->samples_per_subframe; fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; + // definition of Lmax according to ts 38.213 section 4.1 + if (fp->dl_CarrierFreq < 6e9){ + if(fp->frame_type && (fp->ssb_type==2)) + fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8; + else + fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8; + } + else + fp->Lmax = 64; + // Initial bandwidth part configuration -- full carrier bandwidth fp->initial_bwp_dl.bwp_id = 0; fp->initial_bwp_dl.scs = fp->subcarrier_spacing; @@ -181,7 +260,9 @@ int nr_init_frame_parms(nfapi_nr_config_request_t* config, NR_DL_FRAME_PARMS *fp) { - + fp->eutra_band = config->nfapi_config.rf_bands.rf_band[0]; + fp->frame_type = !(config->subframe_config.duplex_mode.value); + fp->L_ssb = config->sch_config.ssb_scg_position_in_burst.value; return nr_init_frame_parms0(fp, config->subframe_config.numerology_index_mu.value, config->subframe_config.dl_cyclic_prefix_type.value, @@ -219,3 +300,6 @@ void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp) LOG_I(PHY,"fp->initial_bwp_dl.location=%d\n",fp->initial_bwp_dl.location); LOG_I(PHY,"fp->initial_bwp_dl.ofdm_symbol_size=%d\n",fp->initial_bwp_dl.ofdm_symbol_size); } + + + diff --git a/openair1/PHY/INIT/phy_init.h b/openair1/PHY/INIT/phy_init.h index 2a7dcf88fd..6f9cff07bf 100644 --- a/openair1/PHY/INIT/phy_init.h +++ b/openair1/PHY/INIT/phy_init.h @@ -376,6 +376,7 @@ void phy_config_request(PHY_Config_t *phy_config); int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf); void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms); +int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp, uint8_t i_ssb, uint8_t half_frame_index); int nr_init_frame_parms(nfapi_nr_config_request_t* config, NR_DL_FRAME_PARMS *frame_parms); int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms,int mu,int Ncp,int N_RB_DL,int n_ssb_crb,int ssb_subcarrier_offset); int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB,uint8_t abstraction_flag); @@ -383,13 +384,14 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue,int abstraction_flag); void nr_dump_frame_parms(NR_DL_FRAME_PARMS *frame_parms); int phy_init_nr_gNB(PHY_VARS_gNB *gNB, unsigned char is_secondary_gNB, unsigned char abstraction_flag); void nr_phy_config_request(NR_PHY_Config_t *gNB); -void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,int N_RB_DL,int N_RB_UL,int mu,int Nid_cell); +void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,int N_RB_DL,int N_RB_UL,int mu,int Nid_cell,uint64_t position_in_burst); void phy_free_nr_gNB(PHY_VARS_gNB *gNB); int l1_north_init_gNB(void); void init_nr_transport(PHY_VARS_gNB *gNB); void init_dfts(void); + /** @} */ #endif diff --git a/openair1/PHY/MODULATION/modulation_UE.h b/openair1/PHY/MODULATION/modulation_UE.h index 9734c02907..63c3637886 100644 --- a/openair1/PHY/MODULATION/modulation_UE.h +++ b/openair1/PHY/MODULATION/modulation_UE.h @@ -53,8 +53,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *phy_vars_ue, unsigned char Ns, int sample_offset, int no_prefix, - int reset_freq_est, - NR_CHANNEL_EST_t channel); + NR_CHANNEL_EST_t channel); int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, unsigned char l, diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 8ef29d016d..6ce486e3a0 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -39,28 +39,40 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, unsigned char Ns, int sample_offset, int no_prefix, - int reset_freq_est, NR_CHANNEL_EST_t channel) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; NR_UE_COMMON *common_vars = &ue->common_vars; - uint8_t eNB_id = 0;//ue_common_vars->eNb_id; unsigned char aa; unsigned char symbol = l;//+((7-frame_parms->Ncp)*(Ns&1)); ///symbol within sub-frame - 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); + unsigned int nb_prefix_samples; + unsigned int nb_prefix_samples0; + if (ue->is_synchronized) { + nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); + nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + } + else { + nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); + nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples); + } //unsigned int subframe_offset;//,subframe_offset_F; unsigned int slot_offset; //int i; unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10; unsigned int rx_offset; - NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[Ns>>1]][0]; - uint16_t coreset_start_subcarrier = frame_parms->first_carrier_offset+((int)floor(frame_parms->ssb_start_subcarrier/NR_NB_SC_PER_RB)+pdcch_vars->coreset[0].rb_offset)*NR_NB_SC_PER_RB; - uint16_t nb_rb_coreset = 24; - uint16_t bwp_start_subcarrier = frame_parms->first_carrier_offset+516; + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[Ns]][0]; + uint16_t coreset_start_subcarrier = frame_parms->first_carrier_offset;//+((int)floor(frame_parms->ssb_start_subcarrier/NR_NB_SC_PER_RB)+pdcch_vars->coreset[0].rb_offset)*NR_NB_SC_PER_RB; + uint16_t nb_rb_coreset = 0; + uint16_t bwp_start_subcarrier = frame_parms->first_carrier_offset;//+516; uint16_t nb_rb_pdsch = 50; uint8_t p=0; - uint8_t l0 = 2; + uint8_t l0 = pdcch_vars->coreset[0].duration; + uint64_t coreset_freq_dom = pdcch_vars->coreset[0].frequencyDomainResources; + for (int i = 0; i < 45; i++) { + if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) nb_rb_coreset++; + } + nb_rb_coreset = 6 * nb_rb_coreset; + //printf("corset duration %d nb_rb_coreset %d\n", l0, nb_rb_coreset); void (*dft)(int16_t *,int16_t *, int); int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs @@ -104,9 +116,9 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, } if (no_prefix) { - slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot*frame_parms->slots_per_subframe) * (Ns>>1); + slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns); } else { - slot_offset = (frame_parms->samples_per_subframe) * (Ns>>1); + slot_offset = (frame_parms->samples_per_slot) * (Ns); } /*if (l<0 || l>=7-frame_parms->Ncp) { @@ -122,7 +134,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, for (aa=0; aanb_antennas_rx; aa++) { - memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); + memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); rx_offset = sample_offset + slot_offset + nb_prefix_samples0 - SOFFSET; // Align with 256 bit @@ -130,8 +142,8 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, #ifdef DEBUG_FEP // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol, - nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples); + /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns)&1].frame_rx,Ns, symbol, + nb_prefix_samples,nb_prefix_samples0,slot_offset,sample_offset,rx_offset,frame_length_samples); #endif if (l==0) { @@ -146,14 +158,14 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, (void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); dft((int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); #endif @@ -175,11 +187,11 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, (void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); dft((int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); + (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); @@ -198,56 +210,17 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, switch(channel){ case NR_PBCH_EST: - -#ifdef DEBUG_FEP - printf("Channel estimation eNB %d, slot %d, symbol %d\n",eNB_id,Ns,l); -#endif -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_channel_estimation_stats); -#endif - nr_pbch_channel_estimation(ue,eNB_id,0, - Ns, - l, - symbol); - //} -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_channel_estimation_stats); -#endif - - // do frequency offset estimation here! - // use channel estimates from current symbol (=ch_t) and last symbol (ch_{t-1}) -#ifdef DEBUG_FEP - printf("Frequency offset estimation\n"); -#endif - - if (l==(4-frame_parms->Ncp)) { - -#if UE_TIMING_TRACE - start_meas(&ue->dlsch_freq_offset_estimation_stats); -#endif - - /*lte_est_freq_offset(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[0], - frame_parms, - l, - &common_vars->freq_offset, - reset_freq_est);*/ -#if UE_TIMING_TRACE - stop_meas(&ue->dlsch_freq_offset_estimation_stats); -#endif - - } - break; case NR_PDCCH_EST: #ifdef DEBUG_FEP - printf("PDCCH Channel estimation eNB %d, aatx %d, slot %d, symbol %d start_sc %d\n",eNB_id,aa,Ns,l,coreset_start_subcarrier); + printf("PDCCH Channel estimation aatx %d, slot %d, symbol %d start_sc %d\n",aa,Ns,l,coreset_start_subcarrier); #endif #if UE_TIMING_TRACE start_meas(&ue->dlsch_channel_estimation_stats); #endif - nr_pdcch_channel_estimation(ue,eNB_id,0, + nr_pdcch_channel_estimation(ue,0, Ns, l, symbol, @@ -261,7 +234,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, case NR_PDSCH_EST: #ifdef DEBUG_FEP - printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l); + printf("Channel estimation aatx %d, slot %d, symbol %d\n",aa,Ns,l); #endif #if UE_TIMING_TRACE start_meas(&ue->dlsch_channel_estimation_stats); @@ -270,7 +243,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, ue->frame_parms.nushift = (p>>1)&1;; if (symbol ==l0) - nr_pdsch_channel_estimation(ue,eNB_id,0, + nr_pdsch_channel_estimation(ue,0, Ns, p, l, diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 2e5ad47d91..e0c17bfb75 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -32,6 +32,7 @@ //#define NR_PBCH_DMRS_LENGTH_DWORD 5 //#define NR_PBCH_DMRS_LENGTH 144 +//#define DEBUG_PDCCH #include "refsig_defs_ue.h" #include "PHY/defs_nr_UE.h" diff --git a/openair1/PHY/NR_REFSIG/nr_gold.c b/openair1/PHY/NR_REFSIG/nr_gold.c index 968f7fa7a4..bd60933155 100644 --- a/openair1/PHY/NR_REFSIG/nr_gold.c +++ b/openair1/PHY/NR_REFSIG/nr_gold.c @@ -32,13 +32,13 @@ void nr_init_pbch_dmrs(PHY_VARS_gNB* gNB) Nid = cfg->sch_config.physical_cell_id.value; - Lmax = (fp->dl_CarrierFreq < 3e9)? 4:8; + Lmax = fp->Lmax; N_hf = (Lmax == 4)? 2:1; for (n_hf = 0; n_hf < N_hf; n_hf++) { for (l = 0; l < Lmax ; l++) { i_ssb = l & (Lmax-1); - i_ssb2 = (i_ssb<<2) + n_hf; + i_ssb2 = i_ssb + (n_hf<<2); reset = 1; x2 = (1<<11) * (i_ssb2 + 1) * ((Nid>>2) + 1) + (1<<6) * (i_ssb2 + 1) + (Nid&3); diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c index 3bb8745875..726aab8a37 100644 --- a/openair1/PHY/NR_REFSIG/nr_gold_ue.c +++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c @@ -29,15 +29,14 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue) unsigned char Lmax, l, n_hf, N_hf; Nid = ue->frame_parms.Nid_cell; - - Lmax = 8; //(fp->dl_CarrierFreq < 3e9)? 4:8; + Lmax = ue->frame_parms.Lmax; N_hf = (Lmax == 4)? 2:1; for (n_hf = 0; n_hf < N_hf; n_hf++) { for (l = 0; l < Lmax ; l++) { i_ssb = l & (Lmax-1); - i_ssb2 = (i_ssb<<2) + n_hf; + i_ssb2 = i_ssb + (n_hf<<2); x1 = 1 + (1<<31); x2 = (1<<11) * (i_ssb2 + 1) * ((Nid>>2) + 1) + (1<<6) * (i_ssb2 + 1) + (Nid&3); diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index 2f39f26ee4..dc20ab24d7 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -137,7 +137,9 @@ int set_pss_nr(int ofdm_symbol_size); int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change); int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id); + int fo_flag, + int *eNB_id, + int *f_off); #endif #undef EXTERN diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index bd2abebdf0..929ac823dd 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -20,7 +20,7 @@ */ /*! \file PHY/NR_TRANSPORT/nr_dci.c -* \brief Implements DCI encoding and PDCCH TX procedures (38.212/38.213/38.214). V15.2.0 2018-06. +* \brief Implements DCI encoding and PDCCH TX procedures (38.212/38.213/38.214). V15.4.0 2019-01. * \author Guy De Souza * \date 2018 * \version 0.1 @@ -35,20 +35,18 @@ //#define DEBUG_PDCCH_DMRS //#define DEBUG_DCI //#define DEBUG_CHANNEL_CODING -#define PDCCH_TEST_POLAR_TEMP_FIX 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, - nfapi_nr_config_request_t* config) -{ + nfapi_nr_rnti_type_e rnti_type, + uint16_t N_RB, + nfapi_nr_config_request_t *config) { uint16_t size = 0; switch(format) { -/*Only sizes for 0_0 and 1_0 are correct at the moment*/ + /*Only sizes for 0_0 and 1_0 are correct at the moment*/ case NFAPI_NR_UL_DCI_FORMAT_0_0: /// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20 size += 20; @@ -83,7 +81,6 @@ uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, /// fixed: Format identifier 1, VRB2PRB 1, MCS 5, NDI 1, RV 2, HARQ PID 4, DAI 2, PUCCH TPC 2, PUCCH RInd 3, PDSCH to HARQ TInd 3 Time Domain assgnmt 4 -- 28 size += 28; size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment - break; case NFAPI_NR_DL_DCI_FORMAT_1_1: @@ -96,7 +93,7 @@ uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, // PRB bundling size indicator // Rate matching indicator // ZP CSI-RS trigger - /// TB1- MCS 5, NDI 1, RV 2 + /// TB1- MCS 5, NDI 1, RV 2 size += 8; // TB2 size += 4 ; // HARQ PID @@ -110,7 +107,6 @@ uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, // CBGTI // CBGFI size += 1; // DMRS sequence init - break; case NFAPI_NR_DL_DCI_FORMAT_2_0: @@ -125,8 +121,8 @@ uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, case NFAPI_NR_DL_DCI_FORMAT_2_3: break; - default: - AssertFatal(1==0, "Invalid NR DCI format %d\n", format); + default: + AssertFatal(1==0, "Invalid NR DCI format %d\n", format); } return size; @@ -136,11 +132,9 @@ void nr_pdcch_scrambling(uint32_t *in, uint16_t size, uint32_t Nid, uint32_t n_RNTI, - uint32_t* out) { - + uint32_t *out) { uint8_t reset; uint32_t x1, x2, s=0; - reset = 1; x2 = (n_RNTI<<16) + Nid; @@ -148,193 +142,228 @@ void nr_pdcch_scrambling(uint32_t *in, if ((i&0x1f)==0) { s = lte_gold_generic(&x1, &x2, reset); reset = 0; - if (i){ - in++; - out++; + + if (i) { + in++; + out++; } } - (*out) ^= ((((*in)>>(i&0x1f))&1) ^ ((s>>(i&0x1f))&1))<<(i&0x1f); - // printf("nr_pdcch_scrambling: in %d => out %d\n",((*in)>>(i&0x1f))&1,((*out)>>(i&0x1f))&1); - } + (*out) ^= ((((*in)>>(i&0x1f))&1) ^ ((s>>(i&0x1f))&1))<<(i&0x1f); + //printf("nr_pdcch_scrambling: in %d seq 0x%08x => out %d\n",((*in)>>(i&0x1f))&1,s,((*out)>>(i&0x1f))&1); + } } uint8_t nr_generate_dci_top(NR_gNB_PDCCH pdcch_vars, - t_nrPolar_paramsPtr *nrPolar_params, uint32_t **gold_pdcch_dmrs, - int32_t* txdataF, + int32_t *txdataF, int16_t amp, NR_DL_FRAME_PARMS frame_parms, - nfapi_nr_config_request_t config) -{ - + nfapi_nr_config_request_t config) { int16_t mod_dmrs[NR_MAX_CSET_DURATION][NR_MAX_PDCCH_DMRS_LENGTH>>1]; // 3 for the max coreset duration - uint8_t idx=0; - //uint16_t a; + uint32_t dmrs_seq[NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD]; + uint16_t dmrs_offset=0; + uint16_t cset_start_sc; + uint8_t cset_start_symb, cset_nsymb; int k,l,k_prime,dci_idx, dmrs_idx; nr_cce_t cce; nr_reg_t reg; nr_reg_t reg_mapping_list[NR_MAX_PDCCH_AGG_LEVEL*NR_NB_REG_PER_CCE]; - /*First iteration: single DCI*/ NR_gNB_DCI_ALLOC_t dci_alloc = pdcch_vars.dci_alloc[0]; nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params = dci_alloc.pdcch_params; - uint16_t dmrs_length = dci_alloc.L*36; //2(QPSK)*3(per RB)*6(REG per CCE) - uint16_t encoded_length = dci_alloc.L*108; //2(QPSK)*9(per RB)*6(REG per CCE) /*The coreset is initialised - * in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset + * in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0 + * or the rb_offset for other coresets * in time: by its first slot and its first symbol*/ - uint16_t cset_start_sc = frame_parms.first_carrier_offset + ((int)floor(frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB)+pdcch_params.rb_offset)*NR_NB_SC_PER_RB; - // uint8_t cset_start_symb = pdcch_params.first_slot*frame_parms.symbols_per_slot + pdcch_params.first_symbol; - uint8_t cset_start_symb = pdcch_params.first_symbol; - uint8_t cset_nsymb = pdcch_params.n_symb; - dci_idx = 0; + if (pdcch_params.config_type == NFAPI_NR_CSET_CONFIG_MIB_SIB1) { + cset_start_sc = frame_parms.first_carrier_offset + (frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB + + pdcch_params.rb_offset)*NR_NB_SC_PER_RB; + } else + cset_start_sc = frame_parms.first_carrier_offset + pdcch_params.rb_offset*NR_NB_SC_PER_RB; + cset_start_symb = pdcch_params.first_symbol; + cset_nsymb = pdcch_params.n_symb; + dci_idx = 0; + LOG_I(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb); + // DMRS length is per OFDM symbol + uint16_t dmrs_length = (pdcch_params.precoder_granularity == NFAPI_NR_CSET_ALL_CONTIGUOUS_RBS)? + (pdcch_params.n_rb*6) : (dci_alloc.L*36/cset_nsymb); //2(QPSK)*3(per RB)*6(REG per CCE) + uint16_t encoded_length = dci_alloc.L*108; //2(QPSK)*9(per RB)*6(REG per CCE) + LOG_I(PHY, "DMRS length per symbol %d\t DCI encoded length %d\n", dmrs_length, encoded_length); /// DMRS QPSK modulation - /*There is a need to shift from which index the pregenerated DMRS sequence is used - * see 38211 r15.2.0 section 7.4.1.3.2: assumption is the reference point for k refers to the DMRS sequence*/ - if (pdcch_params.config_type == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - gold_pdcch_dmrs += ((int)floor(frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB)+pdcch_params.rb_offset)*3/32; + /*There is a need to shift from which index the pregenerated DMRS sequence is used + * see 38211 r15.2.0 section 7.4.1.3.2: assumption is the reference point for k refers to the DMRS sequence*/ + if (pdcch_params.config_type == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) { + for (int symb=cset_start_symb; symb>5; + + dmrs_offset = (pdcch_params.rb_offset*3)&0x1f; + LOG_I(PHY, "PDCCH DMRS offset %d\n", dmrs_offset); + } for (int symb=cset_start_symb; symb>1; i++) { - idx = ((((gold_pdcch_dmrs[symb][(i<<1)>>5])>>((i<<1)&0x1f))&1)<<1) ^ (((gold_pdcch_dmrs[symb][((i<<1)+1)>>5])>>(((i<<1)+1)&0x1f))&1); - mod_dmrs[symb][i<<1] = nr_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx)<<1]; - mod_dmrs[symb][(i<<1)+1] = nr_mod_table[((NR_MOD_TABLE_QPSK_OFFSET + idx)<<1) + 1]; - #ifdef DEBUG_PDCCH_DMRS - printf("symb %d i %d idx %d gold seq %u b0-b1 %d-%d mod_dmrs %d %d\n", symb, i, idx, gold_pdcch_dmrs[symb][(i<<1)>>5], - (((gold_pdcch_dmrs[symb][(i<<1)>>5])>>((i<<1)&0x1f))&1), (((gold_pdcch_dmrs[symb][((i<<1)+1)>>5])>>(((i<<1)+1)&0x1f))&1), - mod_dmrs[symb][(i<<1)], mod_dmrs[symb][(i<<1)+1]); - #endif - } + if (dmrs_offset) { + // a non zero offset requires the DMRS sequence to be rearranged + memset(dmrs_seq,0, NR_MAX_PDCCH_DMRS_INIT_LENGTH_DWORD*sizeof(uint32_t)); + + for (int i=0; i>5)] |= ((gold_pdcch_dmrs[symb][(i+dmrs_offset)>>5]>>((i+dmrs_offset)&0x1f))&1)<<(i&0x1f); +#ifdef DEBUG_PDCCH_DMRS + //printf("out 0x%08x in 0x%08x \n", dmrs_seq[(i>>5)], gold_pdcch_dmrs[symb][(i+dmrs_offset)>>5]); +#endif + } + + nr_modulation(dmrs_seq, dmrs_length, MOD_QPSK, mod_dmrs[symb]); + } else + nr_modulation(gold_pdcch_dmrs[symb], dmrs_length, MOD_QPSK, mod_dmrs[symb]); + +#ifdef DEBUG_PDCCH_DMRS + + for (int i=0; i>1; i++) + if (dmrs_offset) + printf("symb %d i %d gold seq 0x%08x mod_dmrs %d %d\n", symb, i, dmrs_seq[i>>5], + mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1] ); + else + printf("symb %d i %d gold seq 0x%08x mod_dmrs %d %d\n", symb, i, + gold_pdcch_dmrs[symb][i>>5], mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1] ); + +#endif } /// DCI payload processing - // CRC attachment + Scrambling + Channel coding + Rate matching + // CRC attachment + Scrambling + Channel coding + Rate matching uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD]; - uint16_t n_RNTI = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? ((pdcch_params.scrambling_id)?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; -//#ifdef PDCCH_TEST_POLAR_TEMP_FIX -// nr_polar_init(¤tPtr, NR_POLAR_DCI_MESSAGE_TYPE, dci_alloc.size, dci_alloc.L); -// t_nrPolar_paramsPtr currentPtr = nr_polar_params(*nrPolar_params, NR_POLAR_DCI_MESSAGE_TYPE, dci_alloc.size, dci_alloc.L); -//#else - nr_polar_init(nrPolar_params, NR_POLAR_DCI_MESSAGE_TYPE, dci_alloc.size, dci_alloc.L); - t_nrPolar_paramsPtr currentPtr = nr_polar_params(*nrPolar_params, NR_POLAR_DCI_MESSAGE_TYPE, dci_alloc.size, dci_alloc.L); -//#endif - - //polar_encoder_dci(dci_alloc.dci_pdu, encoder_output, currentPtr, pdcch_params.rnti); + uint16_t n_RNTI = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? pdcch_params.rnti: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; + t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, dci_alloc.size, dci_alloc.L); polar_encoder_fast(dci_alloc.dci_pdu, encoder_output, pdcch_params.rnti,currentPtr); - #ifdef DEBUG_CHANNEL_CODING printf("polar rnti %d\n",pdcch_params.rnti); - for (int i=0;i<54;i++) printf("Encoded Payload: [%d]->0x%08x \n", i,encoder_output[i]); + printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n", + dci_alloc.dci_pdu[0], dci_alloc.dci_pdu[1]); + printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5); - printf("DCI PDU: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", - dci_alloc.dci_pdu[0], dci_alloc.dci_pdu[1], dci_alloc.dci_pdu[2], dci_alloc.dci_pdu[3]); - printf("Encoded Payload: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\n", - encoder_output[0], encoder_output[1], encoder_output[2], encoder_output[3]); + for (int i=0; i>5; i++) + printf("[%d]->0x%08x \t", i,encoder_output[i]); + + printf("\n"); #endif - /// Scrambling - uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]={0}; + uint32_t scrambled_output[NR_MAX_DCI_SIZE_DWORD]= {0}; nr_pdcch_scrambling(encoder_output, encoded_length, Nid, n_RNTI, scrambled_output); #ifdef DEBUG_CHANNEL_CODING -printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\t \ + printf("scrambled output: [0]->0x%08x \t [1]->0x%08x \t [2]->0x%08x \t [3]->0x%08x\t [4]->0x%08x\t [5]->0x%08x\t \ [6]->0x%08x \t [7]->0x%08x \t [8]->0x%08x \t [9]->0x%08x\t [10]->0x%08x\t [11]->0x%08x\n", - scrambled_output[0], scrambled_output[1], scrambled_output[2], scrambled_output[3], scrambled_output[4],scrambled_output[5], - scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] ); + scrambled_output[0], scrambled_output[1], scrambled_output[2], scrambled_output[3], scrambled_output[4],scrambled_output[5], + scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] ); #endif - - // QPSK modulation + /// QPSK modulation int16_t mod_dci[NR_MAX_DCI_SIZE>>1]; - for (int i=0; i>1; i++) { - idx = ((((scrambled_output[(i<<1)>>5])>>((i<<1)&0x1f))&1)<<1) ^ (((scrambled_output[((i<<1)+1)>>5])>>(((i<<1)+1)&0x1f))&1); - mod_dci[i<<1] = nr_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx)<<1]; - mod_dci[(i<<1)+1] = nr_mod_table[((NR_MOD_TABLE_QPSK_OFFSET + idx)<<1) + 1]; + nr_modulation(scrambled_output, encoded_length, MOD_QPSK, mod_dci); #ifdef DEBUG_DCI - printf("i %d idx %d b0-b1 %d-%d mod_dci %d %d\n", i, idx, (((scrambled_output[(i<<1)>>5])>>((i<<1)&0x1f))&1), - (((scrambled_output[((i<<1)+1)>>5])>>(((i<<1)+1)&0x1f))&1), mod_dci[(i<<1)], mod_dci[(i<<1)+1]); + + for (int i=0; i>1; i++) + printf("i %d mod_dci %d %d\n", i, mod_dci[i<<1], mod_dci[(i<<1)+1] ); + #endif - } /// Resource mapping - if (cset_start_sc >= frame_parms.ofdm_symbol_size) - cset_start_sc -= frame_parms.ofdm_symbol_size; + if (cset_start_sc >= frame_parms.ofdm_symbol_size) + cset_start_sc -= frame_parms.ofdm_symbol_size; + /*Reorder REG list for a freq first mapping*/ + uint8_t symb_idx[NR_MAX_CSET_DURATION] = {0,0,0}; + uint8_t nb_regs = dci_alloc.L*NR_NB_REG_PER_CCE; + uint8_t regs_per_symb = nb_regs/cset_nsymb; - /*Reorder REG list for a freq first mapping*/ - uint8_t symb_idx[NR_MAX_CSET_DURATION] = {0,0,0}; - uint8_t nb_regs = dci_alloc.L*NR_NB_REG_PER_CCE; - uint8_t regs_per_symb = nb_regs/cset_nsymb; - for (int cce_idx=0; cce_idx> 15; - ((int16_t*)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15; -#ifdef DEBUG_PDCCH_DMRS - printf("symbol %d position %d => (%d,%d)\n",l,k,((int16_t*)txdataF[aa])[(l*frame_parms.ofdm_symbol_size + k)<<1] , ((int16_t*)txdataF[aa])[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); -#endif - k+=4; - if (k >= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; - dmrs_idx++; - } - } - } + printf("\n Ordered REG list:\n"); - /*Now mapping the encoded DCI based on newly constructed REG list - * and the DMRS for the precoder granularity same as REG bundle*/ - for (int reg_idx=0; reg_idx= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; - l = cset_start_symb + reg.symb_idx; - dmrs_idx = (reg.reg_idx/cset_nsymb)*3; - k_prime = 0; - for (int m=0; m> 15; - ((int16_t*)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15; -#ifdef DEBUG_PDCCH_DMRS - printf("l %d position %d => (%d,%d)\n",l,k,((int16_t*)txdataF[aa])[(l*frame_parms.ofdm_symbol_size + k)<<1] , ((int16_t*)txdataF[aa])[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); + for (int i=0; i> 15; - ((int16_t*)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dci[(dci_idx<<1) + 1]) >> 15; - //printf("dci output %d %d\n",(a * mod_dci[dci_idx<<1]) >> 15, (a * mod_dci[(dci_idx<<1) + 1]) >> 15); - dci_idx++; - } - k++; + + if (pdcch_params.precoder_granularity == NFAPI_NR_CSET_ALL_CONTIGUOUS_RBS) { + /*in this case the DMRS are mapped on all the coreset*/ + for (l=cset_start_symb; l>1) * mod_dmrs[l][dmrs_idx<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = ((amp>>1) * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15; +#ifdef DEBUG_PDCCH_DMRS + printf("symbol %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); +#endif + k+=4; + if (k >= frame_parms.ofdm_symbol_size) k -= frame_parms.ofdm_symbol_size; + + dmrs_idx++; } } + } + + /*Now mapping the encoded DCI based on newly constructed REG list + * and the DMRS for the precoder granularity same as REG bundle*/ + for (int reg_idx=0; reg_idx= frame_parms.ofdm_symbol_size) + k -= frame_parms.ofdm_symbol_size; + + l = cset_start_symb + reg.symb_idx; + dmrs_idx = (reg.reg_idx/cset_nsymb)*3; + k_prime = 0; + + for (int m=0; m>1) * mod_dmrs[l][dmrs_idx<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = ((amp>>1) * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15; +#ifdef DEBUG_PDCCH_DMRS + printf("l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); +#endif + dmrs_idx++; + } + + k_prime++; + } else { // DCI payload + ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * mod_dci[dci_idx<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dci[(dci_idx<<1) + 1]) >> 15; +#ifdef DEBUG_DCI + printf("l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); +#endif + dci_idx++; + } + + k++; + + if (k >= frame_parms.ofdm_symbol_size) + k -= frame_parms.ofdm_symbol_size; + } + } return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.h b/openair1/PHY/NR_TRANSPORT/nr_dci.h index 4bf250dbff..21fcd06c09 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.h @@ -28,14 +28,13 @@ typedef unsigned __int128 uint128_t; uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, - nfapi_nr_rnti_type_e rnti_type, - uint16_t N_RB, - nfapi_nr_config_request_t* config); + nfapi_nr_rnti_type_e rnti_type, + uint16_t N_RB, + nfapi_nr_config_request_t *config); uint8_t nr_generate_dci_top(NR_gNB_PDCCH pdcch_vars, - t_nrPolar_paramsPtr *nrPolar_params, uint32_t **gold_pdcch_dmrs, - int32_t* txdataF, + int32_t *txdataF, int16_t amp, NR_DL_FRAME_PARMS frame_parms, nfapi_nr_config_request_t config); @@ -44,7 +43,7 @@ void nr_pdcch_scrambling(uint32_t *in, uint16_t size, uint32_t Nid, uint32_t n_RNTI, - uint32_t* out); + uint32_t *out); void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, int frame, @@ -54,7 +53,7 @@ void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, nfapi_nr_dl_config_dci_dl_pdu *pdu, nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu); -void nr_fill_cce_list(NR_gNB_DCI_ALLOC_t* dci_alloc, uint16_t n_shift, uint8_t m); +void nr_fill_cce_list(NR_gNB_DCI_ALLOC_t *dci_alloc, uint16_t n_shift, uint8_t m); #endif //__PHY_NR_TRANSPORT_DCI__H diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 1d29b057fc..06c0e30bde 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -36,7 +36,6 @@ #include "nr_dlsch.h" - void nr_fill_cce_list(NR_gNB_DCI_ALLOC_t* dci_alloc, uint16_t n_shift, uint8_t m) { nr_cce_t* cce; @@ -48,6 +47,8 @@ void nr_fill_cce_list(NR_gNB_DCI_ALLOC_t* dci_alloc, uint16_t n_shift, uint8_t m uint8_t R = pdcch_params->interleaver_size; uint16_t N_reg = pdcch_params->n_rb * pdcch_params->n_symb; uint16_t Y, N_cce, M_s_max, n_CI=0, tmp, C; + uint16_t n_RNTI = (pdcch_params->search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? pdcch_params->rnti:0; + uint32_t A[3]={39827,39829,39839}; if (pdcch_params->config_type == NFAPI_NR_CSET_CONFIG_MIB_SIB1) AssertFatal(L>=4, "Invalid aggregation level for SIB1 configured PDCCH %d\n", L); @@ -59,13 +60,16 @@ void nr_fill_cce_list(NR_gNB_DCI_ALLOC_t* dci_alloc, uint16_t n_shift, uint8_t m if (pdcch_params->search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_COMMON) Y = 0; else { //NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC + Y = (A[0]*n_RNTI)%65537; // Candidate 0, antenna port 0 } - uint8_t cond = N_reg%(bsize*R); - AssertFatal(cond==0, "CCE to REG interleaving: Invalid configuration leading to non integer C\n"); - C = N_reg/(bsize*R); + if (pdcch_params->cr_mapping_type == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { + AssertFatal((N_reg%(bsize*R))==0, "CCE to REG interleaving: Invalid configuration leading to non integer C (N_reg %d, bsize %d R %d)\n", + N_reg, bsize, R); + C = N_reg/(bsize*R); + } - tmp = L * (( Y + (m*N_cce)/(L*M_s_max) + n_CI ) % (N_cce/L)); + tmp = L * (( Y + (m*N_cce)/(L*M_s_max) + n_CI ) % CEILIDIV(N_cce,L)); LOG_I(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d tmp %d\n", m, bsize, R, tmp); for (uint8_t cce_idx=0; cce_idx>i)&1)<<(size-i-1); + return ret; +}*/ + void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, int frame, int subframe, @@ -154,51 +165,66 @@ void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, case NFAPI_NR_DL_DCI_FORMAT_1_0: switch(params_rel15->rnti_type) { case NFAPI_NR_RNTI_RA: - // printf("dci_pdu %llx\n",(unsigned long long int)*dci_pdu); + // Freq domain assignment fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos=fsize; *dci_pdu |= ((pdu_rel15->frequency_domain_assignment&((1<size-pos)); #ifdef DEBUG_FILL_DCI - printf("frequency-domain assignment %d (%d bits)=> %d (%llx)\n",pdu_rel15->frequency_domain_assignment,fsize,dci_alloc->size-pos,(unsigned long long int)*dci_pdu); + printf("frequency-domain assignment %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->frequency_domain_assignment,fsize,dci_alloc->size-pos,*dci_pdu); #endif // Time domain assignment pos+=4; - *dci_pdu |= ((pdu_rel15->time_domain_assignment&0xf) << (dci_alloc->size-pos)); + *dci_pdu |= (((uint64_t)pdu_rel15->time_domain_assignment&0xf) << (dci_alloc->size-pos)); #ifdef DEBUG_FILL_DCI - printf("time-domain assignment %d (3 bits)=> %d (%llx)\n",pdu_rel15->time_domain_assignment,dci_alloc->size-pos,(unsigned long long int)*dci_pdu); + printf("time-domain assignment %d (3 bits)=> %d (0x%lx)\n",pdu_rel15->time_domain_assignment,dci_alloc->size-pos,*dci_pdu); #endif // VRB to PRB mapping pos++; - *dci_pdu |= (pdu_rel15->vrb_to_prb_mapping&0x1)<<(dci_alloc->size-pos); + *dci_pdu |= ((uint64_t)pdu_rel15->vrb_to_prb_mapping&0x1)<<(dci_alloc->size-pos); #ifdef DEBUG_FILL_DCI - printf("vrb to prb mapping %d (1 bits)=> %d (%llx)\n",pdu_rel15->vrb_to_prb_mapping,dci_alloc->size-pos,(unsigned long long int)*dci_pdu); + printf("vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n",pdu_rel15->vrb_to_prb_mapping,dci_alloc->size-pos,*dci_pdu); #endif // MCS pos+=5; - *dci_pdu |= (pdu_rel15->mcs&0x1f)<<(dci_alloc->size-pos); + *dci_pdu |= ((uint64_t)pdu_rel15->mcs&0x1f)<<(dci_alloc->size-pos); #ifdef DEBUG_FILL_DCI - printf("mcs %d (5 bits)=> %d (%llx)\n",pdu_rel15->mcs,dci_alloc->size-pos,(unsigned long long int)*dci_pdu); + printf("mcs %d (5 bits)=> %d (0x%lx)\n",pdu_rel15->mcs,dci_alloc->size-pos,*dci_pdu); #endif // TB scaling pos+=2; - *dci_pdu |= (pdu_rel15->tb_scaling&0x3)<<(dci_alloc->size-pos); + *dci_pdu |= ((uint64_t)pdu_rel15->tb_scaling&0x3)<<(dci_alloc->size-pos); #ifdef DEBUG_FILL_DCI - printf("tb_scaling %d (2 bits)=> %d (%llx)\n",pdu_rel15->tb_scaling,dci_alloc->size-pos,(unsigned long long int)*dci_pdu); + printf("tb_scaling %d (2 bits)=> %d (0x%lx)\n",pdu_rel15->tb_scaling,dci_alloc->size-pos,*dci_pdu); #endif break; - case NFAPI_NR_RNTI_C: + case NFAPI_NR_RNTI_C: + // indicating a DL DCI format 1bit pos++; - *dci_pdu |= (pdu_rel15->format_indicator&1)<<(dci_alloc->size-pos); + *dci_pdu |= ((uint64_t)pdu_rel15->format_indicator&1)<<(dci_alloc->size-pos); +#ifdef DEBUG_FILL_DCI + printf("Format indicator %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->format_indicator,1,dci_alloc->size-pos,*dci_pdu); +#endif + // Freq domain assignment (275rb >> fsize = 16) fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos+=fsize; - *dci_pdu |= ((pdu_rel15->frequency_domain_assignment&((1<size-pos)); + *dci_pdu |= (((uint64_t)pdu_rel15->frequency_domain_assignment&((1<size-pos)); - if (((pdu_rel15->frequency_domain_assignment+1)&1) ==0) //fsize are all 1 38.212 p86 +#ifdef DEBUG_FILL_DCI + printf("Freq domain assignment %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->frequency_domain_assignment,fsize,dci_alloc->size-pos,*dci_pdu); +#endif + + uint16_t is_ra = 1; + for (int i=0; ifrequency_domain_assignment>>i)&1)) { + is_ra = 0; + break; + } + if (is_ra) //fsize are all 1 38.212 p86 { // ra_preamble_index 6 bits pos+=6; @@ -223,44 +249,73 @@ void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, // Time domain assignment 4bit pos+=4; - *dci_pdu |= ((pdu_rel15->time_domain_assignment&0xf) << (dci_alloc->size-pos)); + *dci_pdu |= ((pdu_rel15->time_domain_assignment&0xf) << (dci_alloc->size-pos)); +#ifdef DEBUG_FILL_DCI + printf("Time domain assignment %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->time_domain_assignment,4,dci_alloc->size-pos,*dci_pdu); +#endif - // VRB to PRB mapping 1bit pos++; *dci_pdu |= (pdu_rel15->vrb_to_prb_mapping&1)<<(dci_alloc->size-pos); - +#ifdef DEBUG_FILL_DCI + printf("VRB to PRB %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->vrb_to_prb_mapping,1,dci_alloc->size-pos,*dci_pdu); +#endif + // MCS 5bit //bit over 32, so dci_pdu ++ pos+=5; *dci_pdu |= (pdu_rel15->mcs&0x1f)<<(dci_alloc->size-pos); - +#ifdef DEBUG_FILL_DCI + printf("MCS %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->mcs,5,dci_alloc->size-pos,*dci_pdu); +#endif + // New data indicator 1bit pos++; *dci_pdu |= (pdu_rel15->ndi&1)<<(dci_alloc->size-pos); - +#ifdef DEBUG_FILL_DCI + printf("NDI %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->ndi,1,dci_alloc->size-pos,*dci_pdu); +#endif + // Redundancy version 2bit pos+=2; *dci_pdu |= (pdu_rel15->rv&0x3)<<(dci_alloc->size-pos); - +#ifdef DEBUG_FILL_DCI + printf("RV %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->rv,2,dci_alloc->size-pos,*dci_pdu); +#endif + // HARQ process number 4bit pos+=4; - *dci_pdu |= ((pdu_rel15->harq_pid&0xf)<<(dci_alloc->size-pos)); - + *dci_pdu |= ((pdu_rel15->harq_pid&0xf)<<(dci_alloc->size-pos)); +#ifdef DEBUG_FILL_DCI + printf("HARQ_PID %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->harq_pid,4,dci_alloc->size-pos,*dci_pdu); +#endif + // Downlink assignment index 2bit pos+=2; *dci_pdu |= ((pdu_rel15->dai&3)<<(dci_alloc->size-pos)); +#ifdef DEBUG_FILL_DCI + printf("DAI %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->dai,2,dci_alloc->size-pos,*dci_pdu); +#endif // TPC command for scheduled PUCCH 2bit pos+=2; - *dci_pdu |= ((pdu_rel15->tpc&3)<<(dci_alloc->size-pos)); + *dci_pdu |= ((pdu_rel15->tpc&3)<<(dci_alloc->size-pos)); +#ifdef DEBUG_FILL_DCI + printf("TPC %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->tpc,2,dci_alloc->size-pos,*dci_pdu); +#endif // PUCCH resource indicator 3bit pos+=3; - *dci_pdu |= ((pdu_rel15->pucch_resource_indicator&0x7)<<(dci_alloc->size-pos)); + *dci_pdu |= ((pdu_rel15->pucch_resource_indicator&0x7)<<(dci_alloc->size-pos)); +#ifdef DEBUG_FILL_DCI + printf("PUCCH RI %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->pucch_resource_indicator,3,dci_alloc->size-pos,*dci_pdu); +#endif // PDSCH-to-HARQ_feedback timing indicator 3bit pos+=3; - *dci_pdu |= ((pdu_rel15->pdsch_to_harq_feedback_timing_indicator&0x7)<<(dci_alloc->size-pos)); + *dci_pdu |= ((pdu_rel15->pdsch_to_harq_feedback_timing_indicator&0x7)<<(dci_alloc->size-pos)); +#ifdef DEBUG_FILL_DCI + printf("PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n",pdu_rel15->pdsch_to_harq_feedback_timing_indicator,3,dci_alloc->size-pos,*dci_pdu); +#endif } //end else break; @@ -269,26 +324,26 @@ void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, // Short Messages Indicator – 2 bits for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->short_messages_indicator>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->short_messages_indicator>>(1-i))&1)<<(dci_alloc->size-pos++); // Short Messages – 8 bits for (int i=0; i<8; i++) - *dci_pdu |= ((pdu_rel15->short_messages>>(7-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->short_messages>>(7-i))&1)<<(dci_alloc->size-pos++); // Freq domain assignment 0-16 bit fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); for (int i=0; ifrequency_domain_assignment>>(fsize-i-1))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->frequency_domain_assignment>>(fsize-i-1))&1)<<(dci_alloc->size-pos++); // Time domain assignment 4 bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); // VRB to PRB mapping 1 bit - *dci_pdu |= (pdu_rel15->vrb_to_prb_mapping&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->vrb_to_prb_mapping&1)<<(dci_alloc->size-pos++); // MCS 5 bit for (int i=0; i<5; i++) - *dci_pdu |= ((pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); - + *dci_pdu |= (((uint64_t)pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); + // TB scaling 2 bit for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->tb_scaling>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->tb_scaling>>(1-i))&1)<<(dci_alloc->size-pos++); break; @@ -300,49 +355,49 @@ void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, *dci_pdu |= ((pdu_rel15->frequency_domain_assignment>>(fsize-i-1))&1)<<(dci_alloc->size-pos++); // Time domain assignment 4 bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); // VRB to PRB mapping 1 bit - *dci_pdu |= (pdu_rel15->vrb_to_prb_mapping&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->vrb_to_prb_mapping&1)<<(dci_alloc->size-pos++); // MCS 5bit //bit over 32, so dci_pdu ++ for (int i=0; i<5; i++) - *dci_pdu |= ((pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); // Redundancy version 2bit for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); break; case NFAPI_NR_RNTI_TC: // indicating a DL DCI format 1bit - *dci_pdu |= (pdu_rel15->format_indicator&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->format_indicator&1)<<(dci_alloc->size-pos++); // Freq domain assignment 0-16 bit fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); for (int i=0; ifrequency_domain_assignment>>(fsize-i-1))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->frequency_domain_assignment>>(fsize-i-1))&1)<<(dci_alloc->size-pos++); // Time domain assignment 4 bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); // VRB to PRB mapping 1 bit - *dci_pdu |= (pdu_rel15->vrb_to_prb_mapping&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->vrb_to_prb_mapping&1)<<(dci_alloc->size-pos++); // MCS 5bit //bit over 32, so dci_pdu ++ for (int i=0; i<5; i++) - *dci_pdu |= ((pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); // New data indicator 1bit - *dci_pdu |= (pdu_rel15->ndi&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->ndi&1)<<(dci_alloc->size-pos++); // Redundancy version 2bit for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); // HARQ process number 4bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->harq_pid>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->harq_pid>>(3-i))&1)<<(dci_alloc->size-pos++); - // Downlink assignment index – 2 bits + // Downlink assignment index – 2 bits for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->dai>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->dai>>(1-i))&1)<<(dci_alloc->size-pos++); // TPC command for scheduled PUCCH – 2 bits for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->tpc>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->tpc>>(1-i))&1)<<(dci_alloc->size-pos++); // LOG_I(PHY, "DCI PDU: [0]->0x%08llx \t [1]->0x%08llx \t [2]->0x%08llx \t [3]->0x%08llx\n", @@ -351,49 +406,50 @@ void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, // PDSCH-to-HARQ_feedback timing indicator – 3 bits for (int i=0; i<3; i++) - *dci_pdu |= ((pdu_rel15->pdsch_to_harq_feedback_timing_indicator>>(2-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->pdsch_to_harq_feedback_timing_indicator>>(2-i))&1)<<(dci_alloc->size-pos++); break; } + break; case NFAPI_NR_UL_DCI_FORMAT_0_0: switch(params_rel15->rnti_type) { case NFAPI_NR_RNTI_C: // indicating a DL DCI format 1bit - *dci_pdu |= (pdu_rel15->format_indicator&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->format_indicator&1)<<(dci_alloc->size-pos++); // Freq domain assignment max 16 bit fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); for (int i=0; ifrequency_domain_assignment>>(fsize-i-1))&1)<<(dci_alloc->size-pos++); // Time domain assignment 4bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); // Frequency hopping flag – 1 bit - *dci_pdu |= (pdu_rel15->frequency_hopping_flag&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->frequency_hopping_flag&1)<<(dci_alloc->size-pos++); // MCS 5 bit for (int i=0; i<5; i++) - *dci_pdu |= ((pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); // New data indicator 1bit - *dci_pdu |= (pdu_rel15->ndi&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->ndi&1)<<(dci_alloc->size-pos++); // Redundancy version 2bit for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); // HARQ process number 4bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->harq_pid>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->harq_pid>>(3-i))&1)<<(dci_alloc->size-pos++); // TPC command for scheduled PUSCH – 2 bits for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->tpc>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->tpc>>(1-i))&1)<<(dci_alloc->size-pos++); // Padding bits for(int a = pos;a<32;a++) - *dci_pdu |= (pdu_rel15->padding&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->padding&1)<<(dci_alloc->size-pos++); // UL/SUL indicator – 1 bit if (cfg->pucch_config.pucch_GroupHopping.value) - *dci_pdu |= (pdu_rel15->ul_sul_indicator&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->ul_sul_indicator&1)<<(dci_alloc->size-pos++); break; @@ -407,39 +463,39 @@ void nr_fill_dci_and_dlsch(PHY_VARS_gNB *gNB, *dci_pdu |= ((pdu_rel15->frequency_domain_assignment>>(fsize-i-1))&1)<<(dci_alloc->size-pos++); // Time domain assignment 4bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->time_domain_assignment>>(3-i))&1)<<(dci_alloc->size-pos++); // Frequency hopping flag – 1 bit - *dci_pdu |= (pdu_rel15->frequency_hopping_flag&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->frequency_hopping_flag&1)<<(dci_alloc->size-pos++); // MCS 5 bit for (int i=0; i<5; i++) - *dci_pdu |= ((pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->mcs>>(4-i))&1)<<(dci_alloc->size-pos++); // New data indicator 1bit - *dci_pdu |= (pdu_rel15->ndi&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->ndi&1)<<(dci_alloc->size-pos++); // Redundancy version 2bit for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->rv>>(1-i))&1)<<(dci_alloc->size-pos++); // HARQ process number 4bit for (int i=0; i<4; i++) - *dci_pdu |= ((pdu_rel15->harq_pid>>(3-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->harq_pid>>(3-i))&1)<<(dci_alloc->size-pos++); // TPC command for scheduled PUSCH – 2 bits for (int i=0; i<2; i++) - *dci_pdu |= ((pdu_rel15->tpc>>(1-i))&1)<<(dci_alloc->size-pos++); + *dci_pdu |= (((uint64_t)pdu_rel15->tpc>>(1-i))&1)<<(dci_alloc->size-pos++); // Padding bits for(int a = pos;a<32;a++) - *dci_pdu |= (pdu_rel15->padding&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->padding&1)<<(dci_alloc->size-pos++); // UL/SUL indicator – 1 bit if (cfg->pucch_config.pucch_GroupHopping.value) - *dci_pdu |= (pdu_rel15->ul_sul_indicator&1)<<(dci_alloc->size-pos++); + *dci_pdu |= ((uint64_t)pdu_rel15->ul_sul_indicator&1)<<(dci_alloc->size-pos++); break; } break; } - LOG_I(PHY, "DCI PDU: [0]->0x%16llxx \t [1]->0x%16llx \n",(long long unsigned int)dci_pdu[0], (long long unsigned int)dci_pdu[1]); + LOG_I(PHY, "DCI PDU: [0]->0x%lx \t [1]->0x%lx \n",dci_pdu[0], dci_pdu[1]); LOG_I(PHY, "DCI type %d payload (size %d) generated on candidate %d\n", dci_alloc->pdcch_params.dci_format, dci_alloc->size, cand_idx); /// DLSCH struct diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index b65b48c39e..eb2e11fec4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -338,11 +338,9 @@ ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol); for (int l=rel15->start_symbol; lstart_symbol+rel15->nb_symbols; l++) { k = start_sc; for (int i=0; in_prb*NR_NB_SC_PER_RB; i++) { -// Note the dmrs index modulo 2048 only works for that symbol size -- to be fixed soon -// Also the different amplitudes are for debug purposes and temporary - if ((l == dmrs_symbol) && (k == ((start_sc+get_pdsch_dmrs_idx(n, k_prime, delta, dmrs_type))&((1<<11)-1)))) { - ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*(amp>>1)*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>>1)*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + 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; #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], @@ -356,8 +354,8 @@ 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<<1) * tx_layers[ap][m<<1]) >> 15; - ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = ((amp<<1) * 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], diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 8a2877cc17..50e836fe58 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -69,7 +69,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) #endif if (dlsch->harq_processes[i]->b) { - free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES); + free16(dlsch->harq_processes[i]->b,MAX_DLSCH_PAYLOAD_BYTES); //this should be MAX_NR_DLSCH_PAYLOAD_BYTES dlsch->harq_processes[i]->b = NULL; #ifdef DEBUG_DLSCH_FREE printf("Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b); @@ -195,8 +195,11 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(unsigned char Kmimo, if (abstraction_flag==0) { for (r=0; rharq_processes[i]->c[r] = (uint8_t*)malloc16(8448); - dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); + dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output if (dlsch->harq_processes[i]->c[r]) { bzero(dlsch->harq_processes[i]->c[r],8448); } else { @@ -272,22 +275,22 @@ int nr_dlsch_encoding(unsigned char *a, unsigned int G; unsigned int crc=1; - uint8_t harq_pid = dlsch->harq_ids[slot]; nfapi_nr_dl_config_dlsch_pdu_rel15_t rel15 = dlsch->harq_processes[harq_pid]->dlsch_pdu.dlsch_pdu_rel15; uint16_t nb_rb = rel15.n_prb; uint8_t nb_symb_sch = rel15.nb_symbols; - uint32_t A, Z; + uint32_t A, Z, F=0; uint32_t *pz = &Z; uint8_t mod_order = rel15.modulation_order; uint16_t Kr=0,r,r_offset=0,Kr_bytes; uint8_t *d_tmp[MAX_NUM_DLSCH_SEGMENTS]; - uint8_t kb,BG=1; + uint8_t BG=1; uint32_t E; uint8_t Ilbrm = 0; uint32_t Tbslbrm = 950984; //max tbs uint8_t nb_re_dmrs = rel15.nb_re_dmrs; uint16_t length_dmrs = 1; + float Coderate = 0.0; /* uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; //unsigned char @@ -301,7 +304,9 @@ int nr_dlsch_encoding(unsigned char *a, A = rel15.transport_block_size; G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15.nb_layers); + LOG_D(PHY,"dlsch 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, rel15.nb_layers); @@ -327,6 +332,7 @@ int nr_dlsch_encoding(unsigned char *a, dlsch->harq_processes[harq_pid]->B = A+24; // dlsch->harq_processes[harq_pid]->b = a; + memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); nr_segmentation(dlsch->harq_processes[harq_pid]->b, @@ -334,21 +340,23 @@ int nr_dlsch_encoding(unsigned char *a, dlsch->harq_processes[harq_pid]->B, &dlsch->harq_processes[harq_pid]->C, &dlsch->harq_processes[harq_pid]->K, - pz, + pz, // [hna] pz is Zc &dlsch->harq_processes[harq_pid]->F); - kb = dlsch->harq_processes[harq_pid]->K/(*pz); - if ( kb==22){ - BG = 1; + F = dlsch->harq_processes[harq_pid]->F; + Coderate = (float) A /(float) G; + + if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ + BG = 2; } else{ - BG = 2; + BG = 1; } Kr = dlsch->harq_processes[harq_pid]->K; Kr_bytes = Kr>>3; - //printf("segment Z %d kb %d k %d Kr %d BG %d\n", *pz,kb,dlsch->harq_processes[harq_pid]->K,Kr,BG); + //printf("segment Z %d k %d Kr %d BG %d\n", *pz,dlsch->harq_processes[harq_pid]->K,Kr,BG); //start_meas(te_stats); for (r=0; rharq_processes[harq_pid]->C; r++) { @@ -385,6 +393,7 @@ int nr_dlsch_encoding(unsigned char *a, //stop_meas(te_stats); //printf("end ldpc encoder -- output\n"); + //write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4); #ifdef DEBUG_DLSCH_CODING write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4); write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[0][0],(3*8*Kr_bytes)+12,1,4); @@ -393,6 +402,14 @@ int nr_dlsch_encoding(unsigned char *a, } for (r=0; rharq_processes[harq_pid]->C; r++) { + + if (dlsch->harq_processes[harq_pid]->F>0) { + for (int k=(Kr-F-2*(*pz)); kharq_processes[harq_pid]->d[r][k] = NR_NULL; + //if (k<(Kr-F+8)) + //printf("r %d filler bits [%d] = %d \n", r,k, dlsch->harq_processes[harq_pid]->d[r][k]); + } + } #ifdef DEBUG_DLSCH_CODING printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", r, @@ -418,6 +435,7 @@ int nr_dlsch_encoding(unsigned char *a, rel15.redundancy_version, E); + #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset); @@ -431,6 +449,7 @@ int nr_dlsch_encoding(unsigned char *a, dlsch->harq_processes[harq_pid]->f+r_offset); //stop_meas(i_stats); + #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset); @@ -444,5 +463,5 @@ int nr_dlsch_encoding(unsigned char *a, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); - return(0); + return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 2e2c99f106..ead8e3cda5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -43,21 +43,20 @@ extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, - 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31}; + 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31 + }; int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, int32_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, - nfapi_nr_config_request_t* config, - NR_DL_FRAME_PARMS *frame_parms) -{ + nfapi_nr_config_request_t *config, + NR_DL_FRAME_PARMS *frame_parms) { int k,l; //int16_t a; int16_t mod_dmrs[NR_PBCH_DMRS_LENGTH<<1]; uint8_t idx=0; uint8_t nushift = config->sch_config.physical_cell_id.value &3; - LOG_D(PHY, "PBCH DMRS mapping started at symbol %d shift %d\n", ssb_start_symbol+1, nushift); /// QPSK modulation @@ -66,79 +65,75 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, mod_dmrs[m<<1] = nr_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx)<<1]; mod_dmrs[(m<<1)+1] = nr_mod_table[((NR_MOD_TABLE_QPSK_OFFSET + idx)<<1) + 1]; #ifdef DEBUG_PBCH_DMRS - printf("m %d idx %d gold seq %d b0-b1 %d-%d mod_dmrs %d %d\n", m, idx, gold_pbch_dmrs[(m<<1)>>5], (((gold_pbch_dmrs[(m<<1)>>5])>>((m<<1)&0x1f))&1), - (((gold_pbch_dmrs[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1), mod_dmrs[(m<<1)], mod_dmrs[(m<<1)+1]); + printf("m %d idx %d gold seq %d b0-b1 %d-%d mod_dmrs %d %d\n", m, idx, gold_pbch_dmrs[(m<<1)>>5], (((gold_pbch_dmrs[(m<<1)>>5])>>((m<<1)&0x1f))&1), + (((gold_pbch_dmrs[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1), mod_dmrs[(m<<1)], mod_dmrs[(m<<1)+1]); #endif } /// Resource mapping + // PBCH DMRS are mapped within the SSB block on every fourth subcarrier starting from nushift of symbols 1, 2, 3 + ///symbol 1 [0+nushift:4:236+nushift] -- 60 mod symbols + k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + l = ssb_start_symbol + 1; - - // PBCH DMRS are mapped within the SSB block on every fourth subcarrier starting from nushift of symbols 1, 2, 3 - ///symbol 1 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; - l = ssb_start_symbol + 1; - - for (int m = 0; m < 60; m++) { + for (int m = 0; m < 60; m++) { #ifdef DEBUG_PBCH_DMRS - printf("m %d at k %d of l %d\n", m, k, l); + printf("m %d at k %d of l %d\n", m, k, l); #endif - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; #ifdef DEBUG_PBCH_DMRS - printf("(%d,%d)\n", - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); + printf("(%d,%d)\n", + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif - k+=4; + k+=4; - 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; + } - ///symbol 2 [0+u:4:44+nushift ; 192+nu:4:236+nushift] -- 24 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; - l++; + ///symbol 2 [0+u:4:44+nushift ; 192+nu:4:236+nushift] -- 24 mod symbols + k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + l++; - for (int m = 60; m < 84; m++) { + for (int m = 60; m < 84; m++) { #ifdef DEBUG_PBCH_DMRS - printf("m %d at k %d of l %d\n", m, k, l); + printf("m %d at k %d of l %d\n", m, k, l); #endif - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; #ifdef DEBUG_PBCH_DMRS - printf("(%d,%d)\n", - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); + printf("(%d,%d)\n", + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif - k+=(m==71)?148:4; // Jump from 44+nu to 192+nu + k+=(m==71)?148:4; // Jump from 44+nu to 192+nu - 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; + } - ///symbol 3 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; - l++; + ///symbol 3 [0+nushift:4:236+nushift] -- 60 mod symbols + k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + l++; - for (int m = 84; m < NR_PBCH_DMRS_LENGTH; m++) { + for (int m = 84; m < NR_PBCH_DMRS_LENGTH; m++) { #ifdef DEBUG_PBCH_DMRS - printf("m %d at k %d of l %d\n", m, k, l); + printf("m %d at k %d of l %d\n", m, k, l); #endif - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; #ifdef DEBUG_PBCH_DMRS - printf("(%d,%d)\n", - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); + printf("(%d,%d)\n", + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif - k+=4; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - } - + k+=4; + if (k >= frame_parms->ofdm_symbol_size) + k-=frame_parms->ofdm_symbol_size; + } #ifdef DEBUG_PBCH_DMRS write_output("txdataF_pbch_dmrs.m", "txdataF_pbch_dmrs", txdataF[0], frame_parms->samples_per_frame_wCP>>1, 1, 1); @@ -186,6 +181,7 @@ void nr_pbch_scrambling(NR_gNB_PBCH *pbch, s = lte_gold_generic(&x1, &x2, reset); reset = 0; } + pbch->pbch_a_prime ^= (((pbch->pbch_a_interleaved>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<pbch_a=0; + for (int i=0; ipbch_a |= ((pbch_pdu[2-(i>>3)]>>(7-(i&7)))&1)<pbch_a); #endif - // Extra byte generation + // Extra byte generation for (int i=0; i<4; i++) pbch->pbch_a |= ((sfn>>(3-i))&1)<<(24+i); // resp. 4th, 3rd, 2nd ans 1st lsb of sfn @@ -276,12 +269,12 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, LOG_I(PHY,"After extra byte: pbch_a = 0x%08x\n",pbch->pbch_a); - // Payload interleaving - + // Payload interleaving + for (int i=0; ipbch_a_interleaved |= ((pbch->pbch_a>>i)&1)<<(*(interleaver+i)); #ifdef DEBUG_PBCH_ENCODING - printf("i %d out 0x%08x ilv %d (in>>i)&1) %d\n", i, pbch->pbch_a_interleaved, *(interleaver+i), (pbch->pbch_a>>i)&1); + printf("i %d out 0x%08x ilv %d (in>>i)&1) %d\n", i, pbch->pbch_a_interleaved, *(interleaver+i), (pbch->pbch_a>>i)&1); #endif } @@ -289,8 +282,7 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, printf("Interleaving:\n"); printf("pbch_a_interleaved: 0x%08x\n", pbch->pbch_a_interleaved); #endif - - // Scrambling + // Scrambling unscrambling_mask = (Lmax ==64)? 0x100006D:0x1000041; M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = (((sfn>>2)&1)<<1) ^ ((sfn>>1)&1); @@ -301,148 +293,143 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, printf("pbch_a_prime: 0x%08x\n", pbch->pbch_a_prime); #endif -// Encoder reversal + // Encoder reversal for (int i=0; ipbch_a_prime>>i)&1)<<(31-i); - /// CRC, coding and rate matching - polar_encoder_fast (&a_reversed, (uint32_t*)pbch->pbch_e, 0, polar_params); + polar_encoder_fast (&a_reversed, (uint32_t *)pbch->pbch_e, 0, + nr_polar_params( NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL) + ); #ifdef DEBUG_PBCH_ENCODING printf("Channel coding:\n"); + for (int i=0; ipbch_e[i]); + printf("\n"); #endif - /// Scrambling M = NR_POLAR_PBCH_E; nushift = (Lmax==4)? ssb_index&3 : ssb_index&7; nr_pbch_scrambling(pbch, (uint32_t)config->sch_config.physical_cell_id.value, nushift, M, NR_POLAR_PBCH_E, 1, 0); #ifdef DEBUG_PBCH_ENCODING printf("Scrambling:\n"); + for (int i=0; ipbch_e[i]); + printf("\n"); #endif /// QPSK modulation - for (int i=0; i>1; i++){ + for (int i=0; i>1; i++) { idx = (((pbch->pbch_e[(i<<1)>>5]>>((i<<1)&0x1f))&1)<<1) ^ ((pbch->pbch_e[((i<<1)+1)>>5]>>(((i<<1)+1)&0x1f))&1); mod_pbch_e[i<<1] = nr_mod_table[(NR_MOD_TABLE_QPSK_OFFSET + idx)<<1]; mod_pbch_e[(i<<1)+1] = nr_mod_table[((NR_MOD_TABLE_QPSK_OFFSET + idx)<<1)+1]; - #ifdef DEBUG_PBCH - printf("i %d idx %d mod_pbch %d %d\n", i, idx, mod_pbch_e[2*i], mod_pbch_e[2*i+1]); + printf("i %d idx %d mod_pbch %d %d\n", i, idx, mod_pbch_e[2*i], mod_pbch_e[2*i+1]); #endif } /// Resource mapping nushift = config->sch_config.physical_cell_id.value &3; + // PBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PBCH DMRS + ///symbol 1 [0:239] -- 180 mod symbols + k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + l = ssb_start_symbol + 1; + m = 0; - - // PBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PBCH DMRS - ///symbol 1 [0:239] -- 180 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; - l = ssb_start_symbol + 1; - m = 0; - - for (int ssb_sc_idx = 0; ssb_sc_idx < 240; ssb_sc_idx++) { - - if ((ssb_sc_idx&3) == nushift) { //skip DMRS - k++; - continue; - } - else { + for (int ssb_sc_idx = 0; ssb_sc_idx < 240; ssb_sc_idx++) { + if ((ssb_sc_idx&3) == nushift) { //skip DMRS + k++; + continue; + } else { #ifdef DEBUG_PBCH - printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); + printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); #endif - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; - k++; - m++; - } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + k++; + m++; } - ///symbol 2 [0:47 ; 192:239] -- 72 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; - l++; - m=180; - - for (int ssb_sc_idx = 0; ssb_sc_idx < 48; ssb_sc_idx++) { - - if ((ssb_sc_idx&3) == nushift) { - k++; - continue; - } - else { -#ifdef DEBUG_PBCH - printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); -#endif - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; - k++; - m++; - } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - } - - k += 144; if (k >= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; + } - m=216; + ///symbol 2 [0:47 ; 192:239] -- 72 mod symbols + k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + l++; + m=180; - for (int ssb_sc_idx = 192; ssb_sc_idx < 240; ssb_sc_idx++) { - - if ((ssb_sc_idx&3) == nushift) { - k++; - continue; - } - else { + for (int ssb_sc_idx = 0; ssb_sc_idx < 48; ssb_sc_idx++) { + if ((ssb_sc_idx&3) == nushift) { + k++; + continue; + } else { #ifdef DEBUG_PBCH - printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); + printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); #endif - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; - k++; - m++; - } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + k++; + m++; } - ///symbol 3 [0:239] -- 180 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; - l++; - m=252; + if (k >= frame_parms->ofdm_symbol_size) + k-=frame_parms->ofdm_symbol_size; + } - for (int ssb_sc_idx = 0; ssb_sc_idx < 240; ssb_sc_idx++) { + k += 144; - if ((ssb_sc_idx&3) == nushift) { - k++; - continue; - } - else { + if (k >= frame_parms->ofdm_symbol_size) + k-=frame_parms->ofdm_symbol_size; + + m=216; + + for (int ssb_sc_idx = 192; ssb_sc_idx < 240; ssb_sc_idx++) { + if ((ssb_sc_idx&3) == nushift) { + k++; + continue; + } else { #ifdef DEBUG_PBCH - printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); + printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); #endif - ((int16_t*)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t*)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; - k++; - m++; - } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + k++; + m++; } + if (k >= frame_parms->ofdm_symbol_size) + k-=frame_parms->ofdm_symbol_size; + } + + ///symbol 3 [0:239] -- 180 mod symbols + k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + l++; + m=252; + + for (int ssb_sc_idx = 0; ssb_sc_idx < 240; ssb_sc_idx++) { + if ((ssb_sc_idx&3) == nushift) { + k++; + continue; + } else { +#ifdef DEBUG_PBCH + printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); +#endif + ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; + ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + k++; + m++; + } + + + if (k >= frame_parms->ofdm_symbol_size) + k-=frame_parms->ofdm_symbol_size; + } + return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_pss.c b/openair1/PHY/NR_TRANSPORT/nr_pss.c index 29dbe4ec99..e0d7b6ae33 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pss.c @@ -59,7 +59,6 @@ int nr_generate_pss( int16_t *d_pss, /// Resource mapping a = amp; - // PSS occupies a predefined position (subcarriers 56-182, symbol 0) within the SSB block starting from k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport.h b/openair1/PHY/NR_TRANSPORT/nr_transport.h index c1a4052191..23413f591c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport.h @@ -36,7 +36,7 @@ int nr_generate_pss( int16_t *d_pss, int32_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, - nfapi_nr_config_request_t* config, + nfapi_nr_config_request_t *config, NR_DL_FRAME_PARMS *frame_parms); /*! @@ -49,7 +49,7 @@ int nr_generate_sss( int16_t *d_sss, int32_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, - nfapi_nr_config_request_t* config, + nfapi_nr_config_request_t *config, NR_DL_FRAME_PARMS *frame_parms); /*! @@ -62,7 +62,7 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, int32_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, - nfapi_nr_config_request_t* config, + nfapi_nr_config_request_t *config, NR_DL_FRAME_PARMS *frame_parms); /*! @@ -85,7 +85,6 @@ void nr_pbch_scrambling(NR_gNB_PBCH *pbch, @returns 0 on success */ int nr_generate_pbch(NR_gNB_PBCH *pbch, - t_nrPolar_paramsPtr polar_params, uint8_t *pbch_pdu, uint8_t *interleaver, int32_t *txdataF, @@ -95,7 +94,7 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, uint8_t Lmax, uint8_t ssb_index, int sfn, - nfapi_nr_config_request_t* config, + nfapi_nr_config_request_t *config, NR_DL_FRAME_PARMS *frame_parms); /*! diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index b075da4e97..14ba3de923 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -38,7 +38,7 @@ #define MAX_NUM_NR_ULSCH_SEGMENTS MAX_NUM_NR_DLSCH_SEGMENTS #define MAX_NR_DLSCH_PAYLOAD_BYTES (MAX_NUM_NR_DLSCH_SEGMENTS*1056) -#define MAX_NR_ULSCH_PAYLOAD_BYTES (MAX_NUM_NR_DLSCH_SEGMENTS*1056) +#define MAX_NR_ULSCH_PAYLOAD_BYTES (MAX_NUM_NR_ULSCH_SEGMENTS*1056) #define MAX_NUM_NR_CHANNEL_BITS (14*273*12*6) // 14 symbols, 273 RB #define MAX_NUM_NR_RE (14*273*12) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h new file mode 100644 index 0000000000..77cc101679 --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -0,0 +1,49 @@ +/* + * 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.0 (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.h +* \brief functions used for PUSCH/ULSCH physical and transport channels for gNB +* \author Ahmed Hussein +* \date 2019 +* \version 0.1 +* \company Fraunhofer IIS +* \email: ahmed.hussein@iis.fraunhofer.de +* \note +* \warning +*/ + +#include "PHY/defs_gNB.h" + +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); + +uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, + uint8_t UE_id, + short *ulsch_llr, + NR_DL_FRAME_PARMS *frame_parms, + uint32_t frame, + uint16_t nb_symb_sch, + uint8_t nr_tti_rx, + uint8_t harq_pid, + uint8_t is_crnti, + uint8_t llr8_flag); + diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c new file mode 100644 index 0000000000..ace93e4ee3 --- /dev/null +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -0,0 +1,611 @@ +/* + * 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.0 (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_decoding.c +* \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12 +* \author Ahmed Hussein +* \date 2019 +* \version 0.1 +* \company Fraunhofer IIS +* \email: ahmed.hussein@iis.fraunhofer.de +* \note +* \warning +*/ + + +// [from gNB coding] +#include "PHY/defs_gNB.h" +#include "PHY/phy_extern.h" +#include "PHY/CODING/coding_extern.h" +#include "PHY/CODING/coding_defs.h" +#include "PHY/CODING/lte_interleaver_inline.h" +#include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h" +#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" +#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_TRANSPORT/nr_ulsch.h" +#include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "SCHED_NR/sched_nr.h" +#include "defs.h" +#include "common/utils/LOG/vcd_signal_dumper.h" +#include "common/utils/LOG/log.h" +#include +//#define DEBUG_ULSCH_DECODING + +#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 + +static uint64_t nb_total_decod =0; +static uint64_t nb_error_decod =0; + +//extern double cpuf; + +void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch) +{ + + int i,r; + + if (ulsch) { + for (i=0; iharq_processes[i]) { + if (ulsch->harq_processes[i]->b) { + free16(ulsch->harq_processes[i]->b,MAX_NR_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->b = NULL; + } + for (r=0; rharq_processes[i]->c[r],(8448)*sizeof(uint8_t)); + ulsch->harq_processes[i]->c[r] = NULL; + } + for (r=0; rharq_processes[i]->d[r]) { + free16(ulsch->harq_processes[i]->d[r],(68*384)*sizeof(int16_t)); + ulsch->harq_processes[i]->d[r] = NULL; + } + } + for (r=0; r<(MAX_NUM_NR_ULSCH_SEGMENTS); r++) { + if (ulsch->harq_processes[i]->p_nrLDPC_procBuf[r]){ + nrLDPC_free_mem(ulsch->harq_processes[i]->p_nrLDPC_procBuf[r]); + ulsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL; + } + } + free16(ulsch->harq_processes[i],sizeof(NR_UL_gNB_HARQ_t)); + ulsch->harq_processes[i] = NULL; + } + } + free16(ulsch,sizeof(NR_gNB_ULSCH_t)); + ulsch = NULL; + } +} + + +NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag) +{ + + NR_gNB_ULSCH_t *ulsch; + uint8_t exit_flag = 0,i,r; + unsigned char bw_scaling =1; + + switch (N_RB_UL) { + case 106: + bw_scaling =2; + break; + + default: + bw_scaling =1; + break; + } + + ulsch = (NR_gNB_ULSCH_t *)malloc16(sizeof(NR_gNB_ULSCH_t)); + + if (ulsch) { + + memset(ulsch,0,sizeof(NR_gNB_ULSCH_t)); + + ulsch->max_ldpc_iterations = max_ldpc_iterations; + ulsch->Mlimit = 4; + + for (i=0; iharq_processes[i] = (NR_UL_gNB_HARQ_t *)malloc16(sizeof(NR_UL_gNB_HARQ_t)); + + if (ulsch->harq_processes[i]) { + + memset(ulsch->harq_processes[i],0,sizeof(NR_UL_gNB_HARQ_t)); + + ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling); + + if (ulsch->harq_processes[i]->b) + memset(ulsch->harq_processes[i]->b,0,MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling); + else + exit_flag=3; + + if (abstraction_flag == 0) { + for (r=0; rharq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem(); + + ulsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(8448*sizeof(uint8_t)); + + if (ulsch->harq_processes[i]->c[r]) + memset(ulsch->harq_processes[i]->c[r],0,8448*sizeof(uint8_t)); + else + exit_flag=2; + + ulsch->harq_processes[i]->d[r] = (int16_t*)malloc16((68*384)*sizeof(int16_t)); + + if (ulsch->harq_processes[i]->d[r]) + memset(ulsch->harq_processes[i]->d[r],0,(68*384)*sizeof(int16_t)); + else + exit_flag=2; + } + } + } else { + exit_flag=1; + } + } + + if (exit_flag==0) + return(ulsch); + } + + printf("new_gNB_ulsch with size %zu: exit_flag = %u\n",sizeof(NR_UL_gNB_HARQ_t), exit_flag); + free_gNB_ulsch(ulsch); + + return(NULL); +} + + +uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, + uint8_t UE_id, + short *ulsch_llr, + NR_DL_FRAME_PARMS *frame_parms, + uint32_t frame, + uint16_t nb_symb_sch, + uint8_t nr_tti_rx, + uint8_t harq_pid, + uint8_t is_crnti, + uint8_t llr8_flag) +{ + + uint32_t A,E; + uint32_t G; + uint32_t ret,offset; + int32_t no_iteration_ldpc, length_dec; + uint32_t r,r_offset=0,Kr=8424,Kr_bytes,K_bytes_F,err_flag=0; + uint8_t crc_type; + 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_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; + + t_nrLDPC_dec_params decParams; + t_nrLDPC_dec_params* p_decParams = &decParams; + t_nrLDPC_time_stats procTime; + 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; + 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; + + uint32_t i,j; + + __m128i *pv = (__m128i*)&z; + __m128i *pl = (__m128i*)&l; + + + if (!ulsch_llr) { + printf("ulsch_decoding.c: NULL ulsch_llr pointer\n"); + return(ulsch->max_ldpc_iterations); + } + + if (!harq_process) { + printf("ulsch_decoding.c: NULL harq_process pointer\n"); + return(ulsch->max_ldpc_iterations); + } + + if (!frame_parms) { + printf("ulsch_decoding.c: NULL frame_parms pointer\n"); + 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); + + A = harq_process->TBS; + ret = ulsch->max_ldpc_iterations; + + 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); + + if (harq_process->round == 0) { + + // This is a new packet, so compute quantities regarding segmentation + harq_process->B = A+24; + + // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F) + nr_segmentation(NULL, + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, // [hna] Z is Zc + &harq_process->F); + + p_decParams->Z = harq_process->Z; + +#ifdef DEBUG_ULSCH_DECODING + printf("ulsch decoding nr segmentation Z %d\n", p_decParams->Z); + if (!frame%100) + printf("K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl); +#endif + } + + Coderate = (float) A /(float) G; + + if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ + p_decParams->BG = 2; + if (Coderate < 0.3333) { + p_decParams->R = 15; + kc = 52; + } + else if (Coderate <0.6667) { + p_decParams->R = 13; + kc = 32; + } + else { + p_decParams->R = 23; + kc = 17; + } + } else { + p_decParams->BG = 1; + if (Coderate < 0.6667) { + p_decParams->R = 13; + kc = 68; + } + else if (Coderate <0.8889) { + p_decParams->R = 23; + kc = 35; + } + else { + p_decParams->R = 89; + kc = 27; + } + } + + //printf("coderate %f kc %d \n", Coderate, kc); + + + + p_decParams->numMaxIter = ulsch->max_ldpc_iterations; + p_decParams->outMode= 0; + + err_flag = 0; + r_offset = 0; + + unsigned char bw_scaling =1; + + switch (frame_parms->N_RB_UL) { + + case 106: + bw_scaling =2; + break; + + default: + bw_scaling =1; + break; + } + + if (harq_process->C > MAX_NUM_NR_ULSCH_SEGMENTS/bw_scaling) { + LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,MAX_NUM_NR_ULSCH_SEGMENTS/bw_scaling); + return((1+ulsch->max_ldpc_iterations)); + } +#ifdef DEBUG_ULSCH_DECODING + printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); +#endif + + opp_enabled=1; + + Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb" + Kr_bytes = Kr>>3; + + K_bytes_F = Kr_bytes-(harq_process->F>>3); + + Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, nfapi_ulsch_pdu_rel15->n_layers); + + for (r=0; rC; 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 + start_meas(ulsch_deinterleaving_stats); +#endif + + //////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + //////////////////////////// ulsch_llr =====> harq_process->e ////////////////////////////// + + nr_deinterleaving_ldpc(E, + nfapi_ulsch_pdu_rel15->Qm, + harq_process->e[r], + ulsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if gNB_TIMING_TRACE + stop_meas(ulsch_deinterleaving_stats); +#endif + +#if gNB_TIMING_TRACE + start_meas(ulsch_rate_unmatching_stats); +#endif + +#ifdef DEBUG_ULSCH_DECODING + LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n", + harq_pid,r, G, + Kr*3, + harq_process->TBS, + nfapi_ulsch_pdu_rel15->Qm, + nfapi_ulsch_pdu_rel15->number_rbs, + nfapi_ulsch_pdu_rel15->n_layers, + nfapi_ulsch_pdu_rel15->rv, + harq_process->round); +#endif + ////////////////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////// harq_process->e =====> harq_process->d ///////////////////////// + + if (nr_rate_matching_ldpc_rx(Ilbrm, + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->e[r], + harq_process->C, + nfapi_ulsch_pdu_rel15->rv, + (harq_process->round==0)?1:0, + E)==-1) { +#if gNB_TIMING_TRACE + stop_meas(ulsch_rate_unmatching_stats); +#endif + LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n"); + return(ulsch->max_ldpc_iterations); + } else { +#if gNB_TIMING_TRACE + stop_meas(ulsch_rate_unmatching_stats); +#endif + } + + r_offset += E; + +#ifdef DEBUG_ULSCH_DECODING + if (r==0) { + write_output("decoder_llr.m","decllr",ulsch_llr,G,1,0); + write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); + } + + printf("decoder input(segment %d) :",r); + int i; + for (i=0;i<(3*8*Kr_bytes)+12;i++) + printf("%d : %d\n",i,harq_process->d[r][i]); + printf("\n"); +#endif + + + // printf("Clearing c, %p\n",harq_process->c[r]); + memset(harq_process->c[r],0,Kr_bytes); + + // printf("done\n"); + if (harq_process->C == 1) { + crc_type = CRC24_A; + length_dec = harq_process->B; + } + else { + crc_type = CRC24_B; + length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; + } + + if (err_flag == 0) { + +#if gNB_TIMING_TRACE + start_meas(ulsch_turbo_decoding_stats); +#endif + + //LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A); + + + memset(pv,0,2*harq_process->Z*sizeof(int16_t)); + memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); + + for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) { + pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); + } + + for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) { + pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); + } + + for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) { + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// + + no_iteration_ldpc = nrLDPC_decoder(p_decParams, + (int8_t*)&pl[0], + llrProcBuf, + p_nrLDPC_procBuf[r], + p_procTime); + + if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { + printf("Segment %d CRC OK\n",r); + ret = 2; + } else { + printf("CRC NOK\n"); + ret = 1+ulsch->max_ldpc_iterations; + } + + nb_total_decod++; + if (no_iteration_ldpc > ulsch->max_ldpc_iterations){ + nb_error_decod++; + } + + ret=no_iteration_ldpc; + + for (int m=0; m < Kr>>3; m ++) { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } + +#ifdef DEBUG_ULSCH_DECODING + //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); + for (int k=0;k>3;k++) + printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); + printf("no_iterations_ldpc %d (ret %d)\n",no_iteration_ldpc,ret); + //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4); +#endif + +#if gNB_TIMING_TRACE + stop_meas(ulsch_turbo_decoding_stats); +#endif + } + + if ((err_flag == 0) && (ret>=(1+ulsch->max_ldpc_iterations))) { + // a Code segment is in error so break; + LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1); + err_flag = 1; + } + ////////////////////////////////////////////////////////////////////////////////////////// + } + + int32_t frame_rx_prev = frame; + int32_t tti_rx_prev = nr_tti_rx - 1; + if (tti_rx_prev < 0) { + frame_rx_prev--; + tti_rx_prev += 10*frame_parms->ttis_per_subframe; + } + frame_rx_prev = frame_rx_prev%1024; + + if (err_flag == 1) { + +#if gNB_DEBUG_TRACE + LOG_I(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", + phy_vars_gNB->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); +#endif + + // harq_process->harq_ack.ack = 0; + // harq_process->harq_ack.harq_id = harq_pid; + // harq_process->harq_ack.send_harq_status = 1; + // harq_process->errors[harq_process->round]++; + harq_process->round++; + + if (harq_process->round >= ulsch->Mlimit) { + harq_process->status = SCH_IDLE; + harq_process->round = 0; + harq_process->handled = 0; + ulsch->harq_mask &= ~(1 << harq_pid); + } + + if(is_crnti) { + LOG_D(PHY,"[gNB %d] ULSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", + phy_vars_gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->status,harq_process->round,ulsch->Mlimit,harq_process->TBS); + } + + harq_process->handled = 1; + return((1+ulsch->max_ldpc_iterations)); + + } else { + +#if gNB_DEBUG_TRACE + LOG_I(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n", + phy_vars_gNB->Mod_id,nr_tti_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); +#endif + + harq_process->status = SCH_IDLE; + harq_process->round = 0; + // harq_process->handled = 0; + ulsch->harq_mask &= ~(1 << harq_pid); + // harq_process->harq_ack.ack = 1; + // harq_process->harq_ack.harq_id = harq_pid; + // harq_process->harq_ack.send_harq_status = 1; + + if(is_crnti) + { + LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",phy_vars_gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->round,harq_process->TBS); + } + } + + // Reassembly of Transport block here + offset = 0; + Kr = harq_process->K; + Kr_bytes = Kr>>3; + + for (r=0; rC; r++) { + + memcpy(harq_process->b+offset, + harq_process->c[r], + Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); + + offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); + +#ifdef DEBUG_ULSCH_DECODING + printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes); + printf("copied %d bytes to b sequence (harq_pid %d)\n", + (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); + printf("b[0] = %x,c[%d] = %x\n", + harq_process->b[offset], + harq_process->F>>3, + harq_process->c[r]); +#endif + + } + + ulsch->last_iteration_cnt = ret; + + return(ret); +} \ No newline at end of file diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index f1a3ef42ab..f3cd1a29f3 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -52,9 +52,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, ncoef = 32767 - coef; -//#ifdef DEBUG_PHY - LOG_D(PHY,"AbsSubframe %d.%d: rx_offset (before) = %d\n",ue->proc.proc_rxtx[0].frame_rx%1024,subframe,ue->rx_offset); -//#endif //DEBUG_PHY + LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset); // we only use channel estimates from tx antenna 0 here @@ -122,8 +120,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, #ifdef DEBUG_PHY - LOG_D(PHY,"AbsSubframe %d.%d: ThreadId %d diff =%i rx_offset (final) = %i : clear %d,max_pos = %d,max_pos_fil = %d (peak %d) max_val %d target_pos %d \n", - ue->proc.proc_rxtx[ue->current_thread_id[subframe]].frame_rx, + LOG_D(PHY,"AbsSubframe %d: ThreadId %d diff =%i rx_offset (final) = %i : clear %d,max_pos = %d,max_pos_fil = %d (peak %d) max_val %d target_pos %d \n", subframe, ue->current_thread_id[subframe], diff, 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 942bf8c0ba..917734f8ec 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -29,47 +29,37 @@ #include "filt16a_32.h" #include "T.h" //#define DEBUG_PDSCH +//#define DEBUG_PDCCH -int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_id, +int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, uint8_t eNB_offset, unsigned char Ns, - unsigned char l, - unsigned char symbol) + unsigned char symbol, + int dmrss, + NR_UE_SSB *current_ssb) { int pilot[200] __attribute__((aligned(16))); unsigned char aarx; unsigned short k; unsigned int pilot_cnt; - int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*fr; - int ch_offset,symbol_offset; - int dmrss; + int16_t ch[2],*pil,*rxF; + int symbol_offset; - //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; - uint8_t nushift, ssb_index=0, n_hf=0; - int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset]; - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF; + uint8_t nushift; + uint8_t ssb_index=current_ssb->i_ssb; + uint8_t n_hf=current_ssb->n_hf; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; nushift = ue->frame_parms.Nid_cell%4; ue->frame_parms.nushift = nushift; - unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size; - if (ue->is_synchronized ==0 ) dmrss = symbol-1; - else dmrss = symbol-5; - - if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = ue->frame_parms.ofdm_symbol_size ; - else - ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; - - AssertFatal((symbol > 0 && symbol < 4 && ue->is_synchronized == 0) || - (symbol > 4 && symbol < 8 && ue->is_synchronized == 1), - "symbol %d is illegal for PBCH DM-RS (is_synchronized %d)\n", - symbol,ue->is_synchronized); + AssertFatal(dmrss >= 0 && dmrss < 3, + "symbol %d is illegal for PBCH DM-RS \n", + dmrss); symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; @@ -77,8 +67,175 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, k = nushift; #ifdef DEBUG_CH - printf("PBCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns>>1], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.Ncp,l,Ns,k, symbol); + printf("PBCH DMRS Correlation : ThreadId %d, eNB_offset %d , OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns>>1], eNB_offset,ue->frame_parms.ofdm_symbol_size, + ue->frame_parms.Ncp,Ns,k, symbol); +#endif + + // generate pilot + nr_pbch_dmrs_rx(dmrss,ue->nr_gold_pbch[n_hf][ssb_index], &pilot[0]); + + int re_offset = ssb_offset; + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + + pil = (int16_t *)&pilot[0]; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; + +#ifdef DEBUG_CH + printf("pbch ch est pilot addr %p RB_DL %d\n",&pilot[0], ue->frame_parms.N_RB_DL); + printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset); + printf("rxF addr %p\n", rxF); +#endif + //if ((ue->frame_parms.N_RB_DL&1)==0) { + + // Treat first 2 pilots specially (left edge) + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + current_ssb->c_re +=ch[0]; + current_ssb->c_im +=ch[1]; + +#ifdef DEBUG_CH + printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); +#endif + + pil+=2; + re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); + 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); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + current_ssb->c_re +=ch[0]; + current_ssb->c_im +=ch[1]; + +#ifdef DEBUG_CH + printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",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); + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; + + current_ssb->c_re +=ch[0]; + current_ssb->c_im +=ch[1]; + +#ifdef DEBUG_CH + printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",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); + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; + + for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt+=3) { + + // if (pilot_cnt == 30) + // rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)]; + + // 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); + 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); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + current_ssb->c_re +=ch[0]; + current_ssb->c_im +=ch[1]; + +#ifdef DEBUG_CH + printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,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); + 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); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + current_ssb->c_re +=ch[0]; + current_ssb->c_im +=ch[1]; + +#ifdef DEBUG_CH + 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); + 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); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + current_ssb->c_re +=ch[0]; + current_ssb->c_im +=ch[1]; + +#ifdef DEBUG_CH + printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,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); + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; + + } + + + //} + + } + return(0); +} + + +int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, + uint8_t eNB_offset, + unsigned char Ns, + unsigned char symbol, + int dmrss, + uint8_t ssb_index, + uint8_t n_hf) +{ + int pilot[200] __attribute__((aligned(16))); + unsigned char aarx; + unsigned short k; + unsigned int pilot_cnt; + int16_t ch[2],*pil,*rxF,*dl_ch,*fl,*fm,*fr; + int ch_offset,symbol_offset; + + //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; + + uint8_t nushift; + int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates[eNB_offset]; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; + + nushift = ue->frame_parms.Nid_cell%4; + ue->frame_parms.nushift = nushift; + unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; + if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size; + + if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage + ch_offset = ue->frame_parms.ofdm_symbol_size ; + else + ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; + + AssertFatal(dmrss >= 0 && dmrss < 3, + "symbol %d is illegal for PBCH DM-RS \n", + dmrss); + + symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; + + + k = nushift; + +#ifdef DEBUG_CH + printf("PBCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, + ue->frame_parms.Ncp,Ns,k, symbol); #endif switch (k) { @@ -121,7 +278,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, pil = (int16_t *)&pilot[0]; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; - + memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size)); if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), @@ -138,6 +295,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + #ifdef DEBUG_CH printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); @@ -155,6 +313,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + #ifdef DEBUG_CH printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif @@ -166,9 +326,6 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); 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); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - #ifdef DEBUG_CH printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif @@ -196,6 +353,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, } ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + #ifdef DEBUG_CH printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif @@ -214,6 +372,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + #ifdef DEBUG_CH 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 @@ -248,12 +407,10 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, //} } - return(0); } int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_id, uint8_t eNB_offset, unsigned char Ns, unsigned char l, @@ -271,8 +428,8 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; uint8_t nushift; - int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset]; - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF; + int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates[eNB_offset]; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; nushift = 1; ue->frame_parms.nushift = nushift; @@ -287,7 +444,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, k = coreset_start_subcarrier; #ifdef DEBUG_PDCCH - printf("PDCCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns>>1], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, + printf("PDCCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp,l,Ns,k, symbol); #endif @@ -459,16 +616,16 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, break; } - if( (Ns== 2) && (l == 0)) + if( (Ns== 1) && (l == 0)) { // do ifft of channel estimate for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) for (p=0; pframe_parms.nb_antenna_ports_eNB; p++) { - if (ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset][(p<<1)+aarx]) + if (ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates[eNB_offset][(p<<1)+aarx]) { - LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d \n", Ns, ue->current_thread_id[Ns>>1], l); - idft((int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset][(p<<1)+aarx][0], - (int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1); + LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d \n", Ns, ue->current_thread_id[Ns], l); + idft((int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates[eNB_offset][(p<<1)+aarx][0], + (int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1); } } } @@ -477,7 +634,6 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, } int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_id, uint8_t eNB_offset, unsigned char Ns, unsigned short p, @@ -496,8 +652,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; uint8_t nushift; - int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset]; - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF; + int **dl_ch_estimates =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].dl_ch_estimates[eNB_offset]; + int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF; nushift = (p>>1)&1; ue->frame_parms.nushift = nushift; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index ae4295a99b..29400bbdc7 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -43,7 +43,6 @@ \param symbol symbol within frame */ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_id, uint8_t eNB_offset, unsigned char Ns, unsigned char l, @@ -51,22 +50,30 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short coreset_start_subcarrier, unsigned short nb_rb_coreset); +int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, + uint8_t eNB_offset, + unsigned char Ns, + unsigned char symbol, + int dmrss, + NR_UE_SSB *current_ssb); + int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_id, - uint8_t eNB_offset, - unsigned char Ns, - unsigned char l, - unsigned char symbol); + uint8_t eNB_offset, + unsigned char Ns, + unsigned char symbol, + int dmrss, + uint8_t ssb_index, + uint8_t n_hf); int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, - uint8_t eNB_id, uint8_t eNB_offset, unsigned char Ns, unsigned short p, unsigned char l, unsigned char symbol, - unsigned short bwp_start_subcarrier, - unsigned short nb_rb_pdsch); + unsigned short bwp_start_subcarrier, + unsigned short nb_rb_pdsch); + void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, PHY_VARS_NR_UE *ue, diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c old mode 100755 new mode 100644 index cf419b0904..e280fcbdf7 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -30,9 +30,9 @@ * \warning */ #ifdef USER_MODE -#include -#include -#include + #include + #include + #include #endif #include "nr_transport_proto_ue.h" #include "PHY/CODING/nrPolar_tools/nr_polar_dci_defs.h" @@ -40,7 +40,7 @@ #include "PHY/CODING/coding_extern.h" #include "PHY/sse_intrin.h" -#include "assertions.h" +#include "assertions.h" #include "T.h" //#define DEBUG_DCI_ENCODING 1 @@ -56,8 +56,8 @@ #ifdef LOG_I -#undef LOG_I -#define LOG_I(A,B...) printf(B) + #undef LOG_I + #define LOG_I(A,B...) printf(B) #endif #ifdef NR_PDCCH_DCI_RUN @@ -73,16 +73,16 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, uint32_t coreset_nbr_rb, uint8_t reg_bundle_size_L, uint8_t coreset_interleaver_size_R, - uint8_t n_shift){ + uint8_t n_shift) { /* * This function will do demapping and deinterleaving from llr containing demodulated symbols * Demapping will regroup in REG and bundles * Deinterleaving will order the bundles - * + * * In the following example we can see the process. The llr contains the demodulated IQs, but they are not ordered from REG 0,1,2,.. * In e_rx (z) we will order the REG ids and group them into bundles. * Then we will put the bundles in the correct order as indicated in subclause 7.3.2.2 - * + * llr --------------------------> e_rx (z) ----> e_rx (z) | ... | ... @@ -91,7 +91,7 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, | ... | REG 5 | REG 2 - + | ... | ... | REG 25 @@ -99,7 +99,7 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, | ... | REG 4 | REG 1 - + | ... | ... ... ... | REG 24 (bundle 7) ... ... @@ -113,43 +113,47 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, uint16_t bundle_j=0, f_bundle_j=0,f_reg=0; uint32_t coreset_C=0; uint16_t index_z, index_llr; - int coreset_interleaved = 0; - if (reg_bundle_size_L!=0){ // interleaving will be done only if reg_bundle_size_L != 0 + + if (reg_bundle_size_L!=0) { // interleaving will be done only if reg_bundle_size_L != 0 coreset_interleaved=1; coreset_C = (uint32_t)((coreset_nbr_rb * coreset_time_dur)/ (coreset_interleaver_size_R*reg_bundle_size_L)); } else { reg_bundle_size_L=6; } - for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++){ - if ((reg%reg_bundle_size_L) == 0){ + for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) { + if ((reg%reg_bundle_size_L) == 0) { if (r == coreset_interleaver_size_R) { r=0; c++; } + bundle_j = (c*coreset_interleaver_size_R)+r; f_bundle_j = ((r*coreset_C)+c+n_shift)%((coreset_nbr_rb*coreset_time_dur)/reg_bundle_size_L); + if (coreset_interleaved==0) f_bundle_j=bundle_j; #ifdef NR_PDCCH_DCI_DEBUG printf("\n\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping_deinterleaving)-> [r=%d,c=%d] bundle_j(%d) interleaved at f_bundle_j(%d)\n",r,c,bundle_j,f_bundle_j); #endif } + f_reg = (f_bundle_j*reg_bundle_size_L)+(reg%reg_bundle_size_L); //index_z = 9*reg; index_z = 9*(uint16_t)floor(reg/coreset_time_dur) + (9*coreset_nbr_rb)*(reg%coreset_time_dur); //index_llr = 9*(((uint16_t)floor(f_reg/reg_bundle_size_L)+(f_reg)%coreset_time_dur))*(coreset_nbr_rb); index_llr = 9*((uint16_t)floor(f_reg/coreset_time_dur)+((f_reg%coreset_time_dur)*(coreset_nbr_rb))); - for (int i=0; i<9; i++){ - z[index_z + i] = llr[index_llr + i]; + for (int i=0; i<9; i++) { + z[index_z + i] = llr[index_llr + i]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_demapping_deinterleaving)-> [reg=%d,bundle_j=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n", - reg,bundle_j,(index_z + i),*(int16_t*) &z[index_z + i],*(1 + (int16_t*) &z[index_z + i]), - f_reg,f_bundle_j,(index_llr + i),*(int16_t*) &llr[index_llr + i], *(1 + (int16_t*) &llr[index_llr + i])); + reg,bundle_j,(index_z + i),*(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i]), + f_reg,f_bundle_j,(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i])); #endif } + if ((reg%reg_bundle_size_L) == 0) r++; } } @@ -158,31 +162,30 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, #ifdef NR_PDCCH_DCI_RUN int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, - int16_t *pdcch_llr, uint8_t symbol,uint32_t coreset_nbr_rb) { - - int16_t *rxF = (int16_t*) &rxdataF_comp[0][(symbol * coreset_nbr_rb * 12)]; + int16_t *pdcch_llr, uint8_t symbol,uint32_t coreset_nbr_rb) { + int16_t *rxF = (int16_t *) &rxdataF_comp[0][(symbol * coreset_nbr_rb * 12)]; int32_t i; int16_t *pdcch_llrp; - pdcch_llrp = &pdcch_llr[2 * symbol * coreset_nbr_rb * 9]; - if (!pdcch_llrp) { printf("pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); return (-1); } + #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llrp-pdcch_llr); #endif + //for (i = 0; i < (frame_parms->N_RB_DL * ((symbol == 0) ? 16 : 24)); i++) { for (i = 0; i < (coreset_nbr_rb * ((symbol == 0) ? 18 : 18)); i++) { - if (*rxF > 31) *pdcch_llrp = 31; else if (*rxF < -32) *pdcch_llrp = -32; else *pdcch_llrp = (*rxF); + #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_llr)-> llr logs: rb=%d i=%d *rxF:%d => *pdcch_llrp:%d\n",i/18,i,*rxF,*pdcch_llrp); #endif @@ -191,7 +194,6 @@ int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, } return (0); - } #endif @@ -200,13 +202,10 @@ int32_t nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, char *pdcch_llr, - uint8_t symbol) -{ - - int16_t *rxF= (int16_t*) &rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; + uint8_t symbol) { + int16_t *rxF= (int16_t *) &rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)]; int32_t i; char *pdcch_llr8; - pdcch_llr8 = &pdcch_llr[2*symbol*frame_parms->N_RB_DL*12]; if (!pdcch_llr8) { @@ -217,7 +216,6 @@ int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, // printf("pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llr8-pdcch_llr); for (i=0; i<(frame_parms->N_RB_DL*((symbol==0) ? 16 : 24)); i++) { - if (*rxF>31) *pdcch_llr8=31; else if (*rxF<-32) @@ -231,7 +229,6 @@ int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, } return(0); - } //__m128i avg128P; @@ -240,9 +237,7 @@ int32_t pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, void pdcch_channel_level(int32_t **dl_ch_estimates_ext, NR_DL_FRAME_PARMS *frame_parms, int32_t *avg, - uint8_t nb_rb) -{ - + uint8_t nb_rb) { int16_t rb; uint8_t aarx; #if defined(__x86_64__) || defined(__i386__) @@ -252,40 +247,38 @@ void pdcch_channel_level(int32_t **dl_ch_estimates_ext, int16x8_t *dl_ch128; int32x4_t *avg128P; #endif + for (aarx=0; aarxnb_antennas_rx; aarx++) { //clear average level #if defined(__x86_64__) || defined(__i386__) avg128P = _mm_setzero_si128(); dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][0]; #elif defined(__arm__) - #endif + for (rb=0; rb<(nb_rb*3)>>2; rb++) { - #if defined(__x86_64__) || defined(__i386__) avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[0],dl_ch128[0])); avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[1],dl_ch128[1])); avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[2],dl_ch128[2])); #elif defined(__arm__) - #endif // for (int i=0;i<24;i+=2) printf("pdcch channel re %d (%d,%d)\n",(rb*12)+(i>>1),((int16_t*)dl_ch128)[i],((int16_t*)dl_ch128)[i+1]); dl_ch128+=3; /* - if (rb==0) { - print_shorts("dl_ch128",&dl_ch128[0]); - print_shorts("dl_ch128",&dl_ch128[1]); - print_shorts("dl_ch128",&dl_ch128[2]); - } + if (rb==0) { + print_shorts("dl_ch128",&dl_ch128[0]); + print_shorts("dl_ch128",&dl_ch128[1]); + print_shorts("dl_ch128",&dl_ch128[2]); + } */ } - - DevAssert( nb_rb ); - avg[aarx] = (((int32_t*)&avg128P)[0] + - ((int32_t*)&avg128P)[1] + - ((int32_t*)&avg128P)[2] + - ((int32_t*)&avg128P)[3])/(nb_rb*9); + DevAssert( nb_rb ); + avg[aarx] = (((int32_t *)&avg128P)[0] + + ((int32_t *)&avg128P)[1] + + ((int32_t *)&avg128P)[2] + + ((int32_t *)&avg128P)[3])/(nb_rb*9); // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); } @@ -293,11 +286,10 @@ void pdcch_channel_level(int32_t **dl_ch_estimates_ext, _mm_empty(); _m_empty(); #endif - } #if defined(__x86_64) || defined(__i386__) -__m128i mmtmpPD0,mmtmpPD1,mmtmpPD2,mmtmpPD3; + __m128i mmtmpPD0,mmtmpPD1,mmtmpPD2,mmtmpPD3; #elif defined(__arm__) #endif @@ -317,7 +309,6 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, uint64_t coreset_freq_dom, uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { - /* * This function is demapping DM-RS PDCCH RE * Implementing 38.211 Section 7.4.1.3.2 Mapping to physical resources @@ -335,7 +326,6 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, #define NBR_RE_PER_RB_WITH_DMRS 12 // after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH #define NBR_RE_PER_RB_WITHOUT_DMRS 9 - uint16_t c_rb, nb_rb = 0; // this variable will be incremented by 1 each time a bit set to '0' is found in coreset_freq_dom bitmap uint16_t offset_discontiguous=0; @@ -344,21 +334,18 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, int32_t *dl_ch0, *dl_ch0_ext, *rxF, *rxF_ext; int nushiftmod3 = frame_parms->nushift % 3; uint8_t symbol_mod; - symbol_mod = (symbol >= (7 - frame_parms->Ncp)) ? symbol - (7 - frame_parms->Ncp) : symbol; c_rb = n_BWP_start; // c_rb is the common resource block: RB within the BWP #ifdef DEBUG_DCI_DECODING LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod); #endif - - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - if (high_speed_flag == 1){ + if (high_speed_flag == 1) { dl_ch0 = &dl_ch_estimates[aarx][(symbol * (frame_parms->ofdm_symbol_size))]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0 = &dl_ch_estimates[aarx = (%d)][ (symbol * (frame_parms->ofdm_symbol_size (%d))) = (%d)]\n", - aarx,frame_parms->ofdm_symbol_size,(symbol * (frame_parms->ofdm_symbol_size))); + aarx,frame_parms->ofdm_symbol_size,(symbol * (frame_parms->ofdm_symbol_size))); #endif } else { dl_ch0 = &dl_ch_estimates[aarx][0]; @@ -370,15 +357,14 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", - aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)); + aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)); #endif rxF_ext = &rxdataF_ext[aarx][symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)]; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", - aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)); + aarx,symbol * (coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS)); printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> (for symbol=%d, aarx=%d), symbol_mod=%d, nushiftmod3=%d \n",symbol,aarx,symbol_mod,nushiftmod3); #endif - /* * The following for loop handles treatment of PDCCH contained in table rxdataF (in frequency domain) * In NR the PDCCH IQ symbols are contained within RBs in the CORESET defined by higher layers which is located within the BWP @@ -396,7 +382,6 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, * then the IQ symbol is going to be found at the position 0+c_rb-N_RB_DL/2 in rxdataF and * we have to point the pointer at (1+c_rb-N_RB_DL/2) in rxdataF */ - #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> n_BWP_start=%d, coreset_nbr_rb=%d\n",n_BWP_start,coreset_nbr_rb); #endif @@ -405,38 +390,42 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, //c_rb_tmp = 0; if (((c_rb - n_BWP_start) % BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN)==0) { bitcnt_coreset_freq_dom ++; - while ((((coreset_freq_dom & 0x1FFFFFFFFFFF) >> (CORESET_FREQ_DOMAIN_BITMAP_SIZE - bitcnt_coreset_freq_dom)) & 0x1)== 0){ // 46 -> 45 is number of bits in coreset_freq_dom + + while ((((coreset_freq_dom & 0x1FFFFFFFFFFF) >> (CORESET_FREQ_DOMAIN_BITMAP_SIZE - bitcnt_coreset_freq_dom)) & 0x1)== 0) { // 46 -> 45 is number of bits in coreset_freq_dom // next 6 RB are not part of the CORESET within the BWP as bit in coreset_freq_dom is set to 0 bitcnt_coreset_freq_dom ++; //c_rb_tmp = c_rb_tmp + 6; c_rb = c_rb + BIT_TO_NBR_RB_CORESET_FREQ_DOMAIN; offset_discontiguous ++; #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> we entered here as coreset_freq_dom=%lx (bit %d) is 0, coreset_freq_domain is discontiguous\n",coreset_freq_dom,(46 - bitcnt_coreset_freq_dom)); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> we entered here as coreset_freq_dom=%lx (bit %d) is 0, coreset_freq_domain is discontiguous\n",coreset_freq_dom, + (46 - bitcnt_coreset_freq_dom)); #endif } } - //c_rb = c_rb + c_rb_tmp; + //c_rb = c_rb + c_rb_tmp; #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> c_rb=%d\n",c_rb); #endif + rxF=NULL; + // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET (c_rb = n_BWP_start) if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): even case rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; - #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", - c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } + if ((c_rb >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in even case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))); #endif //rxF = &rxdataF[aarx][(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol @@ -445,46 +434,47 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, // c_rb,aarx,(1 + 12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))); //#endif } - if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ + + if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): odd case rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; - #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is lower or equal than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", - c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is lower or equal than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } - if ((c_rb > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ + + if ((c_rb > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF just after the first IQ symbols of the RB containing DC rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - frame_parms->N_RB_DL) - 5 + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", - c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is higher than half N_RB_DL (not DC) -> rxF = &rxdataF[aarx = (%d)][(12*(c_rb - frame_parms->N_RB_DL) - 5 + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))); #endif } - if ((c_rb == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)){ // treatment of RB containing the DC + + if ((c_rb == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // treatment of RB containing the DC // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC) // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the end of the table) rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))]; - #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL + 1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", - c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL + 1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", + c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); #endif /*if (symbol_mod > 300) { // this if is going to be removed as DM-RS signals are present in all symbols of PDCCH for (i = 0; i < 6; i++) { - dl_ch0_ext[i] = dl_ch0[i]; - rxF_ext[i] = rxF[i]; + dl_ch0_ext[i] = dl_ch0[i]; + rxF_ext[i] = rxF[i]; } rxF = &rxdataF[aarx][(symbol * (frame_parms->ofdm_symbol_size))]; // we point at the 1st part of the rxdataF in symbol #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", - c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", + c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); #endif for (; i < 12; i++) { - dl_ch0_ext[i] = dl_ch0[i]; - rxF_ext[i] = rxF[(1 + i - 6)]; + dl_ch0_ext[i] = dl_ch0[i]; + rxF_ext[i] = rxF[(1 + i - 6)]; } nb_rb++; dl_ch0_ext += 12; @@ -494,6 +484,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, c_rb++; } else {*/ j = 0; + for (i = 0; i < 6; i++) { //treating first part of the RB note that i=5 would correspond to DC. We treat it in NR if ((i != 1) && (i != 5)) { dl_ch0_ext[j] = dl_ch0[i]; @@ -501,12 +492,14 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } + // then we point at the begining of the symbol part of rxdataF do process second part of RB rxF = &rxdataF[aarx][((symbol * (frame_parms->ofdm_symbol_size)))]; // we point at the 1st part of the rxdataF in symbol #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", - c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> in odd case c_rb (%d) is half N_RB_DL +1 we treat DC case -> rxF = &rxdataF[aarx = (%d)][(symbol * (frame_parms->ofdm_symbol_size)) = (%d)]\n", + c_rb,aarx,(symbol * (frame_parms->ofdm_symbol_size))); #endif + for (; i < 12; i++) { if ((i != 9)) { dl_ch0_ext[j] = dl_ch0[i]; @@ -514,35 +507,36 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } + nb_rb++; dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; dl_ch0 += 12; - //rxF += 7; - //c_rb++; - //n_BWP_start++; // We have to increment this variable here to be consequent in the for loop afterwards + //rxF += 7; + //c_rb++; + //n_BWP_start++; // We have to increment this variable here to be consequent in the for loop afterwards //} } else { // treatment of any RB that does not contain the DC /*if (symbol_mod > 300) { memcpy(dl_ch0_ext, dl_ch0, 12 * sizeof(int32_t)); for (i = 0; i < 12; i++) { - rxF_ext[i] = rxF[i]; + rxF_ext[i] = rxF[i]; } nb_rb++; dl_ch0_ext += 12; rxF_ext += 12; dl_ch0 += 12; //rxF += 12; - } else {*/ + } else {*/ j = 0; + for (i = 0; i < 12; i++) { if ((i != 1) && (i != 5) && (i != 9)) { rxF_ext[j] = rxF[i]; - #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)\n", - c_rb, i, j, *(short *) &rxF_ext[j],*(1 + (short*) &rxF_ext[j]), i, - *(short *) &rxF[i], *(1 + (short*) &rxF[i])); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d)\n", + c_rb, i, j, *(short *) &rxF_ext[j],*(1 + (short *) &rxF_ext[j]), i, + *(short *) &rxF[i], *(1 + (short *) &rxF[i])); #endif dl_ch0_ext[j] = dl_ch0[i]; //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> ch %d => dl_ch0(%d,%d)\n", i, *(short *) &dl_ch0[i], *(1 + (short*) &dl_ch0[i])); @@ -550,17 +544,18 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, j++; } else { #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t\t <==> DM-RS PDCCH, this is a pilot symbol\n", - c_rb, i, j, *(short *) &rxF_ext[j], *(1 + (short*) &rxF_ext[j]), i, - *(short *) &rxF[i], *(1 + (short*) &rxF[i])); + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_extract_rbs_single)-> RB[c_rb %d] \t RE[re %d] => rxF_ext[%d]=(%d,%d)\t rxF[%d]=(%d,%d) \t\t <==> DM-RS PDCCH, this is a pilot symbol\n", + c_rb, i, j, *(short *) &rxF_ext[j], *(1 + (short *) &rxF_ext[j]), i, + *(short *) &rxF[i], *(1 + (short *) &rxF[i])); #endif } } + nb_rb++; dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; dl_ch0 += 12; - //rxF += 12; + //rxF += 12; //} } } @@ -578,38 +573,31 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, NR_DL_FRAME_PARMS *frame_parms, uint8_t symbol, uint8_t output_shift, - uint32_t coreset_nbr_rb) -{ - + uint32_t coreset_nbr_rb) { uint16_t rb; //,nb_rb=20; uint8_t aarx; - #if defined(__x86_64__) || defined(__i386__) __m128i mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; #elif defined(__arm__) int16x8_t mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; #endif - #if defined(__x86_64__) || defined(__i386__) __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; #elif defined(__arm__) - #endif for (aarx=0; aarxnb_antennas_rx; aarx++) { - #if defined(__x86_64__) || defined(__i386__) dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*coreset_nbr_rb*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*coreset_nbr_rb*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[aarx][symbol*coreset_nbr_rb*12]; //printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]); //printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol); - //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]); - + //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]); #elif defined(__arm__) // to be filled in #endif - + for (rb=0; rb<(coreset_nbr_rb*3)>>2; rb++) { //printf("rb %d\n",rb); #if defined(__x86_64__) || defined(__i386__) @@ -619,7 +607,7 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1)); - mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]); + mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i *)&conjugate[0]); // print_ints("im",&mmtmpP1); mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[0]); // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit) @@ -635,13 +623,12 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, //print_shorts("rx:",rxdataF128); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rxdataF_comp128); - // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1)); - mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]); + mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i *)&conjugate[0]); mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[1]); // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit) mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift); @@ -652,13 +639,12 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, //print_shorts("rx:",rxdataF128+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rxdataF_comp128+1); - // multiply by conjugated channel mmtmpP0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); // mmtmpP0 contains real part of 4 consecutive outputs (32-bit) mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1)); - mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]); + mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i *)&conjugate[0]); mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[2]); // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit) mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift); @@ -670,26 +656,24 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, //print_shorts("rx:",rxdataF128+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rxdataF_comp128+2); - #ifdef NR_PDCCH_DCI_DEBUG + for (int i=0; i<12 ; i++) - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n", - (rb*12)+i, ((short *)rxdataF128)[i<<1],((short*)rxdataF128)[1+(i<<1)], - (rb*12)+i, ((short *)dl_ch128)[i<<1],((short*)dl_ch128)[1+(i<<1)], - (rb*12)+i, ((short *)rxdataF_comp128)[i<<1],((short*)rxdataF_comp128)[1+(i<<1)]); - + printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_channel_compensation)-> rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n", + (rb*12)+i, ((short *)rxdataF128)[i<<1],((short *)rxdataF128)[1+(i<<1)], + (rb*12)+i, ((short *)dl_ch128)[i<<1],((short *)dl_ch128)[1+(i<<1)], + (rb*12)+i, ((short *)rxdataF_comp128)[i<<1],((short *)rxdataF_comp128)[1+(i<<1)]); + #endif - dl_ch128+=3; rxdataF128+=3; rxdataF_comp128+=3; - - #elif defined(__arm__) // to be filled in #endif } } + #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); @@ -699,10 +683,7 @@ void nr_pdcch_channel_compensation(int32_t **rxdataF_ext, void pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, - uint8_t symbol) -{ - - + uint8_t symbol) { #if defined(__x86_64__) || defined(__i386__) __m128i *rxdataF_comp128_0,*rxdataF_comp128_1; #elif defined(__arm__) @@ -718,6 +699,7 @@ void pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12]; #endif + // MRC on each re of rb for (i=0; iN_RB_DL*3; i++) { #if defined(__x86_64__) || defined(__i386__) @@ -732,24 +714,17 @@ void pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, _mm_empty(); _m_empty(); #endif - } void pdcch_siso(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, - uint8_t l) -{ - - + uint8_t l) { uint8_t rb,re,jj,ii; - jj=0; ii=0; for (rb=0; rbN_RB_DL; rb++) { - for (re=0; re<12; re++) { - rxdataF_comp[0][jj++] = rxdataF_comp[0][ii]; ii++; } @@ -772,19 +747,19 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, int nb_coreset_active, uint16_t symbol_mon, NR_SEARCHSPACE_TYPE_t searchSpaceType) { - NR_UE_COMMON *common_vars = &ue->common_vars; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]]; NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; - int do_common; + if (searchSpaceType == common) do_common=1; + if (searchSpaceType == ue_specific) do_common=0; + uint8_t log2_maxh, aarx; int32_t avgs; int32_t avgP[4]; - // number of RB (1 symbol) or REG (12 RE) in one CORESET: higher-layer parameter CORESET-freq-dom // (bit map 45 bits: each bit indicates 6 RB in CORESET -> 1 bit MSB indicates PRB 0..6 are part of CORESET) uint64_t coreset_freq_dom = pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources; @@ -800,12 +775,11 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, //int tci_statesPDCCH = pdcch_vars2->coreset[nb_coreset_active].tciStatesPDCCH; //int tci_present = pdcch_vars2->coreset[nb_coreset_active].tciPresentInDCI; uint16_t pdcch_DMRS_scrambling_id = pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID; - // The UE can be assigned 4 different BWP but only one active at a time. // For each BWP the number of CORESETs is limited to 3 (including initial CORESET Id=0 -> ControlResourceSetId (0..maxNrofControlReourceSets-1) (0..12-1) //uint32_t n_BWP_start = 0; //uint32_t n_rb_offset = 0; - uint32_t n_rb_offset = pdcch_vars2->coreset[nb_coreset_active].rb_offset+(int)floor(frame_parms->ssb_start_subcarrier/NR_NB_SC_PER_RB); + uint32_t n_rb_offset = pdcch_vars2->coreset[nb_coreset_active].rb_offset/*+(int)floor(frame_parms->ssb_start_subcarrier/NR_NB_SC_PER_RB)*/; // start time position for CORESET // parameter symbol_mon is a 14 bits bitmap indicating monitoring symbols within a slot uint8_t start_symbol = 0; @@ -818,13 +792,12 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, i=14; } } - + #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol); - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) \n", - coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R); + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) scrambling_ID=(%d) \n", + coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R,pdcch_DMRS_scrambling_id); #endif - // // according to 38.213 v15.1.0: a PDCCH monitoring pattern within a slot, // indicating first symbol(s) of the control resource set within a slot @@ -833,14 +806,12 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, // at the moment we do not implement this and start_symbol is always 0 // note that the bitmap symbol_mon may indicate several monitoring times within a same slot (symbols 0..13) // this may lead to a modification in ue scheduler - // indicates the number of active CORESETs for the current BWP to decode PDCCH: max is 3 (this variable is not useful here, to be removed) //uint8_t coreset_nbr_act; // indicates the number of REG contained in the PDCCH (number of RBs * number of symbols, in CORESET) uint8_t coreset_nbr_reg; uint32_t coreset_C; uint32_t coreset_nbr_rb = 0; - // for (int j=0; j < coreset_nbr_act; j++) { // for each active CORESET (max number of active CORESETs in a BWP is 3), // we calculate the number of RB for each CORESET bitmap @@ -848,10 +819,12 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld)\n",coreset_freq_dom); #endif int i; //for each bit in the coreset_freq_dom bitmap + for (i = 0; i < 45; i++) { // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_rb++; } + coreset_nbr_rb = 6 * coreset_nbr_rb; // coreset_nbr_rb has to be multiplied by 6 to indicate the number of PRB or REG(=12 RE) within the CORESET #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld,%lx), coreset_nbr_rb=%d\n", coreset_freq_dom,coreset_freq_dom,coreset_nbr_rb); @@ -860,16 +833,13 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, coreset_C = (uint32_t)(coreset_nbr_reg / (reg_bundle_size_L * coreset_interleaver_size_R)); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_nbr_rb=%d, coreset_nbr_reg=%d, coreset_C=(%d/(%d*%d))=%d\n", - coreset_nbr_rb, coreset_nbr_reg, coreset_nbr_reg, reg_bundle_size_L,coreset_interleaver_size_R, coreset_C); + coreset_nbr_rb, coreset_nbr_reg, coreset_nbr_reg, reg_bundle_size_L,coreset_interleaver_size_R, coreset_C); #endif for (int s = start_symbol; s < (start_symbol + coreset_time_dur); s++) { - - - #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_extract_rbs_single(is_secondary_ue=%d) to remove DM-RS PDCCH\n", - is_secondary_ue); + is_secondary_ue); printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); #endif nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[nr_tti_rx]].rxdataF, @@ -882,7 +852,6 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, coreset_freq_dom, coreset_nbr_rb, n_rb_offset); - #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",avgP); printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); @@ -893,13 +862,14 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, avgP, coreset_nbr_rb); avgs = 0; + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) avgs = cmax(avgs, avgP[aarx]); + log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; #ifdef UE_DEBUG_TRACE LOG_D(PHY,"nr_tti_rx %d: pdcch log2_maxh = %d (%d,%d)\n",nr_tti_rx,log2_maxh,avgP[0],avgs); #endif - #if T_TRACER T(T_UE_PHY_PDCCH_ENERGY, T_INT(eNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_tti_rx), T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); @@ -917,8 +887,6 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, s, log2_maxh, coreset_nbr_rb); // log2_maxh+I0_shift - - #ifdef DEBUG_PHY if (nr_tti_rx==5) @@ -929,7 +897,7 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, if (frame_parms->nb_antennas_rx > 1) { #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", - frame_parms->nb_antennas_rx); + frame_parms->nb_antennas_rx); #endif pdcch_detection_mrc(frame_parms, pdcch_vars[eNB_id]->rxdataF_comp,s); } @@ -939,11 +907,10 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> in nr_pdcch_llr(rxdataF_comp -> llr)\n"); #endif nr_pdcch_llr(frame_parms, - pdcch_vars[eNB_id]->rxdataF_comp, - pdcch_vars[eNB_id]->llr, - s, - coreset_nbr_rb); - + pdcch_vars[eNB_id]->rxdataF_comp, + pdcch_vars[eNB_id]->llr, + s, + coreset_nbr_rb); #if T_TRACER /* T(T_UE_PHY_PDCCH_IQ, T_INT(frame_parms->N_RB_DL), T_INT(frame_parms->N_RB_DL), @@ -954,36 +921,30 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, #ifdef DEBUG_DCI_DECODING printf("demapping: nr_tti_rx %d, mi %d, tdd_config %d\n",nr_tti_rx,get_mi(frame_parms,nr_tti_rx),frame_parms->tdd_config); #endif - } - #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we enter nr_pdcch_demapping_deinterleaving()\n"); #endif - - nr_pdcch_demapping_deinterleaving((uint32_t*) pdcch_vars[eNB_id]->llr, - (uint32_t*) pdcch_vars[eNB_id]->e_rx, - frame_parms, - coreset_time_dur, - coreset_nbr_rb, - reg_bundle_size_L, - coreset_interleaver_size_R, - n_shift); - - + nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars[eNB_id]->llr, + (uint32_t *) pdcch_vars[eNB_id]->e_rx, + frame_parms, + coreset_time_dur, + coreset_nbr_rb, + reg_bundle_size_L, + coreset_interleaver_size_R, + n_shift); nr_pdcch_unscrambling(pdcch_vars[eNB_id]->crnti, - frame_parms, - nr_tti_rx, - pdcch_vars[eNB_id]->e_rx, - coreset_time_dur*coreset_nbr_rb*9*2, - // get_nCCE(n_pdcch_symbols, frame_parms, mi) * 72, - pdcch_DMRS_scrambling_id, - do_common); + frame_parms, + nr_tti_rx, + pdcch_vars[eNB_id]->e_rx, + coreset_time_dur*coreset_nbr_rb*9*2, + // get_nCCE(n_pdcch_symbols, frame_parms, mi) * 72, + pdcch_DMRS_scrambling_id, + do_common); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> we end nr_pdcch_unscrambling()\n"); #endif - #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> Ending nr_rx_pdcch() function\n"); #endif @@ -994,25 +955,23 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, void pdcch_scrambling(NR_DL_FRAME_PARMS *frame_parms, - uint8_t nr_tti_rx, - uint8_t *e, - uint32_t length) { + uint8_t nr_tti_rx, + uint8_t *e, + uint32_t length) { int i; uint8_t reset; uint32_t x1, x2, s=0; - reset = 1; // x1 is set in lte_gold_generic - x2 = (nr_tti_rx<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 - + for (i=0; i>(i&0x1f))&1)); if (e[i] != 2) // element is 2 e[i] = (e[i]&1) ^ ((s>>(i&0x1f))&1); @@ -1023,33 +982,34 @@ void pdcch_scrambling(NR_DL_FRAME_PARMS *frame_parms, #ifdef NR_PDCCH_DCI_RUN void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, - int16_t *z, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common) { - + int16_t *z, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common) { int i; uint8_t reset; uint32_t x1, x2, s = 0; uint16_t n_id; //{0,1,...,65535} uint32_t n_rnti; - reset = 1; + // x1 is set in first call to lte_gold_generic //do_common=1; - if (do_common){ + if (do_common) { n_id = frame_parms->Nid_cell; n_rnti = 0; } else { n_id = pdcch_DMRS_scrambling_id; n_rnti = (uint32_t)crnti; } + //x2 = ((n_rnti * (1 << 16)) + n_id)%(1 << 31); //uint32_t puissance_2_16 = ((1<<16)*n_rnti)+n_id; //uint32_t puissance_2_31= (1<<30)*2; //uint32_t calc_x2=puissance_2_16%puissance_2_31; x2 = (((1<<16)*n_rnti)+n_id); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3 - // x2 = (nr_tti_rx << 9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 + // x2 = (nr_tti_rx << 9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2 #ifdef NR_PDCCH_DCI_DEBUG - printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> (c_init=%d, n_id=%d, n_rnti=%d, length=%d)\n",x2,n_id,n_rnti,length); + //printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> (c_init=%d, n_id=%d, n_rnti=%d, length=%d)\n",x2,n_id,n_rnti,length); #endif + for (i = 0; i < length; i++) { if ((i & 0x1f) == 0) { s = lte_gold_generic(&x1, &x2, reset); @@ -1057,107 +1017,99 @@ void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8 reset = 0; } - - /* -#ifdef NR_PDCCH_DCI_DEBUG + /* + #ifdef NR_PDCCH_DCI_DEBUG if (i%2 == 0) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> unscrambling %d : scrambled_z=%d, => ", - i,*(char*) &z[(int)floor(i/2)]); + i,*(char*) &z[(int)floor(i/2)]); if (i%2 == 1) printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> unscrambling %d : scrambled_z=%d, => ", - i,*(1 + (char*) &z[(int)floor(i/2)])); -#endif + i,*(1 + (char*) &z[(int)floor(i/2)])); + #endif if (((s >> (i % 32)) & 1) == 1){ if (i%2 == 0) *(char*) &z[(int)floor(i/2)] = -(*(char*) &z[(int)floor(i/2)]); if (i%2 == 1) *(1 + (char*) &z[(int)floor(i/2)]) = -(*(1 + (char*) &z[(int)floor(i/2)])); } //llr[i] = -llr[i]; //llr[i] = (-1)*llr[i]; -#ifdef NR_PDCCH_DCI_DEBUG + #ifdef NR_PDCCH_DCI_DEBUG if (i%2 == 0) printf("unscrambled_z=%d\n",*(char*) &z[(int)floor(i/2)]); if (i%2 == 1) printf("unscrambled_z=%d\n",*(1 + (char*) &z[(int)floor(i/2)])); -#endif + #endif */ #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_pdcch_unscrambling)-> unscrambling %d : scrambled_z=%d, => ", - i,z[i]); + i,z[i]); #endif + if (((s >> (i % 32)) & 1) == 1) z[i] = -z[i]; + #ifdef NR_PDCCH_DCI_DEBUG printf("unscrambled_z=%d\n",z[i]); #endif } - } #endif #ifdef NR_PDCCH_DCI_RUN -void nr_dci_decoding_procedure0(int s, - int p, - int coreset_time_dur, - uint16_t coreset_nbr_rb, - NR_UE_PDCCH **pdcch_vars, - int do_common, - uint8_t nr_tti_rx, - NR_DCI_ALLOC_t *dci_alloc, - int16_t eNB_id, - uint8_t current_thread_id, - NR_DL_FRAME_PARMS *frame_parms, - //uint8_t mi, - uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES], - uint8_t L, - NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t format_css, - NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t format_uss, - uint8_t sizeof_bits, - uint8_t sizeof_bytes, - uint8_t *dci_cnt, - crc_scrambled_t *crc_scrambled, - format_found_t *format_found, - uint16_t pdcch_DMRS_scrambling_id, - uint32_t *CCEmap0, - uint32_t *CCEmap1, - uint32_t *CCEmap2) { - - uint16_t crc, CCEind, nCCE[3]; +void nr_dci_decoding_procedure0(int s, + int p, + int coreset_time_dur, + uint16_t coreset_nbr_rb, + NR_UE_PDCCH **pdcch_vars, + int do_common, + uint8_t nr_tti_rx, + NR_DCI_ALLOC_t *dci_alloc, + int16_t eNB_id, + uint8_t current_thread_id, + NR_DL_FRAME_PARMS *frame_parms, + //uint8_t mi, + uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES], + uint8_t L, + NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t format_css, + NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t format_uss, + uint8_t sizeof_bits, + uint8_t sizeof_bytes, + uint8_t *dci_cnt, + crc_scrambled_t *crc_scrambled, + format_found_t *format_found, + uint16_t pdcch_DMRS_scrambling_id, + uint32_t *CCEmap0, + uint32_t *CCEmap1, + uint32_t *CCEmap2) { + uint32_t crc, CCEind, nCCE[3]; uint32_t *CCEmap = NULL, CCEmap_mask = 0; uint8_t L2 = (1 << L); unsigned int Yk, nb_candidates = 0, i, m; unsigned int CCEmap_cand; - - int8_t decoderState=0; - + uint32_t decoderState=0; // A[p], p is the current active CORESET - uint16_t A[3]={39827,39829,39839}; + uint16_t A[3]= {39827,39829,39839}; //Table 10.1-2: Maximum number of PDCCH candidates per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} uint8_t m_max_slot_pdcch_Table10_1_2 [4] = {44,36,22,20}; //Table 10.1-3: Maximum number of non-overlapped CCEs per slot and per serving cell as a function of the subcarrier spacing value 2^mu*15 KHz, mu {0,1,2,3} //uint8_t cce_max_slot_pdcch_Table10_1_3 [4] = {56,56,48,32}; - int coreset_nbr_cce_per_symbol=0; - - t_nrPolar_paramsPtr nrPolar_params = pdcch_vars[eNB_id]->nrPolar_params; - #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found is %d \n", *format_found); #endif - //if (mode == NO_DCI) { // #ifdef NR_PDCCH_DCI_DEBUG // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> skip DCI decoding: expect no DCIs at nr_tti_rx %d in current searchSpace\n", nr_tti_rx); // #endif // return; //} - #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> frequencyDomainResources=%lx, duration=%d\n", - pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources, pdcch_vars[eNB_id]->coreset[p].duration); + pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources, pdcch_vars[eNB_id]->coreset[p].duration); #endif - + // nCCE = get_nCCE(pdcch_vars[eNB_id]->num_pdcch_symbols, frame_parms, mi); for (int i = 0; i < 45; i++) { // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' if (((pdcch_vars[eNB_id]->coreset[p].frequencyDomainResources & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_cce_per_symbol++; } + nCCE[p] = pdcch_vars[eNB_id]->coreset[p].duration*coreset_nbr_cce_per_symbol; // 1 CCE = 6 RB // p is the current CORESET we are currently monitoring (among the 3 possible CORESETs in a BWP) // the number of CCE in the current CORESET is: @@ -1168,46 +1120,52 @@ void nr_dci_decoding_procedure0(int s, printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> nCCE[%d]=%d\n",p,nCCE[p]); #endif - /* if (nCCE > get_nCCE(3, frame_parms, 1)) { - LOG_D(PHY, - "skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", - nCCE, get_nCCE(3, frame_parms, 1)); - return; - } - - if (nCCE < L2) { - LOG_D(PHY, "skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2); - return; - } - - if (mode == NO_DCI) { - LOG_D(PHY, "skip DCI decoding: expect no DCIs at nr_tti_rx %d\n", - nr_tti_rx); - return; - } + /* if (nCCE > get_nCCE(3, frame_parms, 1)) { + LOG_D(PHY, + "skip DCI decoding: nCCE=%d > get_nCCE(3,frame_parms,1)=%d\n", + nCCE, get_nCCE(3, frame_parms, 1)); + return; + } + + if (nCCE < L2) { + LOG_D(PHY, "skip DCI decoding: nCCE=%d < L2=%d\n", nCCE, L2); + return; + } + + if (mode == NO_DCI) { + LOG_D(PHY, "skip DCI decoding: expect no DCIs at nr_tti_rx %d\n", + nr_tti_rx); + return; + } */ if (do_common == 1) { Yk = 0; + if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_0) { // for dci_format_2_0, the nb_candidates is obtained from a different variable switch (L2) { - case 1: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel1; - break; - case 2: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel2; - break; - case 4: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel4; - break; - case 8: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel8; - break; - case 16: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel16; - break; - default: - break; + case 1: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel1; + break; + + case 2: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel2; + break; + + case 4: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel4; + break; + + case 8: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel8; + break; + + case 16: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.sfi_nrofCandidates_aggrlevel16; + break; + + default: + break; } } else if (pdcch_vars[eNB_id]->searchSpace[s].searchSpaceType.common_dci_formats == cformat2_3) { // for dci_format_2_3, the nb_candidates is obtained from a different variable @@ -1220,49 +1178,59 @@ void nr_dci_decoding_procedure0(int s, } } else { switch (L2) { - case 1: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel1; - break; - case 2: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel2; - break; - case 4: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel4; - break; - case 8: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel8; - break; - case 16: - nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel16; - break; - default: - break; + case 1: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel1; + break; + + case 2: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel2; + break; + + case 4: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel4; + break; + + case 8: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel8; + break; + + case 16: + nb_candidates = pdcch_vars[eNB_id]->searchSpace[s].nrofCandidates_aggrlevel16; + break; + + default: + break; } - + // Find first available in ue specific search space // according to procedure in Section 10.1 of 38.213 // compute Yk Yk = (unsigned int) pdcch_vars[eNB_id]->crnti; + for (i = 0; i <= nr_tti_rx; i++) Yk = (Yk * A[p%3]) % 65537; } + #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> L2(%d) | nCCE[%d](%d) | Yk(%d) | nb_candidates(%d)\n",L2,p,nCCE[p],Yk,nb_candidates); #endif /* for (CCEind=0; CCEind nCCE[p]) - // nb_candidates = nCCE[p] / L2; - + // if (nb_candidates * L2 > nCCE[p]) + // nb_candidates = nCCE[p] / L2; // In the next code line there is maybe a bug. The spec is not comparing Table 10.1-2 with nb_candidates, but with total number of candidates for all s and all p int m_p_s_L_max = (m_max_slot_pdcch_Table10_1_2[1]<=nb_candidates ? m_max_slot_pdcch_Table10_1_2[1] : nb_candidates); + if (L==4) m_p_s_L_max=1; // Table 10.1-2 is not defined for L=4 + #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> m_max_slot_pdcch_Table10_1_2(%d)=%d\n",L,m_max_slot_pdcch_Table10_1_2[L]); #endif + for (m = 0; m < nb_candidates; m++) { int n_ci = 0; + if (nCCE[p] < L2) return; #ifdef NR_PDCCH_DCI_DEBUG @@ -1274,9 +1242,10 @@ void nr_dci_decoding_procedure0(int s, CCEind = (((Yk + (uint16_t)(floor((m*nCCE[p])/(L2*m_p_s_L_max))) + n_ci) % (uint16_t)(floor(nCCE[p] / L2))) * L2); #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEind(%d) = (((Yk(%d) + ((m(%d)*nCCE[p](%d))/(L2(%d)*m_p_s_L_max(%d)))) % (nCCE[p] / L2)) * L2)\n", - CCEind,Yk,m,nCCE[p],L2,m_p_s_L_max); + CCEind,Yk,m,nCCE[p],L2,m_p_s_L_max); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> n_candidate(m)=%d | CCEind=%d |",m,CCEind); #endif + if (CCEind < 32) CCEmap = CCEmap0; else if (CCEind < 64) @@ -1284,94 +1253,93 @@ void nr_dci_decoding_procedure0(int s, else if (CCEind < 96) CCEmap = CCEmap2; else AssertFatal(1==0,"Illegal CCEind %d (Yk %d, m %d, nCCE %d, L2 %d\n",CCEind, Yk, m, nCCE[p], L2); - + switch (L2) { - case 1: - CCEmap_mask = (1 << (CCEind & 0x1f)); - break; - case 2: - CCEmap_mask = (3 << (CCEind & 0x1f)); - break; - case 4: - CCEmap_mask = (0xf << (CCEind & 0x1f)); - break; - case 8: - CCEmap_mask = (0xff << (CCEind & 0x1f)); - break; - case 16: - CCEmap_mask = (0xfff << (CCEind & 0x1f)); - break; - default: - LOG_E(PHY, "Illegal L2 value %d\n", L2); - //mac_xface->macphy_exit("Illegal L2\n"); - return; // not reached + case 1: + CCEmap_mask = (1 << (CCEind & 0x1f)); + break; + + case 2: + CCEmap_mask = (3 << (CCEind & 0x1f)); + break; + + case 4: + CCEmap_mask = (0xf << (CCEind & 0x1f)); + break; + + case 8: + CCEmap_mask = (0xff << (CCEind & 0x1f)); + break; + + case 16: + CCEmap_mask = (0xfff << (CCEind & 0x1f)); + break; + + default: + LOG_E(PHY, "Illegal L2 value %d\n", L2); + //mac_xface->macphy_exit("Illegal L2\n"); + return; // not reached } + CCEmap_cand = (*CCEmap) & CCEmap_mask; // CCE is not allocated yet #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> CCEmap_cand=%d \n",CCEmap_cand); #endif - - if (CCEmap_cand == 0) { + if (CCEmap_cand == 0) { #ifdef DEBUG_DCI_DECODING + if (do_common == 1) - LOG_I(PHY,"[DCI search nPdcch %d - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n", - pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); + LOG_I(PHY,"[DCI search nPdcch %d - common] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x)\n", + pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask); else - LOG_I(PHY,"[DCI search nPdcch %d - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", - pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_uss); + LOG_I(PHY,"[DCI search nPdcch %d - ue spec] Attempting candidate %d Aggregation Level %d DCI length %d at CCE %d/%d (CCEmap %x,CCEmap_cand %x) format %d\n", + pdcch_vars[eNB_id]->num_pdcch_symbols,m,L2,sizeof_bits,CCEind,nCCE,*CCEmap,CCEmap_mask,format_uss); + #endif #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we enter function dci_decoding(sizeof_bits=%d L=%d) -----\n",sizeof_bits,L); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we have to replace this part of the code by polar decoding\n"); #endif - - // for (int m=0; m < (nCCE[p]*6*9*2); m++) #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0: polar decoding)-> polar intput (with coreset_time_dur=%d, coreset_nbr_rb=%d, p=%d, CCEind=%d): \n", - coreset_time_dur,coreset_nbr_rb,p,CCEind); + coreset_time_dur,coreset_nbr_rb,p,CCEind); #endif /* int reg_p=0,reg_e=0; for (int m=0; m < (L2*6); m++){ - reg_p = (((int)floor(m/coreset_time_dur))+((m%coreset_time_dur)*(L2*6/coreset_time_dur)))*9*2; - reg_e = m*9*2; - for (int i=0; i<9*2; i++){ - //polar_input[reg_p+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1.0):(-1.0); - polar_input[reg_e+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1/sqrt(2)):((-1)/sqrt(2)); - //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_e+i,polar_input[reg_e+i], - // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); - //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_p+i,polar_input[reg_p+i], - // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); - } + reg_p = (((int)floor(m/coreset_time_dur))+((m%coreset_time_dur)*(L2*6/coreset_time_dur)))*9*2; + reg_e = m*9*2; + for (int i=0; i<9*2; i++){ + //polar_input[reg_p+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1.0):(-1.0); + polar_input[reg_e+i] = (pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]>0) ? (1/sqrt(2)):((-1)/sqrt(2)); + //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_e+i,polar_input[reg_e+i], + // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); + //printf("\t m=%d \tpolar_input[%d]=%lf <-> e_rx[%d]=%d\n",m,reg_p+i,polar_input[reg_p+i], + // ((CCEind*9*6*2) + reg_e + i),pdcch_vars[eNB_id]->e_rx[((CCEind*9*6*2) + reg_e + i)]); } - -#ifdef NR_PDCCH_DCI_DEBUG + } + + #ifdef NR_PDCCH_DCI_DEBUG printf("\n"); int j=0; uint32_t polar_hex[27] = {0}; for (int i=0; i polar_hex[%d]=%x\n",j,polar_hex[j]); -#endif + #endif */ - - uint32_t dci_estimation[4]={0}; - - - nr_polar_init(&nrPolar_params, 1, sizeof_bits, L2); - - - t_nrPolar_paramsPtr currentPtrDCI=nr_polar_params(nrPolar_params, 1, sizeof_bits, L2); + uint64_t dci_estimation[2]= {0}; + const t_nrPolar_params *currentPtrDCI=nr_polar_params(1, sizeof_bits, L2); decoderState = polar_decoder_int16(&pdcch_vars[eNB_id]->e_rx[CCEind*9*6*2], - (uint64_t*)dci_estimation, - currentPtrDCI); - crc = decoderState; + dci_estimation, + currentPtrDCI); + crc = decoderState; //crc = (crc16(&dci_decoded_output[current_thread_id][0], sizeof_bits) >> 16) ^ extract_crc(&dci_decoded_output[current_thread_id][0], sizeof_bits); #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> ... we end function dci_decoding() with crc=%x\n",crc); @@ -1385,202 +1353,226 @@ void nr_dci_decoding_procedure0(int s, printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> crc_scrambled=%d\n",*crc_scrambled); #endif - if (crc == crc_scrambled_values[_C_RNTI_]) { - *crc_scrambled =_c_rnti; - *format_found=1; + *crc_scrambled =_c_rnti; + *format_found=1; } + if (crc == crc_scrambled_values[_CS_RNTI_]) { - *crc_scrambled =_cs_rnti; - *format_found=1; + *crc_scrambled =_cs_rnti; + *format_found=1; } + if (crc == crc_scrambled_values[_NEW_RNTI_]) { - *crc_scrambled =_new_rnti; - *format_found=1; + *crc_scrambled =_new_rnti; + *format_found=1; } + if (crc == crc_scrambled_values[_TC_RNTI_]) { - *crc_scrambled =_tc_rnti; - *format_found=_format_1_0_found; + *crc_scrambled =_tc_rnti; + *format_found=_format_1_0_found; } + if (crc == crc_scrambled_values[_P_RNTI_]) { - *crc_scrambled =_p_rnti; - *format_found=_format_1_0_found; + *crc_scrambled =_p_rnti; + *format_found=_format_1_0_found; } + if (crc == crc_scrambled_values[_SI_RNTI_]) { - *crc_scrambled =_si_rnti; - *format_found=_format_1_0_found; + *crc_scrambled =_si_rnti; + *format_found=_format_1_0_found; } + if (crc == crc_scrambled_values[_RA_RNTI_]) { - *crc_scrambled =_ra_rnti; - *format_found=_format_1_0_found; + *crc_scrambled =_ra_rnti; + *format_found=_format_1_0_found; } + if (crc == crc_scrambled_values[_SP_CSI_RNTI_]) { - *crc_scrambled =_sp_csi_rnti; - *format_found=_format_0_1_found; + *crc_scrambled =_sp_csi_rnti; + *format_found=_format_0_1_found; } + if (crc == crc_scrambled_values[_SFI_RNTI_]) { - *crc_scrambled =_sfi_rnti; - *format_found=_format_2_0_found; + *crc_scrambled =_sfi_rnti; + *format_found=_format_2_0_found; } + if (crc == crc_scrambled_values[_INT_RNTI_]) { - *crc_scrambled =_int_rnti; - *format_found=_format_2_1_found; + *crc_scrambled =_int_rnti; + *format_found=_format_2_1_found; } + if (crc == crc_scrambled_values[_TPC_PUSCH_RNTI_]) { - *crc_scrambled =_tpc_pusch_rnti; - *format_found=_format_2_2_found; + *crc_scrambled =_tpc_pusch_rnti; + *format_found=_format_2_2_found; } + if (crc == crc_scrambled_values[_TPC_PUCCH_RNTI_]) { - *crc_scrambled =_tpc_pucch_rnti; - *format_found=_format_2_2_found; + *crc_scrambled =_tpc_pucch_rnti; + *format_found=_format_2_2_found; } + if (crc == crc_scrambled_values[_TPC_SRS_RNTI_]) { - *crc_scrambled =_tpc_srs_rnti; - *format_found=_format_2_3_found; + *crc_scrambled =_tpc_srs_rnti; + *format_found=_format_2_3_found; } + + #ifdef NR_PDCCH_DCI_DEBUG printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> format_found=%d\n",*format_found); printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> crc_scrambled=%d\n",*crc_scrambled); #endif - if (*format_found!=255) { - dci_alloc[*dci_cnt].dci_length = sizeof_bits; - dci_alloc[*dci_cnt].rnti = crc; - dci_alloc[*dci_cnt].L = L; - dci_alloc[*dci_cnt].firstCCE = CCEind; - dci_alloc[*dci_cnt].dci_pdu[0] = dci_estimation[0]; - dci_alloc[*dci_cnt].dci_pdu[1] = dci_estimation[1]; - dci_alloc[*dci_cnt].dci_pdu[2] = dci_estimation[2]; - dci_alloc[*dci_cnt].dci_pdu[3] = dci_estimation[3]; -#ifdef NR_PDCCH_DCI_DEBUG - printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> rnti matches -> DCI FOUND !!! crc =>%x, sizeof_bits %d, sizeof_bytes %d \n", - dci_alloc[*dci_cnt].rnti, dci_alloc[*dci_cnt].dci_length, sizeof_bytes); - printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> dci_cnt %d (format_css %d crc_scrambled %d) L %d, firstCCE %d pdu[0] %x pdu[1] %x pdu[2] %x pdu[3] %x \n", - *dci_cnt, format_css,*crc_scrambled,dci_alloc[*dci_cnt].L, dci_alloc[*dci_cnt].firstCCE,dci_alloc[*dci_cnt].dci_pdu[0],dci_alloc[*dci_cnt].dci_pdu[1],dci_alloc[*dci_cnt].dci_pdu[2],dci_alloc[*dci_cnt].dci_pdu[3]); -#endif - if ((format_css == cformat0_0_and_1_0) || (format_uss == uformat0_0_and_1_0)){ - if ((*crc_scrambled == _p_rnti) || (*crc_scrambled == _si_rnti) || (*crc_scrambled == _ra_rnti)){ - dci_alloc[*dci_cnt].format = format1_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_1_0_found; - // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> a format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); - } else { - if ((dci_estimation[0]&1) == 0){ - dci_alloc[*dci_cnt].format = format0_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_0_0_found; - // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> b format0_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); - } - if ((dci_estimation[0]&1) == 1){ - dci_alloc[*dci_cnt].format = format1_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_1_0_found; - // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> c format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); - } - } - } - if (format_css == cformat2_0){ - dci_alloc[*dci_cnt].format = format2_0; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_0_found; - } - if (format_css == cformat2_1){ - dci_alloc[*dci_cnt].format = format2_1; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_1_found; - } - if (format_css == cformat2_2){ - dci_alloc[*dci_cnt].format = format2_2; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_2_found; - } - if (format_css == cformat2_3){ - dci_alloc[*dci_cnt].format = format2_3; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_2_3_found; - } - if (format_uss == uformat0_1_and_1_1){ - if ((dci_estimation[0]&1) == 0){ - dci_alloc[*dci_cnt].format = format0_1; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_0_1_found; - } - if ((dci_estimation[0]&1) == 1){ - dci_alloc[*dci_cnt].format = format1_1; - *dci_cnt = *dci_cnt + 1; - *format_found=_format_1_1_found; - } - } - // store first nCCE of group for PUCCH transmission of ACK/NAK - pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - /* if (crc == si_rnti) { - dci_alloc[*dci_cnt].format = format_si; - *dci_cnt = *dci_cnt + 1; - } else if (crc == p_rnti) { - dci_alloc[*dci_cnt].format = format_p; - *dci_cnt = *dci_cnt + 1; - } else if (crc == ra_rnti) { - dci_alloc[*dci_cnt].format = format_ra; - // store first nCCE of group for PUCCH transmission of ACK/NAK - pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - *dci_cnt = *dci_cnt + 1; - } else if (crc == pdcch_vars[eNB_id]->crnti) { - if ((mode & UL_DCI) && (format_c == format0) - && ((dci_decoded_output[current_thread_id][0] & 0x80) - == 0)) { // check if pdu is format 0 or 1A - if (*format0_found == 0) { - dci_alloc[*dci_cnt].format = format0; - *format0_found = 1; - *dci_cnt = *dci_cnt + 1; - pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - } - } else if (format_c == format0) { // this is a format 1A DCI - dci_alloc[*dci_cnt].format = format1A; - *dci_cnt = *dci_cnt + 1; - pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - } else { - // store first nCCE of group for PUCCH transmission of ACK/NAK - if (*format_c_found == 0) { - dci_alloc[*dci_cnt].format = format_c; - *dci_cnt = *dci_cnt + 1; - *format_c_found = 1; - pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; - } - } - }*/ - //LOG_I(PHY,"DCI decoding CRNTI [format: %d, nCCE[nr_tti_rx: %d]: %d ], AggregationLevel %d \n",format_c, nr_tti_rx, pdcch_vars[eNB_id]->nCCE[nr_tti_rx],L2); - // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); - switch (1 << L) { - case 1: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - case 2: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - case 4: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - case 8: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - case 16: - *CCEmap |= (1 << (CCEind & 0x1f)); - break; - } + if (*format_found!=255) { + dci_alloc[*dci_cnt].dci_length = sizeof_bits; + dci_alloc[*dci_cnt].rnti = crc; + dci_alloc[*dci_cnt].L = L; + dci_alloc[*dci_cnt].firstCCE = CCEind; + memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_estimation,8); + +#ifdef NR_PDCCH_DCI_DEBUG + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> rnti matches -> DCI FOUND !!! crc =>0x%x, sizeof_bits %d, sizeof_bytes %d \n", + dci_alloc[*dci_cnt].rnti, dci_alloc[*dci_cnt].dci_length, sizeof_bytes); + printf ("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> dci_cnt %d (format_css %d crc_scrambled %d) L %d, firstCCE %d pdu[0] 0x%lx pdu[1] 0x%lx \n", + *dci_cnt, format_css,*crc_scrambled,dci_alloc[*dci_cnt].L, dci_alloc[*dci_cnt].firstCCE,dci_alloc[*dci_cnt].dci_pdu[0],dci_alloc[*dci_cnt].dci_pdu[1]); +#endif + if ((format_css == cformat0_0_and_1_0) || (format_uss == uformat0_0_and_1_0)) { + if ((*crc_scrambled == _p_rnti) || (*crc_scrambled == _si_rnti) || (*crc_scrambled == _ra_rnti)) { + dci_alloc[*dci_cnt].format = format1_0; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_1_0_found; + // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> a format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); + } else { + if ((dci_estimation[0]&1) == 0) { + dci_alloc[*dci_cnt].format = format0_0; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_0_0_found; + // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> b format0_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); + } + + if ((dci_estimation[0]&1) == 1) { + dci_alloc[*dci_cnt].format = format1_0; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_1_0_found; + // printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure0)-> c format1_0=%d and dci_cnt=%d\n",*format_found,*dci_cnt); + } + } + } + + if (format_css == cformat2_0) { + dci_alloc[*dci_cnt].format = format2_0; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_2_0_found; + } + + if (format_css == cformat2_1) { + dci_alloc[*dci_cnt].format = format2_1; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_2_1_found; + } + + if (format_css == cformat2_2) { + dci_alloc[*dci_cnt].format = format2_2; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_2_2_found; + } + + if (format_css == cformat2_3) { + dci_alloc[*dci_cnt].format = format2_3; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_2_3_found; + } + + if (format_uss == uformat0_1_and_1_1) { + if ((dci_estimation[0]&1) == 0) { + dci_alloc[*dci_cnt].format = format0_1; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_0_1_found; + } + + if ((dci_estimation[0]&1) == 1) { + dci_alloc[*dci_cnt].format = format1_1; + *dci_cnt = *dci_cnt + 1; + *format_found=_format_1_1_found; + } + } + + // store first nCCE of group for PUCCH transmission of ACK/NAK + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + + /* if (crc == si_rnti) { + dci_alloc[*dci_cnt].format = format_si; + *dci_cnt = *dci_cnt + 1; + } else if (crc == p_rnti) { + dci_alloc[*dci_cnt].format = format_p; + *dci_cnt = *dci_cnt + 1; + } else if (crc == ra_rnti) { + dci_alloc[*dci_cnt].format = format_ra; + // store first nCCE of group for PUCCH transmission of ACK/NAK + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + *dci_cnt = *dci_cnt + 1; + } else if (crc == pdcch_vars[eNB_id]->crnti) { + + if ((mode & UL_DCI) && (format_c == format0) + && ((dci_decoded_output[current_thread_id][0] & 0x80) + == 0)) { // check if pdu is format 0 or 1A + if (*format0_found == 0) { + dci_alloc[*dci_cnt].format = format0; + *format0_found = 1; + *dci_cnt = *dci_cnt + 1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + } + } else if (format_c == format0) { // this is a format 1A DCI + dci_alloc[*dci_cnt].format = format1A; + *dci_cnt = *dci_cnt + 1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + } else { + // store first nCCE of group for PUCCH transmission of ACK/NAK + if (*format_c_found == 0) { + dci_alloc[*dci_cnt].format = format_c; + *dci_cnt = *dci_cnt + 1; + *format_c_found = 1; + pdcch_vars[eNB_id]->nCCE[nr_tti_rx] = CCEind; + } + } + }*/ + //LOG_I(PHY,"DCI decoding CRNTI [format: %d, nCCE[nr_tti_rx: %d]: %d ], AggregationLevel %d \n",format_c, nr_tti_rx, pdcch_vars[eNB_id]->nCCE[nr_tti_rx],L2); + // memcpy(&dci_alloc[*dci_cnt].dci_pdu[0],dci_decoded_output,sizeof_bytes); + switch (1 << L) { + case 1: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + + case 2: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + + case 4: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + + case 8: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + + case 16: + *CCEmap |= (1 << (CCEind & 0x1f)); + break; + } #ifdef DEBUG_DCI_DECODING - LOG_I(PHY,"[DCI search] Found DCI %d rnti %x Aggregation %d length %d format %d in CCE %d (CCEmap %x) candidate %d / %d \n", - *dci_cnt,crc,1< end candidate loop\n"); #endif @@ -1750,10 +1743,10 @@ void nr_dci_decoding_procedure0(int s, L, &pdcch_vars[eNB_id]->e_rx[CCEind*72], &dci_decoded_output[current_thread_id][0]); - + // for (i=0;i<3+(sizeof_bits>>3);i++) // printf("dci_decoded_output[%d] => %x\n",i,dci_decoded_output[i]); - + crc = (crc16(&dci_decoded_output[current_thread_id][0],sizeof_bits)>>16) ^ extract_crc(&dci_decoded_output[current_thread_id][0],sizeof_bits); #ifdef DEBUG_DCI_DECODING printf("crc =>%x\n",crc); @@ -1861,8 +1854,8 @@ void nr_dci_decoding_procedure0(int s, return; } // rnti match } // CCEmap_cand == 0 - - // if ( agregationLevel != 0xFF && + + // if ( agregationLevel != 0xFF && // (format_c == format0 && m==0 && si_rnti != SI_RNTI)) // { // //Only valid for OAI : Save some processing time when looking for DCI format0. From the log we see the DCI only on candidate 0. @@ -2051,18 +2044,17 @@ void nr_dci_decoding_procedure0(int s, #ifdef NR_PDCCH_DCI_RUN uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, - uint16_t eNB_id, - uint8_t nr_tti_rx, - int p, - crc_scrambled_t crc_scrambled, - uint16_t n_RB_ULBWP, - uint16_t n_RB_DLBWP, - uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], - uint8_t format){ + uint16_t eNB_id, + uint8_t nr_tti_rx, + int p, + crc_scrambled_t crc_scrambled, + uint16_t n_RB_ULBWP, + uint16_t n_RB_DLBWP, + uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], + uint8_t format) { #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size)-> crc_scrambled=%d, n_RB_ULBWP=%d, n_RB_DLBWP=%d\n",crc_scrambled,n_RB_ULBWP,n_RB_DLBWP); #endif - /* * function nr_dci_format_size calculates and returns the size in bits of a determined format * it also returns an bi-dimensional array 'dci_fields_sizes' with x rows and y columns, where: @@ -2070,7 +2062,6 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, * y is the number of formats * e.g.: dci_fields_sizes[10][0] contains the size in bits of the field FREQ_DOM_RESOURCE_ASSIGNMENT_UL for format 0_0 */ - // pdsch_config contains the PDSCH-Config IE is used to configure the UE specific PDSCH parameters (TS 38.331) PDSCH_Config_t pdsch_config = ue->PDSCH_Config; // pusch_config contains the PUSCH-Config IE is used to configure the UE specific PUSCH parameters (TS 38.331) @@ -2083,15 +2074,14 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, PUSCH_ServingCellConfig_t PUSCH_ServingCellConfig= ue->PUSCH_ServingCellConfig; PDSCH_ServingCellConfig_t PDSCH_ServingCellConfig= ue->PDSCH_ServingCellConfig; NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; - // 1 CARRIER_IN // crossCarrierSchedulingConfig from higher layers, variable crossCarrierSchedulingConfig indicates if 'cross carrier scheduling' is enabled or not: // if No cross carrier scheduling: number of bits for CARRIER_IND is 0 // if Cross carrier scheduling: number of bits for CARRIER_IND is 3 // The IE CrossCarrierSchedulingConfig is used to specify the configuration when the cross-carrier scheduling is used in a cell uint8_t crossCarrierSchedulingConfig_ind = 0; - if (crossCarrierSchedulingConfig.schedulingCellInfo.other.cif_InSchedulingCell !=0 ) crossCarrierSchedulingConfig_ind=1; + if (crossCarrierSchedulingConfig.schedulingCellInfo.other.cif_InSchedulingCell !=0 ) crossCarrierSchedulingConfig_ind=1; // 2 SUL_IND_0_1, // 40 SRS_REQUEST, // 50 SUL_IND_0_0 // UL/SUL indicator (TS 38.331, supplementary uplink is indicated in higher layer parameter ServCellAdd-SUL from IE ServingCellConfig and ServingCellConfigCommon): @@ -2099,7 +2089,6 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, // 1 bit for UEs configured with SUL in the cell as defined in Table 7.3.1.1.1-1 // sul_ind indicates whether SUL is configured in cell or not uint8_t sul_ind=ue->supplementaryUplink.supplementaryUplink; // this value will be 0 or 1 depending on higher layer parameter ServCellAdd-SUL. FIXME!!! - // 7 BANDWIDTH_PART_IND // number of UL BWPs configured by higher layers uint8_t n_UL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! @@ -2107,16 +2096,14 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, // number of DL BWPs configured by higher layers uint8_t n_DL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! n_DL_BWP_RRC = ((n_DL_BWP_RRC > 3)?n_DL_BWP_RRC:(n_DL_BWP_RRC+1)); - - // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL // if format0_0, only resource allocation type 1 is allowed // if format0_1, then resource allocation type 0 can be configured and N_RBG is defined in TS 38.214 subclause 6.1.2.2.1 - // for PUSCH hopping with resource allocation type 1 // n_UL_hopping = 1 if the higher layer parameter frequencyHoppingOffsetLists contains two offset values // n_UL_hopping = 2 if the higher layer parameter frequencyHoppingOffsetLists contains four offset values uint8_t n_UL_hopping=pusch_config.n_frequencyHoppingOffsetLists; + if (n_UL_hopping == 2) { n_UL_hopping = 1; } else if (n_UL_hopping == 4) { @@ -2124,27 +2111,39 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, } else { n_UL_hopping = 0; } + ul_resourceAllocation_t ul_resource_allocation_type = pusch_config.ul_resourceAllocation; uint8_t ul_res_alloc_type_0 = 0; uint8_t ul_res_alloc_type_1 = 0; + if (ul_resource_allocation_type == ul_resourceAllocationType0) ul_res_alloc_type_0 = 1; + if (ul_resource_allocation_type == ul_resourceAllocationType1) ul_res_alloc_type_1 = 1; + if (ul_resource_allocation_type == ul_dynamicSwitch) { ul_res_alloc_type_0 = 1; ul_res_alloc_type_1 = 1; } + uint8_t n_bits_freq_dom_res_assign_ul=0,n_ul_RGB_tmp; - if (ul_res_alloc_type_0 == 1){ // implementation of Table 6.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 + + if (ul_res_alloc_type_0 == 1) { // implementation of Table 6.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 // config1: PUSCH-Config IE contains rbg-Size ENUMERATED {config1 config2} ul_rgb_Size_t config = pusch_config.ul_rgbSize; uint8_t nominal_RBG_P = (config==ul_rgb_config1?2:4); + if (n_RB_ULBWP > 36) nominal_RBG_P = (config==ul_rgb_config1?4:8); + if (n_RB_ULBWP > 72) nominal_RBG_P = (config==ul_rgb_config1?8:16); + if (n_RB_ULBWP > 144) nominal_RBG_P = 16; + n_bits_freq_dom_res_assign_ul = (uint8_t)ceil((n_RB_ULBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? n_ul_RGB_tmp = n_bits_freq_dom_res_assign_ul; } + if (ul_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_ul = (uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping; + if ((ul_res_alloc_type_0 == 1) && (ul_res_alloc_type_1 == 1)) n_bits_freq_dom_res_assign_ul = ((n_bits_freq_dom_res_assign_ul>n_ul_RGB_tmp)?(n_bits_freq_dom_res_assign_ul+1):(n_ul_RGB_tmp+1)); @@ -2154,37 +2153,49 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, dl_resourceAllocation_t dl_resource_allocation_type = pdsch_config.dl_resourceAllocation; uint8_t dl_res_alloc_type_0 = 0; uint8_t dl_res_alloc_type_1 = 0; + if (dl_resource_allocation_type == dl_resourceAllocationType0) dl_res_alloc_type_0 = 1; + if (dl_resource_allocation_type == dl_resourceAllocationType1) dl_res_alloc_type_1 = 1; + if (dl_resource_allocation_type == dl_dynamicSwitch) { dl_res_alloc_type_0 = 1; dl_res_alloc_type_1 = 1; } + uint8_t n_bits_freq_dom_res_assign_dl=0,n_dl_RGB_tmp; - if (dl_res_alloc_type_0 == 1){ // implementation of Table 5.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 + + if (dl_res_alloc_type_0 == 1) { // implementation of Table 5.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 // config1: PDSCH-Config IE contains rbg-Size ENUMERATED {config1, config2} dl_rgb_Size_t config = pdsch_config.dl_rgbSize; uint8_t nominal_RBG_P = (config==dl_rgb_config1?2:4); + if (n_RB_DLBWP > 36) nominal_RBG_P = (config==dl_rgb_config1?4:8); + if (n_RB_DLBWP > 72) nominal_RBG_P = (config==dl_rgb_config1?8:16); + if (n_RB_DLBWP > 144) nominal_RBG_P = 16; + n_bits_freq_dom_res_assign_dl = (uint8_t)ceil((n_RB_DLBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? n_dl_RGB_tmp = n_bits_freq_dom_res_assign_dl; } + if (dl_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_dl = (uint8_t)(ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2))); + if ((dl_res_alloc_type_0 == 1) && (dl_res_alloc_type_1 == 1)) n_bits_freq_dom_res_assign_dl = ((n_bits_freq_dom_res_assign_dl>n_dl_RGB_tmp)?(n_bits_freq_dom_res_assign_dl+1):(n_dl_RGB_tmp+1)); // 12 TIME_DOM_RESOURCE_ASSIGNMENT uint8_t pusch_alloc_list = pusch_config.n_push_alloc_list; uint8_t pdsch_alloc_list = pdsch_config.n_pdsh_alloc_list; - // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] static_bundleSize_t static_prb_BundlingType = pdsch_config.prbBundleType.staticBundling; bundleSizeSet1_t dynamic_prb_BundlingType1 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet1; bundleSizeSet2_t dynamic_prb_BundlingType2 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet2; uint8_t prb_BundlingType_size=0; + if ((static_prb_BundlingType==st_n4)||(static_prb_BundlingType==st_wideband)) prb_BundlingType_size=0; + if ((dynamic_prb_BundlingType1==dy_1_n4)||(dynamic_prb_BundlingType1==dy_1_wideband)||(dynamic_prb_BundlingType1==dy_1_n2_wideband)||(dynamic_prb_BundlingType1==dy_1_n4_wideband)|| (dynamic_prb_BundlingType2==dy_2_n4)||(dynamic_prb_BundlingType2==dy_2_wideband)) prb_BundlingType_size=1; @@ -2195,37 +2206,38 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, // 0, 1, or 2 bits as defined in Subclause 5.1.4.2 of [6, TS 38.214]. // is the number of ZP CSI-RS resource sets in the higher layer parameter zp-CSI-RS-Resource uint8_t n_zp_bits = pdsch_config.n_zp_CSI_RS_ResourceId; - // 17 FREQ_HOPPING_FLAG // freqHopping is defined by higher layer parameter frequencyHopping from IE PUSCH-Config. Values are ENUMERATED{mode1, mode2} frequencyHopping_t f_hopping = pusch_config.frequencyHopping; uint8_t freqHopping = 0; + if ((f_hopping==f_hop_mode1)||(f_hopping==f_hop_mode2)) freqHopping = 1; // 28 DAI pdsch_HARQ_ACK_Codebook_t pdsch_HARQ_ACK_Codebook = pdsch_config.pdsch_HARQ_ACK_Codebook; uint8_t n_dai = 0; uint8_t n_serving_cell_dl = 1; // this is hardcoded to 1 as we need to get this value from RRC higher layers parameters. FIXME!!! + if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl == 1)) n_dai = 2; + if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl > 1)) n_dai = 4; // 29 FIRST_DAI uint8_t codebook_HARQ_ACK = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. + if (pdsch_HARQ_ACK_Codebook == semiStatic) codebook_HARQ_ACK = 1; + if (pdsch_HARQ_ACK_Codebook == dynamic) codebook_HARQ_ACK = 2; // 30 SECOND_DAI uint8_t n_HARQ_ACK_sub_codebooks = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. FIXME!!! - // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND uint8_t pdsch_harq_t_ind = (uint8_t)ceil(log2(pucch_config_dedicated.dl_DataToUL_ACK[0])); - // 36 SRS_RESOURCE_IND // n_SRS is the number of configured SRS resources in the SRS resource set associated with the higher layer parameter usage of value 'codeBook' or 'nonCodeBook' // from SRS_ResourceSet_t type we should get the information of the usage parameter (with possible values beamManagement, codebook, nonCodebook, antennaSwitching) // at frame_parms->srs_nr->p_SRS_ResourceSetList[]->usage uint8_t n_SRS = ue->srs.number_srs_Resource_Set; - // 37 PRECOD_NBR_LAYERS // 38 ANTENNA_PORTS txConfig_t txConfig = pusch_config.txConfig; @@ -2235,91 +2247,118 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, uint8_t num_antenna_ports = 1; // this is hardcoded. We need to get the real value FIXME!!! uint8_t precond_nbr_layers_bits = 0; uint8_t antenna_ports_bits_ul = 0; + // searching number of bits at tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 - if (txConfig == txConfig_codebook){ + if (txConfig == txConfig_codebook) { if (num_antenna_ports == 4) { if ((transformPrecoder == transformPrecoder_disabled) && ((maxRank == 2)||(maxRank == 3)||(maxRank == 4))) { // Table 7.3.1.1.2-2 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=6; - if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=5; - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=4; + if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=6; + + if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=5; + + if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=4; } + if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-3 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=5; - if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=4; - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; + if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=5; + + if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=4; + + if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; } } + if (num_antenna_ports == 2) { if ((transformPrecoder == transformPrecoder_disabled) && (maxRank == 2)) { // Table 7.3.1.1.2-4 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=4; - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; + if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=4; + + if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; } + if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-5 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=3; - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=1; + if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=3; + + if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=1; } } } - if (txConfig == txConfig_nonCodebook){ + + if (txConfig == txConfig_nonCodebook) { } + // searching number of bits at tables 7.3.1.1.2-6/7/8/9/10/11/12/13/14/15/16/17/18/19 - if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)){ + if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)) { if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 2; + if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; + if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 3; + if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; } - if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type2)){ + + if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type2)) { if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 4; + if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 5; } + // for format 1_1 number of bits as defined by Tables 7.3.1.2.2-1/2/3/4 uint8_t antenna_ports_bits_dl = 0; + if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 4; // Table 7.3.1.2.2-1 + if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-2 + if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-3 + if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 6; // Table 7.3.1.2.2-4 // 39 TCI uint8_t tci_bits=0; + if (pdcch_vars2->coreset[p].tciPresentInDCI == tciPresentInDCI_enabled) tci_bits=3; // 42 CSI_REQUEST // reportTriggerSize is defined in the CSI-MeasConfig IE (TS 38.331). // Size of CSI request field in DCI (bits). Corresponds to L1 parameter 'ReportTriggerSize' (see 38.214, section 5.2) uint8_t reportTriggerSize = csi_MeasConfig.reportTriggerSize; // value from 0..6 - // 43 CBGTI // for format 0_1 uint8_t maxCodeBlockGroupsPerTransportBlock = 0; + if (PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock != 0) maxCodeBlockGroupsPerTransportBlock = (uint8_t)PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock; + // for format 1_1, as defined in Subclause 5.1.7 of [6, TS38.214] uint8_t maxCodeBlockGroupsPerTransportBlock_dl = 0; + if (PDSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock_dl != 0) maxCodeBlockGroupsPerTransportBlock_dl = pdsch_config.maxNrofCodeWordsScheduledByDCI; // FIXME!!! // 44 CBGFI uint8_t cbgfi_bit = PDSCH_ServingCellConfig.codeBlockGroupFlushIndicator; - // 45 PTRS_DMRS // 0 bit if PTRS-UplinkConfig is not configured and transformPrecoder=disabled, or if transformPrecoder=enabled, or if maxRank=1 // 2 bits otherwise uint8_t ptrs_dmrs_bits=0; //FIXME!!! - // 46 BETA_OFFSET_IND // at IE PUSCH-Config, beta_offset indicator – 0 if the higher layer parameter betaOffsets = semiStatic; otherwise 2 bits // uci-OnPUSCH // Selection between and configuration of dynamic and semi-static beta-offset. If the field is absent or released, the UE applies the value 'semiStatic' and the BetaOffsets uint8_t betaOffsets = 0; + if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_semiStatic); + if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_dynamic) betaOffsets = 2; // 47 DMRS_SEQ_INI uint8_t dmrs_seq_ini_bits_ul = 0; uint8_t dmrs_seq_ini_bits_dl = 0; + //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-UplinkConfig if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.scramblingID0 != 0) && (dmrs_UplinkConfig.scramblingID1 != 0)) dmrs_seq_ini_bits_ul = 1; + //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-DownlinkConfig if ((dmrs_DownlinkConfig.scramblingID0 != 0) && (dmrs_DownlinkConfig.scramblingID0 != 0)) dmrs_seq_ini_bits_dl = 1; @@ -2349,49 +2388,68 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, // 40 SRS_REQUEST // 41 TPC_CMD uint8_t tpc_cmd_bit_2_3 = 0; - uint8_t dci_field_size_table [NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = { // This table contains the number of bits for each field (row) contained in each dci format (column). // The values of the variables indicate field sizes in number of bits //Format0_0 Format0_1 Format1_0 Format1_1 Formats2_0/1/2/3 - {1, 1, (((crc_scrambled == _p_rnti) || (crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti)) ? 0:1), - 1, 0,0,0,0}, // 0 IDENTIFIER_DCI_FORMATS: - {0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), - 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), - 0,0,0,0}, // 1 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] + { + 1, 1, (((crc_scrambled == _p_rnti) || (crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti)) ? 0:1), + 1, 0,0,0,0 + }, // 0 IDENTIFIER_DCI_FORMATS: + { + 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), + 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), + 0,0,0,0 + }, // 1 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] {0, (sul_ind == 0)?0:1, 0, 0, 0,0,0,0}, // 2 SUL_IND_0_1: {0, 0, 0, 0, 1,0,0,0}, // 3 SLOT_FORMAT_IND: size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213] {0, 0, 0, 0, 0,1,0,0}, // 4 PRE_EMPTION_IND: size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits {0, 0, 0, 0, 0,0,0,0}, // 5 BLOCK_NUMBER: starting position of a block is determined by the parameter startingBitOfFormat2_3 {0, 0, 0, 0, 0,0,1,0}, // 6 CLOSE_LOOP_IND - {0, (uint8_t)ceil(log2(n_UL_BWP_RRC)), - 0, (uint8_t)ceil(log2(n_DL_BWP_RRC)), - 0,0,0,0}, // 7 BANDWIDTH_PART_IND: - {0, 0, ((crc_scrambled == _p_rnti) ? 2:0), - 0, 0,0,0,0}, // 8 SHORT_MESSAGE_IND 2 bits if crc scrambled with P-RNTI - {0, 0, ((crc_scrambled == _p_rnti) ? 8:0), - 0, 0,0,0,0}, // 9 SHORT_MESSAGES 8 bit8 if crc scrambled with P-RNTI - {(uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping, - n_bits_freq_dom_res_assign_ul, - 0, 0, 0,0,0,0}, // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered + { + 0, (uint8_t)ceil(log2(n_UL_BWP_RRC)), + 0, (uint8_t)ceil(log2(n_DL_BWP_RRC)), + 0,0,0,0 + }, // 7 BANDWIDTH_PART_IND: + { + 0, 0, ((crc_scrambled == _p_rnti) ? 2:0), + 0, 0,0,0,0 + }, // 8 SHORT_MESSAGE_IND 2 bits if crc scrambled with P-RNTI + { + 0, 0, ((crc_scrambled == _p_rnti) ? 8:0), + 0, 0,0,0,0 + }, // 9 SHORT_MESSAGES 8 bit8 if crc scrambled with P-RNTI + { + (uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping, + n_bits_freq_dom_res_assign_ul, + 0, 0, 0,0,0,0 + }, // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered // (NOTE 1) If DCI format 0_0 is monitored in common search space // and if the number of information bits in the DCI format 0_0 prior to padding // is larger than the payload size of the DCI format 1_0 monitored in common search space // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 // is reduced such that the size of DCI format 0_0 equals to the size of the DCI format 1_0 - {0, 0, (uint8_t)ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2)), - n_bits_freq_dom_res_assign_dl, - 0,0,0,0}, // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: - {4, (uint8_t)log2(pusch_alloc_list), - 4, (uint8_t)log2(pdsch_alloc_list), - 0,0,0,0}, // 12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, + { + 0, 0, (uint8_t)ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2)), + n_bits_freq_dom_res_assign_dl, + 0,0,0,0 + }, // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: + { + 4, (uint8_t)log2(pusch_alloc_list), + 4, (uint8_t)log2(pdsch_alloc_list), + 0,0,0,0 + }, // 12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, // where I the number of entries in the higher layer parameter pusch-AllocationList - {0, 0, 1, (((dl_res_alloc_type_0==1)&&(dl_res_alloc_type_1==0))?0:1), - 0,0,0,0}, // 13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 + { + 0, 0, 1, (((dl_res_alloc_type_0==1) &&(dl_res_alloc_type_1==0))?0:1), + 0,0,0,0 + }, // 13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 {0, 0, 0, prb_BundlingType_size, 0,0,0,0}, // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] {0, 0, 0, rateMatching_bits, 0,0,0,0}, // 15 RATE_MATCHING_IND: 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set {0, 0, 0, n_zp_bits, 0,0,0,0}, // 16 ZP_CSI_RS_TRIGGER: - {1, (((ul_res_alloc_type_0==1)&&(ul_res_alloc_type_1==0))||(freqHopping == 0))?0:1, - 0, 0, 0,0,0,0}, // 17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 + { + 1, (((ul_res_alloc_type_0==1) &&(ul_res_alloc_type_1==0))||(freqHopping == 0))?0:1, + 0, 0, 0,0,0,0 + }, // 17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 {0, 0, 0, 5, 0,0,0,0}, // 18 TB1_MCS: {0, 0, 0, 1, 0,0,0,0}, // 19 TB1_NDI: {0, 0, 0, 2, 0,0,0,0}, // 20 TB1_RV: @@ -2400,17 +2458,23 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, {0, 0, 0, 2, 0,0,0,0}, // 23 TB2_RV: {5, 5, 5, 0, 0,0,0,0}, // 24 MCS: {1, 1, (crc_scrambled == _c_rnti)?1:0,0, 0,0,0,0}, // 25 NDI: - {2, 2, (((crc_scrambled == _c_rnti) || (crc_scrambled == _si_rnti)) ? 2:0), - 0, 0,0,0,0}, // 26 RV: + { + 2, 2, (((crc_scrambled == _c_rnti) || (crc_scrambled == _si_rnti)) ? 2:0), + 0, 0,0,0,0 + }, // 26 RV: {4, 4, (crc_scrambled == _c_rnti)?4:0,4, 0,0,0,0}, // 27 HARQ_PROCESS_NUMBER: {0, 0, (crc_scrambled == _c_rnti)?2:0,n_dai, 0,0,0,0}, // 28 DAI: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI // 0 otherwise {0, codebook_HARQ_ACK, 0, 0, 0,0,0,0}, // 29 FIRST_DAI: (1 or 2 bits) 1 bit for semi-static HARQ-ACK // 2 bits for dynamic HARQ-ACK codebook with single HARQ-ACK codebook - {0, (((codebook_HARQ_ACK == 2) && (n_HARQ_ACK_sub_codebooks==2))?2:0), - 0, 0, 0,0,0,0}, // 30 SECOND_DAI: (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks // 0 bits otherwise - {0, 0, (((crc_scrambled == _p_rnti) || (crc_scrambled == _ra_rnti)) ? 2:0), - 0, 0,0,0,0}, // 31 TB_SCALING + { + 0, (((codebook_HARQ_ACK == 2) &&(n_HARQ_ACK_sub_codebooks==2))?2:0), + 0, 0, 0,0,0,0 + }, // 30 SECOND_DAI: (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks // 0 bits otherwise + { + 0, 0, (((crc_scrambled == _p_rnti) || (crc_scrambled == _ra_rnti)) ? 2:0), + 0, 0,0,0,0 + }, // 31 TB_SCALING {2, 2, 0, 0, 0,0,0,0}, // 32 TPC_PUSCH: {0, 0, (crc_scrambled == _c_rnti)?2:0,2, 0,0,0,0}, // 33 TPC_PUCCH: {0, 0, (crc_scrambled == _c_rnti)?3:0,3, 0,0,0,0}, // 34 PUCCH_RESOURCE_IND: @@ -2420,13 +2484,17 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, {0, antenna_ports_bits_ul, 0, antenna_ports_bits_dl, 0,0,0,0}, // 38 ANTENNA_PORTS: {0, 0, 0, tci_bits, 0,0,0,0}, // 39 TCI: 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits {0, (sul_ind == 0)?2:3, 0, (sul_ind == 0)?2:3, 0,0,0,2}, // 40 SRS_REQUEST: - {0, 0, 0, 0, 0,0,tpc_cmd_bit_2_2, - tpc_cmd_bit_2_3}, + { + 0, 0, 0, 0, 0,0,tpc_cmd_bit_2_2, + tpc_cmd_bit_2_3 + }, // 41 TPC_CMD: {0, reportTriggerSize, 0, 0, 0,0,0,0}, // 42 CSI_REQUEST: - {0, maxCodeBlockGroupsPerTransportBlock, - 0, maxCodeBlockGroupsPerTransportBlock_dl, - 0,0,0,0}, // 43 CBGTI: 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH + { + 0, maxCodeBlockGroupsPerTransportBlock, + 0, maxCodeBlockGroupsPerTransportBlock_dl, + 0,0,0,0 + }, // 43 CBGTI: 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH {0, 0, 0, cbgfi_bit, 0,0,0,0}, // 44 CBGFI: 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator {0, ptrs_dmrs_bits, 0, 0, 0,0,0,0}, // 45 PTRS_DMRS: {0, betaOffsets, 0, 0, 0,0,0,0}, // 46 BETA_OFFSET_IND: @@ -2444,13 +2512,13 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, {0, 0, 0, 0, 0,0,0,0}, // 52 SUL_IND_1_0 (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) {0, 0, 0, 0, 0,0,0,0}, // 53 SS_PBCH_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) {0, 0, 0, 0, 0,0,0,0}, // 54 PRACH_MASK_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - {0, 0, ((crc_scrambled == _p_rnti)?6:(((crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti))?16:0)), - 0, 0,0,0,0} // 55 RESERVED_NR_DCI + { + 0, 0, ((crc_scrambled == _p_rnti)?6:(((crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti))?16:0)), + 0, 0,0,0,0 + } // 55 RESERVED_NR_DCI }; - // NOTE 1: adjustments in freq_dom_resource_assignment_UL to be done if necessary // NOTE 2: adjustments in padding to be done if necessary - uint8_t dci_size [8] = {0,0,0,0,0,0,0,0}; // will contain size for each format for (int i=0 ; i dci_size[2])){ + if ((dci_field_size_table[SUL_IND_0_0][0] == 1) && (dci_size[0] > dci_size[2])) { dci_field_size_table[SUL_IND_0_0][0] = 0; dci_size[0]=dci_size[0]-1; } + // if ((format == format0_0) || (format == format1_0)) { // According to Section 7.3.1.1.1 in TS 38.212 // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding @@ -2503,6 +2578,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, #endif //} } + // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding // is larger than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 is reduced @@ -2528,20 +2604,20 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, * Not implemented. FIXME!!! * */ - - // } #ifdef NR_PDCCH_DCI_DEBUG printf("\t\t<-NR_PDCCH_DCI_DEBUG (nr_dci_format_size) dci_fields_sizes[][] = { \n"); - for (int j=0; jpdcch_vars[ue->current_thread_id[nr_tti_rx]]; NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; uint16_t pdcch_DMRS_scrambling_id = pdcch_vars2->coreset[p].pdcchDMRSScramblingID; uint64_t coreset_freq_dom = pdcch_vars2->coreset[p].frequencyDomainResources; int coreset_time_dur = pdcch_vars2->coreset[p].duration; uint16_t coreset_nbr_rb=0; + for (int i = 0; i < 45; i++) { // this loop counts each bit of the bit map coreset_freq_dom, and increments nbr_RB_coreset for each bit set to '1' if (((coreset_freq_dom & 0x1FFFFFFFFFFF) >> i) & 0x1) coreset_nbr_rb++; } + coreset_nbr_rb = 6 * coreset_nbr_rb; // coreset_time_dur,coreset_nbr_rb, NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; //uint8_t mi;// = get_mi(&ue->frame_parms, nr_tti_rx); - //uint8_t tmode = ue->transmission_mode[eNB_id]; //uint8_t frame_type = frame_parms->frame_type; - uint8_t format_0_0_1_0_size_bits = 0, format_0_0_1_0_size_bytes = 0; //FIXME uint8_t format_0_1_1_1_size_bits = 0, format_0_1_1_1_size_bytes = 0; //FIXME uint8_t format_2_0_size_bits = 0, format_2_0_size_bytes = 0; //FIXME uint8_t format_2_1_size_bits = 0, format_2_1_size_bytes = 0; //FIXME uint8_t format_2_2_size_bits = 0, format_2_2_size_bytes = 0; //FIXME uint8_t format_2_3_size_bits = 0, format_2_3_size_bytes = 0; //FIXME - /* * * The implementation of this function will depend on the information given by the searchSpace IE @@ -2616,32 +2688,29 @@ uint8_t nr_dci_decoding_procedure(int s, * Implementation according to 38.213 v15.1.0 Section 10. * */ - NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t css_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.common_dci_formats; //FIXME!!! NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t uss_dci_format = pdcch_vars2->searchSpace[s].searchSpaceType.ue_specific_dci_formats; //FIXME!!! - // The following initialization is only for test purposes. To be removed // NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t css_dci_format = cformat0_0_and_1_0; //NR_UE_SEARCHSPACE_USS_DCI_FORMAT_t uss_dci_format = uformat0_0_and_1_0; - /* * Possible overlap between RE for SS/PBCH blocks (described in section 10, 38.213) has not been implemented yet * This can be implemented by setting variable 'mode = NO_DCI' when overlap occurs */ //dci_detect_mode_t mode = 3; //dci_detect_mode_select(&ue->frame_parms, nr_tti_rx); - #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> searSpaceType=%d\n",do_common); + if (do_common==0) { printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> css_dci_format=%d\n",css_dci_format); } else { printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> uss_dci_format=%d\n",uss_dci_format); } + #endif - - + // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces if (do_common==0) { // COMMON SearchSpaceType assigned to current SearchSpace/CORESET // Type0-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI @@ -2664,39 +2733,41 @@ uint8_t nr_dci_decoding_procedure(int s, // FIXME // We shall consider Table 10.1-1 to calculate the blind decoding only for Type0/Type0A/Type2-PDCCH // Shall we consider the nrofCandidates in SearSpace IE that considers Aggregation Levels 1,2,4,8,16? Our implementation considers Table 10.1-1 - // blind decoding (Type0-PDCCH,Type0A-PDCCH,Type1-PDCCH,Type2-PDCCH) // for format0_0 => we are NOT implementing format0_0 for common search spaces. FIXME! - // for format0_0 and format1_0, first we calculate dci pdu size format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,_c_rnti,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0); format_0_0_1_0_size_bytes = (format_0_0_1_0_size_bits%8 == 0) ? (uint8_t)floor(format_0_0_1_0_size_bits/8) : (uint8_t)(floor(format_0_0_1_0_size_bits/8) + 1); #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> calculating dci format size for common searchSpaces with format css_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n", - css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes); + css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes); #endif - for (int aggregationLevel = 3; aggregationLevel<4 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 - //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { - // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 + + for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 + //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { + // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 #ifdef NR_PDCCH_DCI_DEBUG - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1< common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat0_0_and_1_0, uformat0_0_and_1_0, - format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_, pdcch_DMRS_scrambling_id,&CCEmap0, &CCEmap1, &CCEmap2); - if (dci_cnt != old_dci_cnt){ - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,crc_scrambled_,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes,0); // after decoding dci successfully we recalculate dci pdu size with correct crc scrambled to get the right field sizes - old_dci_cnt = dci_cnt; - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, + crc_scrambled_values, aggregationLevel, + cformat0_0_and_1_0, uformat0_0_and_1_0, + format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, + &crc_scrambled_, &format_found_, pdcch_DMRS_scrambling_id,&CCEmap0, &CCEmap1, &CCEmap2); + + if (dci_cnt != old_dci_cnt) { + // we will exit the loop as we have found the DCI + aggregationLevel = 5; + format_0_0_1_0_size_bits = nr_dci_format_size(ue,eNB_id,nr_tti_rx,p,crc_scrambled_,n_RB_ULBWP,n_RB_DLBWP,dci_fields_sizes, + 0); // after decoding dci successfully we recalculate dci pdu size with correct crc scrambled to get the right field sizes + old_dci_cnt = dci_cnt; + + for (int i=0; i calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_0_size_bits=%d, format2_0_size_bytes=%d\n", - css_dci_format,format_2_0_size_bits,format_2_0_size_bytes); + css_dci_format,format_2_0_size_bits,format_2_0_size_bytes); #endif - for (int aggregationLevelSFI = 0; aggregationLevelSFI<5 ; aggregationLevelSFI++){ + + for (int aggregationLevelSFI = 0; aggregationLevelSFI<5 ; aggregationLevelSFI++) { #ifdef NR_PDCCH_DCI_DEBUG - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1< common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevelSFI, - cformat2_0, uformat0_0_and_1_0, - format_2_0_size_bits, format_2_0_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - if (dci_cnt != old_dci_cnt){ - // we will exit the loop as we have found the DCI - aggregationLevelSFI = 5; - old_dci_cnt = dci_cnt; - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, + crc_scrambled_values, aggregationLevelSFI, + cformat2_0, uformat0_0_and_1_0, + format_2_0_size_bits, format_2_0_size_bytes, &dci_cnt, + &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); + + if (dci_cnt != old_dci_cnt) { + // we will exit the loop as we have found the DCI + aggregationLevelSFI = 5; + old_dci_cnt = dci_cnt; + + for (int i=0; i calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_1_size_bits=%d, format2_1_size_bytes=%d\n", - css_dci_format,format_2_1_size_bits,format_2_1_size_bytes); + css_dci_format,format_2_1_size_bits,format_2_1_size_bytes); #endif - for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++){ + + for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { #ifdef NR_PDCCH_DCI_DEBUG - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1< common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat2_1, uformat0_0_and_1_0, - format_2_1_size_bits, format_2_1_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - if (dci_cnt != old_dci_cnt){ - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, + crc_scrambled_values, aggregationLevel, + cformat2_1, uformat0_0_and_1_0, + format_2_1_size_bits, format_2_1_size_bytes, &dci_cnt, + &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); + + if (dci_cnt != old_dci_cnt) { + // we will exit the loop as we have found the DCI + aggregationLevel = 5; + old_dci_cnt = dci_cnt; + + for (int i=0; i calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_2_size_bits=%d, format2_2_size_bytes=%d\n", - css_dci_format,format_2_2_size_bits,format_2_2_size_bytes); + css_dci_format,format_2_2_size_bits,format_2_2_size_bytes); #endif - for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++){ + + for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { #ifdef NR_PDCCH_DCI_DEBUG - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1< common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat2_2, uformat0_0_and_1_0, - format_2_2_size_bits, format_2_2_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - if (dci_cnt != old_dci_cnt){ - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, + crc_scrambled_values, aggregationLevel, + cformat2_2, uformat0_0_and_1_0, + format_2_2_size_bits, format_2_2_size_bytes, &dci_cnt, + &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); + + if (dci_cnt != old_dci_cnt) { + // we will exit the loop as we have found the DCI + aggregationLevel = 5; + old_dci_cnt = dci_cnt; + + for (int i=0; i calculating dci format size for common searchSpaces with format css_dci_format=%d, format2_3_size_bits=%d, format2_3_size_bytes=%d\n", - css_dci_format,format_2_3_size_bits,format_2_3_size_bytes); + css_dci_format,format_2_3_size_bits,format_2_3_size_bytes); #endif - for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++){ + + for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { #ifdef NR_PDCCH_DCI_DEBUG - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1< common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat2_3, uformat0_0_and_1_0, - format_2_3_size_bits, format_2_3_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - if (dci_cnt != old_dci_cnt){ - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, + crc_scrambled_values, aggregationLevel, + cformat2_3, uformat0_0_and_1_0, + format_2_3_size_bits, format_2_3_size_bytes, &dci_cnt, + &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); + + if (dci_cnt != old_dci_cnt) { + // we will exit the loop as we have found the DCI + aggregationLevel = 5; + old_dci_cnt = dci_cnt; + + for (int i=0; i calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_0_1_0_size_bits=%d, format_0_0_1_0_size_bytes=%d\n", - css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes); + css_dci_format,format_0_0_1_0_size_bits,format_0_0_1_0_size_bytes); #endif + for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 - //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { - // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 + //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { + // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 #ifdef NR_PDCCH_DCI_DEBUG - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1< common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat0_0_and_1_0, uformat0_0_and_1_0, - format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - if (dci_cnt != old_dci_cnt){ - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, + crc_scrambled_values, aggregationLevel, + cformat0_0_and_1_0, uformat0_0_and_1_0, + format_0_0_1_0_size_bits, format_0_0_1_0_size_bytes, &dci_cnt, + &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); + + if (dci_cnt != old_dci_cnt) { + // we will exit the loop as we have found the DCI + aggregationLevel = 5; + old_dci_cnt = dci_cnt; + + for (int i=0; i calculating dci format size for UE-specific searchSpaces with format uss_dci_format=%d, format_0_1_1_1_size_bits=%d, format_0_1_1_1_size_bytes=%d\n", - css_dci_format,format_0_1_1_1_size_bits,format_0_1_1_1_size_bytes); + css_dci_format,format_0_1_1_1_size_bits,format_0_1_1_1_size_bytes); #endif + for (int aggregationLevel = 0; aggregationLevel<5 ; aggregationLevel++) { // We fix aggregationLevel to 3 for testing=> nbr of CCE=8 - //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { - // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 + //for (int aggregationLevel = 2; aggregationLevel<5 ; aggregationLevel++) { + // for aggregation level aggregationLevel. The number of candidates (for L2= 2^aggregationLevel) will be calculated in function nr_dci_decoding_procedure0 #ifdef NR_PDCCH_DCI_DEBUG - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", - css_dci_format,(1< common searchSpaces with format css_dci_format=%d and aggregation_level=%d\n", + css_dci_format,(1<current_thread_id[nr_tti_rx], frame_parms, - crc_scrambled_values, aggregationLevel, - cformat0_0_and_1_0, uformat0_1_and_1_1, - format_0_1_1_1_size_bits, format_0_1_1_1_size_bytes, &dci_cnt, - &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); - if (dci_cnt != old_dci_cnt){ - // we will exit the loop as we have found the DCI - aggregationLevel = 5; - old_dci_cnt = dci_cnt; - for (int i=0; icurrent_thread_id[nr_tti_rx], frame_parms, + crc_scrambled_values, aggregationLevel, + cformat0_0_and_1_0, uformat0_1_and_1_1, + format_0_1_1_1_size_bits, format_0_1_1_1_size_bytes, &dci_cnt, + &crc_scrambled_, &format_found_,pdcch_DMRS_scrambling_id, &CCEmap0, &CCEmap1, &CCEmap2); + + if (dci_cnt != old_dci_cnt) { + // we will exit the loop as we have found the DCI + aggregationLevel = 5; + old_dci_cnt = dci_cnt; + + for (int i=0; i at the end crc_scrambled=%d and format_found=%d\n",*crc_scrambled,*format_found); #endif - #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_dci_decoding_procedure)-> at the end dci_cnt=%d \n",dci_cnt); #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c index 1eafbfb7dc..c067142897 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_tools_nr.c @@ -52,7 +52,7 @@ //#define DEBUG_DCI #define NR_PDCCH_DCI_TOOLS -#define NR_PDCCH_DCI_TOOLS_DEBUG +//#define NR_PDCCH_DCI_TOOLS_DEBUG typedef unsigned __int128 uint128_t; @@ -64,17 +64,10 @@ int8_t *nr_delta_PUCCH_lut = nr_delta_PUSCH_acc; #ifdef NR_PDCCH_DCI_TOOLS -uint16_t nr_dci_field(uint32_t dci_pdu[4], +uint16_t nr_dci_field(uint64_t dci_pdu[2], uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS], uint8_t dci_field) { - // uint16_t field_value = 0 ; - // first_bit_position contains the position of the first bit of the corresponding field within the dci pdu payload - - // last_bit_position contains the position of the last bit of the corresponding field within the dci pdu payload - // uint16_t last_bit_position = 0; - // uint8_t bit=0; - //printf("\tdci_field=%d, \tsize=%d \t|",dci_field,dci_fields_sizes[dci_field]); int dci_size=0; for (int i=0;i= first_bit_position) && (((i*32)+j) < last_bit_position)){ - bit = (dci_pdu[i]<<(31-j))>>31; - field_value = (field_value<<1) + bit; - //printf(" bit(%d)=%d[%d] ",(i*32)+j,bit,field_value); - } - } - */ - uint64_t *dci_pdu64=(uint64_t*)&dci_pdu[0]; - /* - printf("pdu %llx, field %d, pos %d, size %d => %u\n",(long long unsigned int)*dci_pdu64,dci_field,first_bit_position,dci_fields_sizes[dci_field], - (unsigned int)((*dci_pdu64>>first_bit_position)&((1<>first_bit_position)&((1<>i)&1)<<(dci_fields_sizes[dci_field]-i-1);*/ - return (uint16_t)((*dci_pdu64>>first_bit_position)&((1<>first_bit_position)&((1< Entering function nr_extract_dci_info() with dci_pdu=%x %x %x %x dci_length=%d\n", - dci_pdu[0],dci_pdu[1],dci_pdu[2],dci_pdu[3], dci_length); + printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> Entering function nr_extract_dci_info() with dci_pdu=%lx %lx dci_length=%d\n", + dci_pdu[0],dci_pdu[1], dci_length); printf("\t\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_extract_dci_info) -> for format %d, dci_fields_sizes {",dci_format); for (int i=0; i dci_format=%d, rnti=%d, dci_length=%d, dci_pdu[0]=%x, dci_pdu[2]=%x, dci_pdu[2]=%x, dci_pdu[3]=%x\n", - dci_format,rnti,dci_length,dci_pdu[0],dci_pdu[1],dci_pdu[2],dci_pdu[3]); + printf("\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci) -> dci_format=%d, rnti=%d, dci_length=%d, dci_pdu[0]=0x%lx, dci_pdu[1]=0x%lx\n", + dci_format,rnti,dci_length,dci_pdu[0],dci_pdu[1]); #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 2888a59606..e56ccd8af7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -39,7 +39,7 @@ #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "SCHED_NR_UE/defs.h" #include "SIMULATION/TOOLS/sim.h" -#include "targets/RT/USER/nr-uesoftmodem.h" +#include "executables/nr-uesoftmodem.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" //#define DEBUG_DLSCH_DECODING @@ -76,11 +76,11 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch) } for (r=0; r<(MAX_NUM_NR_DLSCH_SEGMENTS); r++) { - if (dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]){ - nrLDPC_free_mem(dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]); - dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL; - } - } + if (dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]){ + nrLDPC_free_mem(dlsch->harq_processes[i]->p_nrLDPC_procBuf[r]); + dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = NULL; + } + } free16(dlsch->harq_processes[i],sizeof(NR_DL_UE_HARQ_t)); dlsch->harq_processes[i] = NULL; @@ -143,7 +143,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint if (abstraction_flag == 0) { for (r=0; rharq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem(); + dlsch->harq_processes[i]->p_nrLDPC_procBuf[r] = nrLDPC_init_mem(); dlsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(1056); if (dlsch->harq_processes[i]->c[r]) @@ -192,7 +192,7 @@ void nr_dlsch_unscrambling(int16_t* llr, reset = 0; } if (((s>>(i&0x1f))&1)==1) - llr[i] = -llr[i]; + llr[i] = -llr[i]; } } @@ -203,7 +203,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, NR_UE_DLSCH_t *dlsch, NR_DL_UE_HARQ_t *harq_process, uint32_t frame, - uint16_t nb_symb_sch, + uint16_t nb_symb_sch, uint8_t nr_tti_rx, uint8_t harq_pid, uint8_t is_crnti, @@ -218,8 +218,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint32_t A,E; uint32_t G; uint32_t ret,offset; - int32_t no_iteration_ldpc; - //short dummy_w[MAX_NUM_DLSCH_SEGMENTS][3*(8448+64)]; + int32_t no_iteration_ldpc, length_dec; uint32_t r,r_offset=0,Kr=8424,Kr_bytes,K_bytes_F,err_flag=0; uint8_t crc_type; int8_t llrProcBuf[OAI_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32))); @@ -233,24 +232,22 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, int8_t l [68*384]; //__m128i l; int16_t inv_d [68*384]; -// int16_t *p_invd =&inv_d; - uint8_t kb, kc; + uint8_t kc; uint8_t Ilbrm = 0; uint32_t Tbslbrm = 950984; uint16_t nb_rb = 30; //to update - //uint16_t nb_symb_sch = 12; uint8_t nb_re_dmrs = 6; uint16_t length_dmrs = 1; + double Coderate = 0.0; uint32_t i,j; -// uint32_t k; __m128i *pv = (__m128i*)&z; __m128i *pl = (__m128i*)&l; //NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[0]; - if (!dlsch_llr) { + if (!dlsch_llr) { printf("dlsch_decoding.c: NULL dlsch_llr pointer\n"); return(dlsch->max_ldpc_iterations); } @@ -308,37 +305,59 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // This is a new packet, so compute quantities regarding segmentation harq_process->B = A+24; nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F); - p_decParams->Z = harq_process->Z; + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, // [hna] Z is Zc + &harq_process->F); + + p_decParams->Z = harq_process->Z; #ifdef DEBUG_DLSCH_DECODING printf("dlsch decoding nr segmentation Z %d\n", p_decParams->Z); - if (!frame%100) - printf("K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl); + if (!frame%100) + printf("K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, p_decParams->Z, harq_process->Nl); #endif } - kb = harq_process->K/harq_process->Z; - if ( kb==22){ - p_decParams->BG = 1; - p_decParams->R = 13; - kc = 68; - } - else{ - p_decParams->BG = 2; - p_decParams->R = 13; - kc = 52; - } + Coderate = (float) A /(float) G; + if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) + { + p_decParams->BG = 2; + if (Coderate < 0.3333){ + p_decParams->R = 15; + kc = 52; + } + else if (Coderate <0.6667){ + p_decParams->R = 13; + kc = 32; + } + else { + p_decParams->R = 23; + kc = 17; + } + } + else{ + p_decParams->BG = 1; + if (Coderate < 0.6667){ + p_decParams->R = 13; + kc = 68; + } + else if (Coderate <0.8889){ + p_decParams->R = 23; + kc = 35; + } + else { + p_decParams->R = 89; + kc = 27; + } + } - p_decParams->numMaxIter = dlsch->max_ldpc_iterations; - Kr = p_decParams->Z*kb; - p_decParams->outMode= 0; + //printf("coderate %f kc %d \n", Coderate, kc); + p_decParams->numMaxIter = dlsch->max_ldpc_iterations; + p_decParams->outMode= 0; err_flag = 0; r_offset = 0; @@ -346,27 +365,27 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, unsigned char bw_scaling =1; switch (frame_parms->N_RB_DL) { + case 106: + bw_scaling =2; + break; - case 106: - bw_scaling =2; - break; - - default: - bw_scaling =1; - break; + default: + bw_scaling =1; + break; } if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS/bw_scaling) { LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,MAX_NUM_NR_DLSCH_SEGMENTS/bw_scaling); return((1+dlsch->max_ldpc_iterations)); } + #ifdef DEBUG_DLSCH_DECODING printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); #endif opp_enabled=1; - Kr = harq_process->K; + Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb" Kr_bytes = Kr>>3; K_bytes_F = Kr_bytes-(harq_process->F>>3); @@ -383,11 +402,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, #endif nr_deinterleaving_ldpc(E, harq_process->Qm, - harq_process->w[r], + harq_process->w[r], // [hna] w is e dlsch_llr+r_offset); //for (int i =0; i<16; i++) - // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); #if UE_TIMING_TRACE stop_meas(dlsch_deinterleaving_stats); @@ -424,130 +443,110 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, #endif LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n"); return(dlsch->max_ldpc_iterations); - } else - { + } else { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif } //for (int i =0; i<16; i++) - // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); r_offset += E; #ifdef DEBUG_DLSCH_DECODING if (r==0) { - write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); + write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); + write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); } printf("decoder input(segment %d) :",r); - int i; for (i=0;i<(3*8*Kr_bytes)+12;i++) + int i; + for (i=0;i<(3*8*Kr_bytes)+12;i++) printf("%d : %d\n",i,harq_process->d[r][i]); - printf("\n"); + printf("\n"); #endif - // printf("Clearing c, %p\n",harq_process->c[r]); memset(harq_process->c[r],0,Kr_bytes); // printf("done\n"); - if (harq_process->C == 1) + if (harq_process->C == 1){ crc_type = CRC24_A; - else + length_dec = harq_process->B; + } + else{ crc_type = CRC24_B; + length_dec = (harq_process->B+24*harq_process->C)/harq_process->C; + } if (err_flag == 0) { -/* - LOG_I(PHY, "turbo algo Kr=%d cb_cnt=%d C=%d nbRB=%d crc_type %d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d maxIter %d\n", - Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, - harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); -*/ #if UE_TIMING_TRACE - start_meas(dlsch_turbo_decoding_stats); + start_meas(dlsch_turbo_decoding_stats); #endif - //LOG_E(PHY,"AbsSubframe %d.%d Start turbo segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A); + //LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A); //printf("harq process dr iteration %d\n", p_decParams->numMaxIter); - for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ - inv_d[cnt] = (1)*harq_process->d[r][cnt]; - } + memset(pv,0,2*harq_process->Z*sizeof(int16_t)); + //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); + memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); - /*for (int cnt =0; cnt < 16; cnt++){ - printf("dr %d inv_d %d \n", harq_process->d[r][cnt], inv_d[cnt]); + for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) + { + pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); } - printf(" \n"); + for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) + { + pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); + } - printf("end dr \n"); - for (int cnt =(50*p_decParams->Z-16) ; cnt < 50*p_decParams->Z; cnt++){ - printf("%d ", harq_process->d[r][cnt]); - } - printf(" \n");*/ + for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) + { + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + } - memset(pv,0,2*harq_process->Z*sizeof(int16_t)); - //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); - memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); - - for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } - - for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } - - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) - { - - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - - } - - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, + no_iteration_ldpc = nrLDPC_decoder(p_decParams, + (int8_t*)&pl[0], + llrProcBuf, p_nrLDPC_procBuf[r], p_procTime); - if (check_crc(llrProcBuf,harq_process->B,harq_process->F,crc_type)) { - printf("CRC OK\n"); - ret = 2; - } - else { - printf("CRC NOK\n"); - ret = 1+dlsch->max_ldpc_iterations; - } - + // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int + if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { + printf("Segment %d CRC OK\n",r); + ret = 2; + } + else { + printf("CRC NOK\n"); + ret = 1+dlsch->max_ldpc_iterations; + } - nb_total_decod++; - if (no_iteration_ldpc > dlsch->max_ldpc_iterations){ - nb_error_decod++; - } + nb_total_decod++; + if (no_iteration_ldpc > dlsch->max_ldpc_iterations){ + nb_error_decod++; + } - ret=no_iteration_ldpc; + ret=no_iteration_ldpc; - //if (!nb_total_decod%10000){ - //printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout); - //} - //else - //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); + //if (!nb_total_decod%10000){ + //printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout); + //} + //else + //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } + for (int m=0; m < Kr>>3; m ++) + { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } #ifdef DEBUG_DLSCH_DECODING //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); for (int k=0;k>3;k++) - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); + printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); printf("no_iterations_ldpc %d (ret %d)\n",no_iteration_ldpc,ret); //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4); #endif @@ -662,18 +661,18 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, #ifdef UE_DLSCH_PARALLELISATION uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, - UE_nr_rxtx_proc_t *proc, - int eNB_id, - short *dlsch_llr, - NR_DL_FRAME_PARMS *frame_parms, - NR_UE_DLSCH_t *dlsch, - NR_DL_UE_HARQ_t *harq_process, - uint32_t frame, - uint16_t nb_symb_sch, - uint8_t nr_tti_rx, - uint8_t harq_pid, - uint8_t is_crnti, - uint8_t llr8_flag) + UE_nr_rxtx_proc_t *proc, + int eNB_id, + short *dlsch_llr, + NR_DL_FRAME_PARMS *frame_parms, + NR_UE_DLSCH_t *dlsch, + NR_DL_UE_HARQ_t *harq_process, + uint32_t frame, + uint16_t nb_symb_sch, + uint8_t nr_tti_rx, + uint8_t harq_pid, + uint8_t is_crnti, + uint8_t llr8_flag) { #if UE_TIMING_TRACE @@ -784,27 +783,28 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, // This is a new packet, so compute quantities regarding segmentation harq_process->B = A+24; nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F); - p_decParams->Z = harq_process->Z; + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F); + + p_decParams->Z = harq_process->Z; } - kb = harq_process->K/harq_process->Z; - if ( kb==22){ - p_decParams->BG = 1; - p_decParams->R = 13; - kc = 68; - } - else{ - p_decParams->BG = 2; - p_decParams->R = 13; - kc = 52; - } + kb = harq_process->K/harq_process->Z; + if ( kb==22){ + p_decParams->BG = 1; + p_decParams->R = 13; + kc = 68; + } + else{ + p_decParams->BG = 2; + p_decParams->R = 13; + kc = 52; + } p_decParams->numMaxIter = 2; Kr = p_decParams->Z*kb; @@ -840,135 +840,133 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, #endif opp_enabled=1; -if (harq_process->C>1) { // wakeup worker if more than 1 segment - if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) { - LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id ); - exit_fun("nothing to add"); - } + if (harq_process->C>1) { // wakeup worker if more than 1 segment + if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id ); + exit_fun("nothing to add"); + } - /*Qm= harq_process->Qm; - Nl=harq_process->Nl; - r_thread = harq_process->C/2-1; - C= harq_process->C; + /*Qm= harq_process->Qm; + Nl=harq_process->Nl; + r_thread = harq_process->C/2-1; + C= harq_process->C; - Gp = G/Nl/Qm; - GpmodC = Gp%C; + Gp = G/Nl/Qm; + GpmodC = Gp%C; - if (r_thread < (C-(GpmodC))) - Er = Nl*Qm * (Gp/C); - else - Er = Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - printf("mthread Er %d\n", Er); + if (r_thread < (C-(GpmodC))) + Er = Nl*Qm * (Gp/C); + else + Er = Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); + printf("mthread Er %d\n", Er); - printf("mthread instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td);*/ + printf("mthread instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td);*/ - proc->instance_cnt_dlsch_td++; - proc->eNB_id = eNB_id; - proc->harq_pid = harq_pid; - proc->llr8_flag = llr8_flag; - //proc->r[0] = 1; + proc->instance_cnt_dlsch_td++; + proc->eNB_id = eNB_id; + proc->harq_pid = harq_pid; + proc->llr8_flag = llr8_flag; + //proc->r[0] = 1; - if (proc->instance_cnt_dlsch_td == 0) - { - LOG_D(PHY,"unblock dlsch td processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td ); - if (pthread_cond_signal(&proc->cond_dlsch_td) != 0) { - LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id); - exit_fun("nothing to add"); - } - if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) { - LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id ); - exit_fun("nothing to add"); - } + if (proc->instance_cnt_dlsch_td == 0) + { + LOG_D(PHY,"unblock dlsch td processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td ); + if (pthread_cond_signal(&proc->cond_dlsch_td) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id); + exit_fun("nothing to add"); + } + if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id ); + exit_fun("nothing to add"); + } + } else + { + LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td); + if (proc->instance_cnt_dlsch_td > 4) + exit_fun("instance_cnt_dlsch_td > 4"); + } + //AssertFatal(pthread_cond_signal(&proc->cond_slot1_dl_processing) ==0 ,""); + AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td) ==0,""); - } else - { - LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td); - if (proc->instance_cnt_dlsch_td > 4) - exit_fun("instance_cnt_dlsch_td > 4"); - } - //AssertFatal(pthread_cond_signal(&proc->cond_slot1_dl_processing) ==0 ,""); - AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td) ==0,""); + if (harq_process->C>2) { + if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id ); + exit_fun("nothing to add"); + } - if (harq_process->C>2) { - if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) { - LOG_E( PHY, "[SCHED][UE %d][Slot0] error locking mutex for UE dlsch td\n",phy_vars_ue->Mod_id ); - exit_fun("nothing to add"); - } + proc->instance_cnt_dlsch_td1++; + proc->eNB_id = eNB_id; + proc->harq_pid = harq_pid; + proc->llr8_flag = llr8_flag; + // proc->Er = Er; - proc->instance_cnt_dlsch_td1++; - proc->eNB_id = eNB_id; - proc->harq_pid = harq_pid; - proc->llr8_flag = llr8_flag; - // proc->Er = Er; + if (proc->instance_cnt_dlsch_td1 == 0) + { + LOG_D(PHY,"unblock slot1 dl processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td1 ); + if (pthread_cond_signal(&proc->cond_dlsch_td1) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id); + exit_fun("nothing to add"); + } + if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) { + LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id ); + exit_fun("nothing to add"); + } + } else + { + LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread 1 busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td1); + if (proc->instance_cnt_dlsch_td1 > 4) + exit_fun("instance_cnt_dlsch_td1 > 4"); + } - if (proc->instance_cnt_dlsch_td1 == 0) - { - LOG_D(PHY,"unblock slot1 dl processing thread blocked on instance_cnt_dlsch_td : %d \n", proc->instance_cnt_dlsch_td1 ); - if (pthread_cond_signal(&proc->cond_dlsch_td1) != 0) { - LOG_E( PHY, "[SCHED][UE %d][Slot0] ERROR pthread_cond_signal for UE dlsch td\n", phy_vars_ue->Mod_id); - exit_fun("nothing to add"); - } - if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) { - LOG_E( PHY, "[SCHED][UE %d][Slot0] error unlocking mutex for UE dlsch td \n",phy_vars_ue->Mod_id ); - exit_fun("nothing to add"); - } + AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td1) ==0,""); - } else - { - LOG_E( PHY, "[SCHED][UE %d] UE dlsch td thread 1 busy (IC %d)!!\n", phy_vars_ue->Mod_id, proc->instance_cnt_dlsch_td1); - if (proc->instance_cnt_dlsch_td1 > 4) - exit_fun("instance_cnt_dlsch_td1 > 4"); - } + } + /* + if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { + printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); + exit_fun( "error locking mutex_fep" ); + return -1; + } - AssertFatal(pthread_mutex_unlock(&proc->mutex_dlsch_td1) ==0,""); + if (proc->instance_cnt_td==0) { + printf("[UE] TD thread busy\n"); + exit_fun("TD thread busy"); + pthread_mutex_unlock( &proc->mutex_td ); + return -1; + } - } - /* - if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); - exit_fun( "error locking mutex_fep" ); - return -1; - } + ++proc->instance_cnt_td; - if (proc->instance_cnt_td==0) { - printf("[UE] TD thread busy\n"); - exit_fun("TD thread busy"); - pthread_mutex_unlock( &proc->mutex_td ); - return -1; - } + proc->tdp.UE = phy_vars_ue; + proc->tdp.eNB_id = eNB_id; + proc->tdp.harq_pid = harq_pid; + proc->tdp.llr8_flag = llr8_flag; - ++proc->instance_cnt_td; - - proc->tdp.UE = phy_vars_ue; - proc->tdp.eNB_id = eNB_id; - proc->tdp.harq_pid = harq_pid; - proc->tdp.llr8_flag = llr8_flag; - - printf("----- 2thread llr flag %d tdp flag %d\n",llr8_flag, proc->tdp.llr8_flag); + printf("----- 2thread llr flag %d tdp flag %d\n",llr8_flag, proc->tdp.llr8_flag); - // wakeup worker to do second half segments - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[UE] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (1+dlsch->last_iteration_cnt); - } + // wakeup worker to do second half segments + if (pthread_cond_signal(&proc->cond_td) != 0) { + printf("[UE] ERROR pthread_cond_signal for td thread exit\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return (1+dlsch->last_iteration_cnt); + } - pthread_mutex_unlock( &proc->mutex_td );*/ + pthread_mutex_unlock( &proc->mutex_td );*/ - Cby2 = 1; //harq_process->C/2; - //proc->decoder_main_available = 1; - } - else { - Cby2 = 1; - } + Cby2 = 1; //harq_process->C/2; + //proc->decoder_main_available = 1; + } + else { + Cby2 = 1; + } - //for (r=0; rK; Kr_bytes = Kr>>3; @@ -1039,27 +1037,27 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment } //for (int i =0; i<16; i++) - // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); //r_offset += E; //printf("main thread r_offset %d\n",r_offset); #ifdef DEBUG_DLSCH_DECODING for (int i =0; i<16; i++) - printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); #endif #ifdef DEBUG_DLSCH_DECODING if (r==0) { - write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - write_output("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0); + write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); + write_output("decoder_in.m","dec",&harq_process->d[0][96],(3*8*Kr_bytes)+12,1,0); } printf("decoder input(segment %d) :",r); for (int i=0;i<(3*8*Kr_bytes);i++) printf("%d : %d\n",i,harq_process->d[r][i]); - printf("\n"); + printf("\n"); #endif @@ -1080,98 +1078,94 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); */ - if (llr8_flag) { - AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", - Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); - } + if (llr8_flag) { + AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", + Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); + } #if UE_TIMING_TRACE - start_meas(dlsch_turbo_decoding_stats); + start_meas(dlsch_turbo_decoding_stats); #endif LOG_D(PHY,"mthread AbsSubframe %d.%d Start turbo segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1); - - for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ - inv_d[cnt] = (1)*harq_process->d[r][cnt]; - } - memset(pv,0,2*p_decParams->Z*sizeof(int16_t)); - //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); - memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); + for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ + inv_d[cnt] = (1)*harq_process->d[r][cnt]; + } + + memset(pv,0,2*p_decParams->Z*sizeof(int16_t)); + //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); + memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); - for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } + for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++) + { + pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); + } - for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } + for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) + { + pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); + } - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) - { + for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) + { + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + } - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + no_iteration_ldpc = nrLDPC_decoder(p_decParams, + (int8_t*)&pl[0], + llrProcBuf, + p_nrLDPC_procBuf, + p_procTime); - } + nb_total_decod++; + if (no_iteration_ldpc > 10){ + nb_error_decod++; + ret = 1+dlsch->max_ldpc_iterations; + } + else { + ret=2; + } - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, - p_nrLDPC_procBuf, - p_procTime); + if (check_crc(llrProcBuf,harq_process->B,harq_process->F,crc_type)) { + printf("CRC OK\n"); + ret = 2; + } + else { + printf("CRC NOK\n"); + ret = 1+dlsch->max_ldpc_iterations; + } - nb_total_decod++; - if (no_iteration_ldpc > 10){ - nb_error_decod++; - ret = 1+dlsch->max_ldpc_iterations; - } - else { - ret=2; - } - - if (check_crc(llrProcBuf,harq_process->B,harq_process->F,crc_type)) { - printf("CRC OK\n"); - ret = 2; - } - else { - printf("CRC NOK\n"); - ret = 1+dlsch->max_ldpc_iterations; - } - - //if (!nb_total_decod%10000){ - printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout); - //} + //if (!nb_total_decod%10000){ + printf("Error number of iteration LPDC %d %ld/%ld \n", no_iteration_ldpc, nb_error_decod,nb_total_decod);fflush(stdout); + //} - //else - //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); + //else + //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } + for (int m=0; m < Kr>>3; m ++) + { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } - /*for (int u=0; u < Kr>>3; u ++) - { - ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; - } + /*for (int u=0; u < Kr>>3; u ++) + { + ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; + } - printf("output unsigned ullrProcBuf \n"); + printf("output unsigned ullrProcBuf \n"); - for (int j=0; j < Kr>>3; j ++) - { + for (int j=0; j < Kr>>3; j ++) + { + printf(" %d \n", ullrProcBuf[j]); + } + printf(" \n");*/ + //printf("output channel decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - printf(" %d \n", ullrProcBuf[j]); - - } - printf(" \n");*/ - //printf("output channel decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - - //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); + //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); #ifdef DEBUG_DLSCH_DECODING - for (int k=0;k<32;k++) - printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); + for (int k=0;k<32;k++) + printf("output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); #endif #if UE_TIMING_TRACE @@ -1250,40 +1244,40 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment */ uint32_t wait = 0; if (harq_process->C==2){ - while((proc->decoder_thread_available == 0) ) + while((proc->decoder_thread_available == 0) ) { usleep(1); wait++; } } else if ((harq_process->C==3) ){ - while((proc->decoder_thread_available == 0) || (proc->decoder_thread_available1 == 0)) - { - usleep(1); - wait++; - } + while((proc->decoder_thread_available == 0) || (proc->decoder_thread_available1 == 0)) + { + usleep(1); + wait++; + } } proc->decoder_main_available = 0; for (r=0; rC; r++) { - Kr = harq_process->K; //to check if same K in all segments - Kr_bytes = Kr>>3; + Kr = harq_process->K; //to check if same K in all segments + Kr_bytes = Kr>>3; - memcpy(harq_process->b+offset, - harq_process->c[r], - Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); - offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); + memcpy(harq_process->b+offset, + harq_process->c[r], + Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0)); + offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); #ifdef DEBUG_DLSCH_DECODING - printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes); - printf("copied %d bytes to b sequence (harq_pid %d)\n", - (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); - printf("b[0] = %x,c[%d] = %x\n", - harq_process->b[offset], - harq_process->F>>3, - harq_process->c[r]); + printf("Segment %d : Kr= %d bytes\n",r,Kr_bytes); + printf("copied %d bytes to b sequence (harq_pid %d)\n", + (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)),harq_pid); + printf("b[0] = %x,c[%d] = %x\n", + harq_process->b[offset], + harq_process->F>>3, + harq_process->c[r]); #endif } @@ -1344,14 +1338,14 @@ void *nr_dlsch_decoding_2thread0(void *arg) char threadname[256]; sprintf(threadname,"UE_thread_dlsch_td_%d", proc->sub_frame_start); - cpu_set_t cpuset; + cpu_set_t cpuset; CPU_ZERO(&cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.dlsch_td_one != -1 ) - CPU_SET(threads.dlsch_td_one, &cpuset); + CPU_SET(threads.dlsch_td_one, &cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.dlsch_td_two != -1 ) - CPU_SET(threads.dlsch_td_two, &cpuset); + CPU_SET(threads.dlsch_td_two, &cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.dlsch_td_three != -1 ) - CPU_SET(threads.dlsch_td_three, &cpuset); + CPU_SET(threads.dlsch_td_three, &cpuset); @@ -1374,42 +1368,42 @@ void *nr_dlsch_decoding_2thread0(void *arg) init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, threadname); while (!oai_exit) { - //proc->decoder_thread_available = 1; - - if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" ); - exit_fun("nothing to add"); - } - while (proc->instance_cnt_dlsch_td < 0) { - // most of the time, the thread is waiting here - pthread_cond_wait( &proc->cond_dlsch_td, &proc->mutex_dlsch_td ); - } - if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" ); - exit_fun("nothing to add"); - } + //proc->decoder_thread_available = 1; + + if (pthread_mutex_lock(&proc->mutex_dlsch_td) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" ); + exit_fun("nothing to add"); + } + while (proc->instance_cnt_dlsch_td < 0) { + // most of the time, the thread is waiting here + pthread_cond_wait( &proc->cond_dlsch_td, &proc->mutex_dlsch_td ); + } + if (pthread_mutex_unlock(&proc->mutex_dlsch_td) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" ); + exit_fun("nothing to add"); + } - uint32_t wait = 0; - while(proc->decoder_main_available == 0) - { - usleep(1); - wait++; - } + uint32_t wait = 0; + while(proc->decoder_main_available == 0) + { + usleep(1); + wait++; + } - //proc->decoder_thread_available = 0; - //PHY_VARS_NR_UE *phy_vars_ue = tdp->UE; - int eNB_id = proc->eNB_id; - int harq_pid = proc->harq_pid; - llr8_flag1 = proc->llr8_flag; - //r_offset = proc->Er; - //UE_rxtx_proc_t *proc = tdp->proc; - int frame = proc->frame_rx; - int subframe = proc->nr_tti_rx; - NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]; - NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid]; - short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; - //printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag); - p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[1]; + //proc->decoder_thread_available = 0; + //PHY_VARS_NR_UE *phy_vars_ue = tdp->UE; + int eNB_id = proc->eNB_id; + int harq_pid = proc->harq_pid; + llr8_flag1 = proc->llr8_flag; + //r_offset = proc->Er; + //UE_rxtx_proc_t *proc = tdp->proc; + int frame = proc->frame_rx; + int subframe = proc->nr_tti_rx; + NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]; + NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid]; + short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; + //printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag); + p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[1]; /* if (nb_rb > frame_parms->N_RB_DL) { @@ -1442,27 +1436,27 @@ void *nr_dlsch_decoding_2thread0(void *arg) harq_process->B = A+24; nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F); - p_decParams->Z = harq_process->Z; + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F); + p_decParams->Z = harq_process->Z; } kb = harq_process->K/harq_process->Z; - if ( kb==22){ - p_decParams->BG = 1; - p_decParams->R = 13; - kc = 68; - } - else{ - p_decParams->BG = 2; - p_decParams->R = 13; - kc = 52; - } + if ( kb==22){ + p_decParams->BG = 1; + p_decParams->R = 13; + kc = 68; + } + else{ + p_decParams->BG = 2; + p_decParams->R = 13; + kc = 52; + } p_decParams->numMaxIter = 2; Kr = p_decParams->Z*kb; @@ -1508,14 +1502,14 @@ void *nr_dlsch_decoding_2thread0(void *arg) Cprime = C; //assume CBGTI not present if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - r_offset = Nl*Qm*(G/(Nl*Qm*Cprime)); + r_offset = Nl*Qm*(G/(Nl*Qm*Cprime)); else - r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1); + r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - // printf("thread0 r_offset %d\n",r_offset); - + // printf("thread0 r_offset %d\n",r_offset); + //for (r=(harq_process->C/2); rC; r++) { - r=1; //(harq_process->C/2); + r=1; //(harq_process->C/2); Kr = harq_process->K; @@ -1535,7 +1529,7 @@ void *nr_dlsch_decoding_2thread0(void *arg) dlsch_llr+r_offset); //for (int i =0; i<16; i++) - // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); #if UE_TIMING_TRACE stop_meas(dlsch_deinterleaving_stats); @@ -1580,7 +1574,7 @@ void *nr_dlsch_decoding_2thread0(void *arg) } //for (int i =0; i<16; i++) - // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); //r_offset += E; @@ -1614,10 +1608,10 @@ void *nr_dlsch_decoding_2thread0(void *arg) Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); */ - if (llr8_flag1) { - AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", - Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); - } + if (llr8_flag1) { + AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", + Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); + } #if UE_TIMING_TRACE start_meas(dlsch_turbo_decoding_stats); #endif @@ -1632,58 +1626,58 @@ void *nr_dlsch_decoding_2thread0(void *arg) memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } + { + pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); + } - for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } + for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) + { + pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); + } - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) - { + for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) + { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } + } - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, + no_iteration_ldpc = nrLDPC_decoder(p_decParams, + (int8_t*)&pl[0], + llrProcBuf, p_nrLDPC_procBuf, - p_procTime); + p_procTime); - if (no_iteration_ldpc > 10) - printf("Error number of iteration LPDC %d\n", no_iteration_ldpc); - //else - //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); + if (no_iteration_ldpc > 10) + printf("Error number of iteration LPDC %d\n", no_iteration_ldpc); + //else + //printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } + for (int m=0; m < Kr>>3; m ++) + { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } - /*for (int u=0; u < Kr>>3; u ++) - { - ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; - } + /*for (int u=0; u < Kr>>3; u ++) + { + ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; + } - printf("output unsigned ullrProcBuf \n"); + printf("output unsigned ullrProcBuf \n"); - for (int j=0; j < Kr>>3; j ++) - { + for (int j=0; j < Kr>>3; j ++) + { - printf(" %d \n", ullrProcBuf[j]); + printf(" %d \n", ullrProcBuf[j]); - } - printf(" \n");*/ -#ifdef DEBUG_DLSCH_DECODING - for (int k=0;k<2;k++) - printf("segment 1 output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); + } + printf(" \n");*/ +#ifdef DEBUG_DLSCH_DECODING + for (int k=0;k<2;k++) + printf("segment 1 output decoder [%d] = 0x%02x \n", k, harq_process->c[r][k]); #endif - + #if UE_TIMING_TRACE stop_meas(dlsch_turbo_decoding_stats); #endif @@ -1816,7 +1810,7 @@ void *nr_dlsch_decoding_2thread0(void *arg) #define FIFO_PRIORITY 39 void *nr_dlsch_decoding_2thread1(void *arg) { - static __thread int UE_dlsch_td_retval1; + static __thread int UE_dlsch_td_retval1; struct nr_rxtx_thread_data *rtd = arg; UE_nr_rxtx_proc_t *proc = rtd->proc; PHY_VARS_NR_UE *phy_vars_ue = rtd->UE; @@ -1858,14 +1852,14 @@ void *nr_dlsch_decoding_2thread1(void *arg) char threadname[256]; sprintf(threadname,"UE_thread_dlsch_td1_%d", proc->sub_frame_start); - cpu_set_t cpuset; + cpu_set_t cpuset; CPU_ZERO(&cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.dlsch_td_one != -1 ) - CPU_SET(threads.dlsch_td_one, &cpuset); + CPU_SET(threads.dlsch_td_one, &cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.dlsch_td_two != -1 ) - CPU_SET(threads.dlsch_td_two, &cpuset); + CPU_SET(threads.dlsch_td_two, &cpuset); if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.dlsch_td_three != -1 ) - CPU_SET(threads.dlsch_td_three, &cpuset); + CPU_SET(threads.dlsch_td_three, &cpuset); @@ -1879,51 +1873,51 @@ void *nr_dlsch_decoding_2thread1(void *arg) uint32_t ret,offset; uint32_t r,r_offset=0,Kr,Kr_bytes,err_flag=0,K_bytes_F; uint8_t crc_type; - uint8_t C,Cprime; + uint8_t C,Cprime; uint8_t Qm; - uint8_t Nl; + uint8_t Nl; //uint32_t Er; - init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, threadname); - printf("2thread1 oai_exit %d\n", oai_exit); - while (!oai_exit) { - if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" ); - exit_fun("nothing to add"); - } - while (proc->instance_cnt_dlsch_td1 < 0) { - // most of the time, the thread is waiting here - pthread_cond_wait( &proc->cond_dlsch_td1, &proc->mutex_dlsch_td1 ); - } - if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" ); - exit_fun("nothing to add"); - } + init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, threadname); + printf("2thread1 oai_exit %d\n", oai_exit); + while (!oai_exit) { + if (pthread_mutex_lock(&proc->mutex_dlsch_td1) != 0) { + LOG_E( PHY, "[SCHED][UE] error locking mutex for UE dlsch td\n" ); + exit_fun("nothing to add"); + } + while (proc->instance_cnt_dlsch_td1 < 0) { + // most of the time, the thread is waiting here + pthread_cond_wait( &proc->cond_dlsch_td1, &proc->mutex_dlsch_td1 ); + } + if (pthread_mutex_unlock(&proc->mutex_dlsch_td1) != 0) { + LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE dlsch_td \n" ); + exit_fun("nothing to add"); + } - //printf("2thread1 main available %d\n", proc->decoder_main_available); + //printf("2thread1 main available %d\n", proc->decoder_main_available); - uint32_t wait = 0; - while(proc->decoder_main_available == 0) - { - usleep(1); - wait++; - } - - //proc->decoder_thread_available1 = 0; - //PHY_VARS_NR_UE *phy_vars_ue = tdp->UE; - int eNB_id = proc->eNB_id; - int harq_pid = proc->harq_pid; - llr8_flag1 = proc->llr8_flag; - //r_offset = proc->Er; - //UE_rxtx_proc_t *proc = tdp->proc; - int frame = proc->frame_rx; - int subframe = proc->nr_tti_rx; - NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]; - NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid]; - short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; - //printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag); - //printf("2thread1 nr_tti_tx %d subframe %d SF thread id %d r_offset %d\n", proc->nr_tti_rx, subframe, phy_vars_ue->current_thread_id[subframe], r_offset); - p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[2]; + uint32_t wait = 0; + while(proc->decoder_main_available == 0) + { + usleep(1); + wait++; + } + + //proc->decoder_thread_available1 = 0; + //PHY_VARS_NR_UE *phy_vars_ue = tdp->UE; + int eNB_id = proc->eNB_id; + int harq_pid = proc->harq_pid; + llr8_flag1 = proc->llr8_flag; + //r_offset = proc->Er; + //UE_rxtx_proc_t *proc = tdp->proc; + int frame = proc->frame_rx; + int subframe = proc->nr_tti_rx; + NR_UE_DLSCH_t *dlsch = phy_vars_ue->dlsch[phy_vars_ue->current_thread_id[subframe]][eNB_id][0]; + NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[harq_pid]; + short *dlsch_llr = phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; + //printf("2thread0 llr flag %d tdp flag %d\n",llr8_flag1, tdp->llr8_flag); + //printf("2thread1 nr_tti_tx %d subframe %d SF thread id %d r_offset %d\n", proc->nr_tti_rx, subframe, phy_vars_ue->current_thread_id[subframe], r_offset); + p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[2]; /* if (nb_rb > frame_parms->N_RB_DL) { @@ -1958,27 +1952,27 @@ void *nr_dlsch_decoding_2thread1(void *arg) // This is a new packet, so compute quantities regarding segmentation harq_process->B = A+24; nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F); - p_decParams->Z = harq_process->Z; + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F); + p_decParams->Z = harq_process->Z; } kb = harq_process->K/harq_process->Z; - if ( kb==22){ - p_decParams->BG = 1; - p_decParams->R = 89; - kc = 68; - } - else{ - p_decParams->BG = 2; - p_decParams->R = 13; - kc = 52; - } + if ( kb==22){ + p_decParams->BG = 1; + p_decParams->R = 89; + kc = 68; + } + else{ + p_decParams->BG = 2; + p_decParams->R = 13; + kc = 52; + } p_decParams->numMaxIter = 2; Kr = p_decParams->Z*kb; @@ -2023,23 +2017,23 @@ void *nr_dlsch_decoding_2thread1(void *arg) Cprime = C; //assume CBGTI not present if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - r_offset = Nl*Qm*(G/(Nl*Qm*Cprime)); + r_offset = Nl*Qm*(G/(Nl*Qm*Cprime)); else - r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1); + r_offset = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - //printf("sub thread r_offset %d\n", r_offset); + //printf("sub thread r_offset %d\n", r_offset); //for (r=(harq_process->C/2); rC; r++) { - r=2; //(harq_process->C/2); - r_offset = r*r_offset; - //printf("thread1 r=%d r_offset %d \n",r, r_offset); + r=2; //(harq_process->C/2); + r_offset = r*r_offset; + //printf("thread1 r=%d r_offset %d \n",r, r_offset); - Kr = harq_process->K; - Kr_bytes = Kr>>3; - K_bytes_F = Kr_bytes-(harq_process->F>>3); + Kr = harq_process->K; + Kr_bytes = Kr>>3; + K_bytes_F = Kr_bytes-(harq_process->F>>3); - Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); @@ -2057,7 +2051,7 @@ void *nr_dlsch_decoding_2thread1(void *arg) dlsch_llr+r_offset); //for (int i =0; i<16; i++) - // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); #if UE_TIMING_TRACE stop_meas(dlsch_deinterleaving_stats); @@ -2080,15 +2074,15 @@ void *nr_dlsch_decoding_2thread1(void *arg) #endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - harq_process->d[r], - harq_process->w[r], - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - E)==-1) { + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -2102,7 +2096,7 @@ void *nr_dlsch_decoding_2thread1(void *arg) } //for (int i =0; i<16; i++) - // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); //r_offset += E; @@ -2134,71 +2128,71 @@ void *nr_dlsch_decoding_2thread1(void *arg) Kr,r,harq_process->C,harq_process->nb_rb,crc_type,A,harq_process->TBS, harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round,dlsch->max_ldpc_iterations); */ - if (llr8_flag1) { - AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", - Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); - } + if (llr8_flag1) { + AssertFatal (Kr >= 256, "turbo algo issue Kr=%d cb_cnt=%d C=%d nbRB=%d TBSInput=%d TBSHarq=%d TBSplus24=%d mcs=%d Qm=%d RIV=%d round=%d\n", + Kr,r,harq_process->C,harq_process->nb_rb,A,harq_process->TBS,harq_process->B,harq_process->mcs,harq_process->Qm,harq_process->rvidx,harq_process->round); + } #if UE_TIMING_TRACE start_meas(dlsch_turbo_decoding_stats); #endif // LOG_D(PHY,"AbsSubframe %d.%d Start turbo segment %d/%d \n",frame%1024,subframe,r,harq_process->C-1); - memset(pv,0,2*p_decParams->Z*sizeof(int16_t)); + memset(pv,0,2*p_decParams->Z*sizeof(int16_t)); //memset(pl,0,2*p_decParams->Z*sizeof(int8_t)); - memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); + memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t)); for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F+((2*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } + { + pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); + } - for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) - { - pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); - } + for (i=Kr_bytes+((2*p_decParams->Z)>>3),j=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) + { + pv[i]= _mm_loadu_si128((__m128i*)(&inv_d[8*j])); + } - for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) - { + for (i=0, j=0; j < ((kc*p_decParams->Z)>>4); i+=2, j++) + { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); + pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } + } - no_iteration_ldpc = nrLDPC_decoder(p_decParams, - (int8_t*)&pl[0], - llrProcBuf, + no_iteration_ldpc = nrLDPC_decoder(p_decParams, + (int8_t*)&pl[0], + llrProcBuf, p_nrLDPC_procBuf, - p_procTime); + p_procTime); - if (no_iteration_ldpc > 10) - printf("Error number of iteration LPDC %d\n", no_iteration_ldpc); - //else - // printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); + if (no_iteration_ldpc > 10) + printf("Error number of iteration LPDC %d\n", no_iteration_ldpc); + //else + // printf("OK number of iteration LPDC %d\n", no_iteration_ldpc); - for (int m=0; m < Kr>>3; m ++) - { - harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; - } + for (int m=0; m < Kr>>3; m ++) + { + harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; + } - /*for (int u=0; u < Kr>>3; u ++) - { - ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; - } + /*for (int u=0; u < Kr>>3; u ++) + { + ullrProcBuf[u]= (uint8_t) llrProcBuf[u]; + } - printf("output unsigned ullrProcBuf \n"); + printf("output unsigned ullrProcBuf \n"); - for (int j=0; j < Kr>>3; j ++) - { + for (int j=0; j < Kr>>3; j ++) + { - printf(" %d \n", ullrProcBuf[j]); + printf(" %d \n", ullrProcBuf[j]); - } - printf(" \n");*/ + } + printf(" \n");*/ #endif - //printf("output channel decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); + //printf("output channel decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); + //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); #if UE_TIMING_TRACE stop_meas(dlsch_turbo_decoding_stats); @@ -2237,7 +2231,7 @@ void *nr_dlsch_decoding_2thread1(void *arg) //printf("end 2thread1 proc->instance_cnt_dlsch_td1 %d\n", proc->instance_cnt_dlsch_td1); } - //printf("after 2thread1 after oai exit proc->instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td1); + //printf("after 2thread1 after oai exit proc->instance_cnt_dlsch_td %d\n", proc->instance_cnt_dlsch_td1); // thread finished free(arg); return &UE_dlsch_td_retval1; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index a9f6b02567..3a7af2e6be 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -203,14 +203,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, #endif } else { - LOG_E(PHY,"[UE][FATAL] Frame %d nr_tti_rx %d: no active DLSCH\n",ue->proc.proc_rxtx[0].frame_rx,nr_tti_rx); + LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n",nr_tti_rx); return(-1); } beamforming_mode = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]; break; default: - LOG_E(PHY,"[UE][FATAL] Frame %d nr_tti_rx %d: Unknown PDSCH format %d\n",ue->proc.proc_rxtx[0].frame_rx,nr_tti_rx,type); + LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n",nr_tti_rx,type); return(-1); break; } @@ -1350,7 +1350,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, unsigned char aatx,aarx,pilots=0; __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; - + QAM_amp128b = _mm_setzero_si128(); if (symbol == 2){ pilots=1; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 4a6e6423f6..40cbb0d23e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -35,10 +35,12 @@ #include "PHY/INIT/phy_init.h" #include "PHY/MODULATION/modulation_UE.h" #include "nr_transport_proto_ue.h" +#include "PHY/NR_UE_ESTIMATION/nr_estimation.h" //#include "SCHED/defs.h" //#include "SCHED/extern.h" #include "common_lib.h" +#include #include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_REFSIG/sss_nr.h" @@ -51,59 +53,126 @@ int cnt=0; #define DEBUG_INITIAL_SYNCH -int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) + +// create a new node of SSB structure +NR_UE_SSB* create_ssb_node(uint8_t i, uint8_t h) { + + NR_UE_SSB *new_node = (NR_UE_SSB*)malloc(sizeof(NR_UE_SSB)); + new_node->i_ssb = i; + new_node->n_hf = h; + new_node->c_re = 0; + new_node->c_im = 0; + new_node->metric = 0; + new_node->next_ssb = NULL; + + return new_node; +} + + +// insertion of the structure in the ordered list (highest metric first) +NR_UE_SSB* insert_into_list(NR_UE_SSB *head, NR_UE_SSB *node) { + + if (node->metric > head->metric) { + node->next_ssb = head; + head = node; + return head; + } + + NR_UE_SSB *current = head; + while (current->next_ssb !=NULL) { + NR_UE_SSB *temp=current->next_ssb; + if(node->metric > temp->metric) { + node->next_ssb = temp; + current->next_ssb = node; + return head; + } + else + current = temp; + } + current->next_ssb = node; + + return head; +} + + +void free_list(NR_UE_SSB *node) { + if (node->next_ssb != NULL) + free_list(node->next_ssb); + free(node); +} + + +int nr_pbch_detection(PHY_VARS_NR_UE *ue, int pbch_initial_symbol, runmode_t mode) { NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int ret =-1; + NR_UE_SSB *best_ssb = NULL; + NR_UE_SSB *current_ssb; + #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id, ue->rx_offset); #endif - // save the nb_prefix_samples0 since we are not synchronized to subframes yet and the SSB has all symbols with nb_prefix_samples - int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples; + uint8_t N_L = (frame_parms->Lmax == 4)? 4:8; + uint8_t N_hf = (frame_parms->Lmax == 4)? 2:1; - //symbol 1 - nr_slot_fep(ue, - 1, - 0, - ue->ssb_offset, - 0, - 1, - NR_PBCH_EST); - - //symbol 2 - nr_slot_fep(ue, - 2, - 0, - ue->ssb_offset, - 0, - 1, - NR_PBCH_EST); + // loops over possible pbch dmrs cases to retrive best estimated i_ssb (and n_hf for Lmax=4) for multiple ssb detection + for (int hf = 0; hf < N_hf; hf++) { + for (int l = 0; l < N_L ; l++) { - //symbol 3 - nr_slot_fep(ue, - 3, - 0, - ue->ssb_offset, - 0, - 1, - NR_PBCH_EST); + // initialization of structure + current_ssb = create_ssb_node(l,hf); + +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_channel_estimation_stats); +#endif + // computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf + for(int i=pbch_initial_symbol; idlsch_channel_estimation_stats); +#endif + + current_ssb->metric = current_ssb->c_re*current_ssb->c_re + current_ssb->c_im+current_ssb->c_re; + + // generate a list of SSB structures + if (best_ssb == NULL) + best_ssb = current_ssb; + else + best_ssb = insert_into_list(best_ssb,current_ssb); + + } + } + + NR_UE_SSB *temp_ptr=best_ssb; + while (ret!=0 && temp_ptr != NULL) { + +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_channel_estimation_stats); +#endif + // computing channel estimation for selected best ssb + for(int i=pbch_initial_symbol; ii_ssb,temp_ptr->n_hf); +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_channel_estimation_stats); +#endif + + ret = nr_rx_pbch(ue, + 0, + ue->pbch_vars[0], + frame_parms, + 0, + temp_ptr->i_ssb, + SISO, + ue->high_speed_flag); + + temp_ptr=temp_ptr->next_ssb; + } + + free_list(best_ssb); - //put back nb_prefix_samples0 - frame_parms->nb_prefix_samples0 = nb_prefix_samples0; - - - ret = nr_rx_pbch(ue, - &ue->proc.proc_rxtx[0], - ue->pbch_vars[0], - frame_parms, - 0, - SISO, - ue->high_speed_flag); - if (ret==0) { @@ -119,11 +188,6 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) // ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2]; // ue->pbch_vars[0]->decoded_output[2] = dummy; - for(int i=0; iproc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx; - } #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully\n",ue->Mod_id); #endif @@ -140,9 +204,10 @@ char prefix_string[2][9] = {"NORMAL","EXTENDED"}; int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) { - int32_t sync_pos, sync_pos_slot; // k_ssb, N_ssb_crb, sync_pos2, + int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, int32_t metric_tdd_ncp=0; uint8_t phase_tdd_ncp; + double im, re; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; int ret=-1; @@ -182,25 +247,58 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) /* process pss search on received buffer */ sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE); - sync_pos_slot = (fp->samples_per_subframe/fp->slots_per_subframe) - 10*(fp->ofdm_symbol_size + fp->nb_prefix_samples); - - if (sync_pos >= fp->nb_prefix_samples){ - ue->ssb_offset = sync_pos - fp->nb_prefix_samples;} - else{ - ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;} - - ue->rx_offset = ue->ssb_offset - sync_pos_slot; - + if (sync_pos >= fp->nb_prefix_samples) + ue->ssb_offset = sync_pos - fp->nb_prefix_samples; + else + ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples; + + //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n", ue->Mod_id, sync_pos,ue->common_vars.eNb_id); - LOG_I(PHY,"sync_pos %d ssb_offset %d sync_pos_slot %d \n",sync_pos,ue->ssb_offset,sync_pos_slot); + LOG_I(PHY,"sync_pos %d ssb_offset %d \n",sync_pos,ue->ssb_offset); #endif + // digital compensation of FFO for SSB symbols + if (ue->UE_fo_compensation){ + double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time + double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample + + int start = ue->ssb_offset; // start for offset correction is at ssb_offset (pss time position) + int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples); // loop over samples in 4 symbols (ssb size), including prefix + + for(int n=start; nnb_antennas_rx; ar++) { + re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]); + im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]); + ((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); + ((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle))); + } + } + } + + /* check that SSS/PBCH block is continuous inside the received buffer */ if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) { + /* slop_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */ + /* for NR this is not the case but slot_fep is still used for computing FFT of samples */ + /* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */ + /* symbol number are from beginning of SS/PBCH blocks as below: */ + /* Signal PSS PBCH SSS PBCH */ + /* symbol number 0 1 2 3 */ + /* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */ + /* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */ + + for(int i=0; i<4;i++) + nr_slot_fep(ue, + i, + 0, + ue->ssb_offset, + 0, + NR_PBCH_EST); + #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"Calling sss detection (normal CP)\n"); #endif @@ -211,15 +309,22 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) //nr_init_frame_parms_ue(fp,NR_MU_1,NORMAL,n_ssb_crb,0); nr_gold_pbch(ue); - ret = nr_pbch_detection(ue,mode); - + ret = nr_pbch_detection(ue,1,mode); // start pbch detection at first symbol after pss + + if (ret == 0) { + // sync at symbol ue->symbol_offset + // computing the offset wrt the beginning of the frame + sync_pos_frame = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)+((ue->symbol_offset)-1)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); + ue->rx_offset = ue->ssb_offset - sync_pos_frame; + } + nr_gold_pdcch(ue,0, 2); /* int nb_prefix_samples0 = fp->nb_prefix_samples0; fp->nb_prefix_samples0 = fp->nb_prefix_samples; - nr_slot_fep(ue,0, 0, ue->ssb_offset, 0, 1, NR_PDCCH_EST); - nr_slot_fep(ue,1, 0, ue->ssb_offset, 0, 1, NR_PDCCH_EST); + nr_slot_fep(ue,0, 0, ue->ssb_offset, 0, NR_PDCCH_EST); + nr_slot_fep(ue,1, 0, ue->ssb_offset, 0, NR_PDCCH_EST); fp->nb_prefix_samples0 = nb_prefix_samples0; LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n", @@ -236,7 +341,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) } else { #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"TDD Normal prefix: SSS error condition: sync_pos %d, sync_pos_slot %d\n", sync_pos, sync_pos_slot); + LOG_I(PHY,"TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos); #endif } } @@ -244,7 +349,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) ret = -1; } - /* Consider this is a false detection if the offset is > 1000 Hz */ + /* Consider this is a false detection if the offset is > 1000 Hz + Not to be used now that offest estimation is in place if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) ) { ret=-1; @@ -253,7 +359,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) #else LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset); #endif - } + }*/ if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters @@ -268,9 +374,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) if (ue->UE_scan_carrier == 0) { #if UE_AUTOTEST_TRACE - LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n", + LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : rx_offset %d, freq_offset %d \n", ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, ue->rx_offset, ue->common_vars.freq_offset ); #endif @@ -281,30 +386,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) } -#if DISABLE_LOG_X - printf("[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, - 10*log10(ue->measurements.rssi), - ue->rx_total_gain_dB, - ue->measurements.n0_power_tot_dBm, - 10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB, - (10*log10(ue->measurements.rsrq[0]))); - - - printf("[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d\n", - ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - duplex_string[fp->frame_type], - prefix_string[fp->Ncp], - fp->Nid_cell, - fp->N_RB_DL, - fp->phich_config_common.phich_duration, - phich_string[fp->phich_config_common.phich_resource], - fp->nb_antenna_ports_eNB); -#else - LOG_I(PHY, "[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, + LOG_I(PHY, "[UE %d] RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, 10*log10(ue->measurements.rssi), ue->rx_total_gain_dB, @@ -322,22 +404,12 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) fp->phich_config_common.phich_duration, phich_string[fp->phich_config_common.phich_resource], fp->nb_antenna_ports_eNB);*/ -#endif #if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) -# if DISABLE_LOG_X - printf("[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", + LOG_I(PHY, "[UE %d] Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, + openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset, ue->common_vars.freq_offset); -# else - LOG_I(PHY, "[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", - ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, - ue->common_vars.freq_offset); -# endif #endif } else { #ifdef DEBUG_INITIAL_SYNC diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index a0b150eda1..a50edecb2c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -34,12 +34,13 @@ #include "PHY/phy_extern_nr_ue.h" #include "PHY/sse_intrin.h" #include "PHY/LTE_REFSIG/lte_refsig.h" +#include "PHY/INIT/phy_init.h" //#define DEBUG_PBCH 1 //#define DEBUG_PBCH_ENCODING #ifdef OPENAIR2 -//#include "PHY_INTERFACE/defs.h" + //#include "PHY_INTERFACE/defs.h" #endif #define PBCH_A 24 @@ -47,42 +48,39 @@ #define print_shorts(s,x) printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s,((int16_t*)x)[0],((int16_t*)x)[1],((int16_t*)x)[2],((int16_t*)x)[3],((int16_t*)x)[4],((int16_t*)x)[5],((int16_t*)x)[6],((int16_t*)x)[7]) uint16_t nr_pbch_extract(int **rxdataF, - int **dl_ch_estimates, - int **rxdataF_ext, - int **dl_ch_estimates_ext, - uint32_t symbol, - uint32_t s_offset, - uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms) -{ - - + int **dl_ch_estimates, + int **rxdataF_ext, + int **dl_ch_estimates_ext, + uint32_t symbol, + uint32_t s_offset, + uint32_t high_speed_flag, + NR_DL_FRAME_PARMS *frame_parms) { uint16_t rb; uint8_t i,j,aarx; int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; - int nushiftmod4 = frame_parms->nushift; - unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; //and + if (rx_offset>= frame_parms->ofdm_symbol_size) rx_offset-=frame_parms->ofdm_symbol_size; - - AssertFatal(symbol>=1 && symbol<5, - "symbol %d illegal for PBCH extraction\n", - symbol); + + AssertFatal(symbol>=1 && symbol<5, + "symbol %d illegal for PBCH extraction\n", + symbol); for (aarx=0; aarxnb_antennas_rx; aarx++) { - rxF = &rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size]; rxF_ext = &rxdataF_ext[aarx][symbol*20*12]; #ifdef DEBUG_PBCH - printf("extract_rbs (nushift %d): rx_offset=%d, symbol %d\n",frame_parms->nushift, - (rx_offset + ((symbol+s_offset)*(frame_parms->ofdm_symbol_size))),symbol); - int16_t *p = (int16_t *)rxF; - for (int i =0; i<8;i++){ - printf("rxF [%d]= %d\n",i,rxF[i]); - printf("pbch extract rxF %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]); - printf("rxF ext addr %p\n", &rxF_ext[i]); - } + printf("extract_rbs (nushift %d): rx_offset=%d, symbol %d\n",frame_parms->nushift, + (rx_offset + ((symbol+s_offset)*(frame_parms->ofdm_symbol_size))),symbol); + int16_t *p = (int16_t *)rxF; + + for (int i =0; i<8; i++) { + printf("rxF [%d]= %d\n",i,rxF[i]); + printf("pbch extract rxF %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]); + printf("rxF ext addr %p\n", &rxF_ext[i]); + } + #endif for (rb=0; rb<20; rb++) { @@ -95,41 +93,43 @@ uint16_t nr_pbch_extract(int **rxdataF, (i!=(nushiftmod4+8))) { rxF_ext[j]=rxF[rx_offset]; #ifdef DEBUG_PBCH - printf("rxF ext[%d] = (%d,%d) rxF [%d]= (%d,%d)\n",(9*rb) + j, - ((int16_t*)&rxF_ext[j])[0], - ((int16_t*)&rxF_ext[j])[1], - rx_offset, - ((int16_t*)&rxF[rx_offset])[0], - ((int16_t*)&rxF[rx_offset])[1]); + printf("rxF ext[%d] = (%d,%d) rxF [%d]= (%d,%d)\n",(9*rb) + j, + ((int16_t *)&rxF_ext[j])[0], + ((int16_t *)&rxF_ext[j])[1], + rx_offset, + ((int16_t *)&rxF[rx_offset])[0], + ((int16_t *)&rxF[rx_offset])[1]); #endif - j++; + j++; } - rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); + + rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); } + rxF_ext+=9; } else { //symbol 2 - if ((rb < 4) || (rb >15)){ - for (i=0; i<12; i++) { - if ((i!=nushiftmod4) && - (i!=(nushiftmod4+4)) && - (i!=(nushiftmod4+8))) { - rxF_ext[j]=rxF[rx_offset]; + if ((rb < 4) || (rb >15)) { + for (i=0; i<12; i++) { + if ((i!=nushiftmod4) && + (i!=(nushiftmod4+4)) && + (i!=(nushiftmod4+8))) { + rxF_ext[j]=rxF[rx_offset]; #ifdef DEBUG_PBCH - printf("rxF ext[%d] = (%d,%d) rxF [%d]= (%d,%d)\n",(rb<4) ? (9*rb) + j : (9*(rb-12))+j, - ((int16_t*)&rxF_ext[j])[0], - ((int16_t*)&rxF_ext[j])[1], - rx_offset, - ((int16_t*)&rxF[rx_offset])[0], - ((int16_t*)&rxF[rx_offset])[1]); -#endif - j++; - } - rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); - } - rxF_ext+=9; - } - else rx_offset = (rx_offset+12)&(frame_parms->ofdm_symbol_size-1); - + printf("rxF ext[%d] = (%d,%d) rxF [%d]= (%d,%d)\n",(rb<4) ? (9*rb) + j : (9*(rb-12))+j, + ((int16_t *)&rxF_ext[j])[0], + ((int16_t *)&rxF_ext[j])[1], + rx_offset, + ((int16_t *)&rxF[rx_offset])[0], + ((int16_t *)&rxF[rx_offset])[1]); +#endif + j++; + } + + rx_offset=(rx_offset+1)&(frame_parms->ofdm_symbol_size-1); + } + + rxF_ext+=9; + } else rx_offset = (rx_offset+12)&(frame_parms->ofdm_symbol_size-1); } } @@ -137,56 +137,59 @@ uint16_t nr_pbch_extract(int **rxdataF, dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))]; else dl_ch0 = &dl_ch_estimates[aarx][0]; - + //printf("dl_ch0 addr %p\n",dl_ch0); - dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*20*12]; - + for (rb=0; rb<20; rb++) { j=0; + if (symbol==1 || symbol==3) { - for (i=0; i<12; i++) { - if ((i!=nushiftmod4) && - (i!=(nushiftmod4+4)) && - (i!=(nushiftmod4+8))) { - dl_ch0_ext[j]=dl_ch0[i]; + for (i=0; i<12; i++) { + if ((i!=nushiftmod4) && + (i!=(nushiftmod4+4)) && + (i!=(nushiftmod4+8))) { + dl_ch0_ext[j]=dl_ch0[i]; #ifdef DEBUG_PBCH - if ((rb==0) && (i<2)) - printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j, - ((int16_t*)&dl_ch0_ext[j])[0], - ((int16_t*)&dl_ch0_ext[j])[1], - i, - ((int16_t*)&dl_ch0[i])[0], - ((int16_t*)&dl_ch0[i])[1]); + + if ((rb==0) && (i<2)) + printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j, + ((int16_t *)&dl_ch0_ext[j])[0], + ((int16_t *)&dl_ch0_ext[j])[1], + i, + ((int16_t *)&dl_ch0[i])[0], + ((int16_t *)&dl_ch0[i])[1]); + #endif - j++; - } - } - - dl_ch0+=12; - dl_ch0_ext+=9; - } - else { - if ((rb < 4) || (rb >15)){ - for (i=0; i<12; i++) { - if ((i!=nushiftmod4) && - (i!=(nushiftmod4+4)) && - (i!=(nushiftmod4+8))) { - dl_ch0_ext[j]=dl_ch0[i]; + j++; + } + } + + dl_ch0+=12; + dl_ch0_ext+=9; + } else { + if ((rb < 4) || (rb >15)) { + for (i=0; i<12; i++) { + if ((i!=nushiftmod4) && + (i!=(nushiftmod4+4)) && + (i!=(nushiftmod4+8))) { + dl_ch0_ext[j]=dl_ch0[i]; #ifdef DEBUG_PBCH - printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j, - ((int16_t*)&dl_ch0_ext[j])[0], - ((int16_t*)&dl_ch0_ext[j])[1], - i, - ((int16_t*)&dl_ch0[i])[0], - ((int16_t*)&dl_ch0[i])[1]); + printf("dl ch0 ext[%d] = (%d,%d) dl_ch0 [%d]= (%d,%d)\n",j, + ((int16_t *)&dl_ch0_ext[j])[0], + ((int16_t *)&dl_ch0_ext[j])[1], + i, + ((int16_t *)&dl_ch0[i])[0], + ((int16_t *)&dl_ch0[i])[1]); #endif - j++; - } - } - dl_ch0_ext+=9; - } - dl_ch0+=12; + j++; + } + } + + dl_ch0_ext+=9; + } + + dl_ch0+=12; } } } @@ -198,13 +201,10 @@ uint16_t nr_pbch_extract(int **rxdataF, //compute average channel_level on each (TX,RX) antenna pair int nr_pbch_channel_level(int **dl_ch_estimates_ext, - NR_DL_FRAME_PARMS *frame_parms, - uint32_t symbol) -{ - + NR_DL_FRAME_PARMS *frame_parms, + uint32_t symbol) { int16_t rb, nb_rb=20; uint8_t aarx; - #if defined(__x86_64__) || defined(__i386__) __m128i avg128; __m128i *dl_ch128; @@ -216,180 +216,83 @@ int nr_pbch_channel_level(int **dl_ch_estimates_ext, for (aarx=0; aarxnb_antennas_rx; aarx++) { //clear average level - #if defined(__x86_64__) || defined(__i386__) avg128 = _mm_setzero_si128(); dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][symbol*20*12]; #elif defined(__arm__) avg128 = vdupq_n_s32(0); dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[aarx][symbol*20*12]; - #endif + for (rb=0; rbavg2) avg2 = avg1; - + //LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2); } + #if defined(__x86_64__) || defined(__i386__) _mm_empty(); _m_empty(); #endif return(avg2); - } void nr_pbch_channel_compensation(int **rxdataF_ext, - int **dl_ch_estimates_ext, - int **rxdataF_comp, - NR_DL_FRAME_PARMS *frame_parms, - uint32_t symbol, - uint8_t output_shift) -{ - - short conjugate[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1}; - //short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; -#if defined(__x86_64__) || defined(__i386__) - __m128i mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; -#elif defined(__arm__) - int16x8_t mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3; -#endif - - uint16_t nb_re=180; - uint8_t aarx; - -#if defined(__x86_64__) || defined(__i386__) - __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128; -#elif defined(__arm__) - -#endif - + int **dl_ch_estimates_ext, + int **rxdataF_comp, + NR_DL_FRAME_PARMS *frame_parms, + uint32_t symbol, + uint8_t output_shift) { + const uint16_t nb_re=symbol == 2 ? 72 : 180; AssertFatal((symbol > 0 && symbol < 4), - "symbol %d is illegal for PBCH DM-RS\n", - symbol); - - if (symbol == 2) nb_re = 72; + "symbol %d is illegal for PBCH DM-RS\n", + symbol); // printf("comp: symbol %d : nb_re %d\n",symbol,nb_re); - for (aarx=0; aarxnb_antennas_rx; aarx++) { - -#if defined(__x86_64__) || defined(__i386__) - dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*20*12]; - rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*20*12]; - rxdataF_comp128 = (__m128i *)&rxdataF_comp[aarx][symbol*20*12]; + for (int aarx=0; aarxnb_antennas_rx; aarx++) { + vect128 *dl_ch128 = (vect128 *)&dl_ch_estimates_ext[aarx][symbol*20*12]; + vect128 *rxdataF128 = (vect128 *)&rxdataF_ext[aarx][symbol*20*12]; + vect128 *rxdataF_comp128 = (vect128 *)&rxdataF_comp[aarx][symbol*20*12]; /* printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[aarx][symbol*20*12]); printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol); - printf("rxdataf_comp addr %p\n",&rxdataF_comp[aarx][symbol*20*12]); + printf("rxdataf_comp addr %p\n",&rxdataF_comp[aarx][symbol*20*12]); */ -#elif defined(__arm__) -// to be filled in -#endif for (int re=0; renb_antennas_rx>1) { #if defined(__x86_64__) || defined(__i386__) - rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[0][symbol_mod*6*12]; - rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[1][symbol_mod*6*12]; + rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[0][symbol_mod*6*12]; + rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[1][symbol_mod*6*12]; #elif defined(__arm__) - rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[0][symbol_mod*6*12]; - rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[1][symbol_mod*6*12]; - + rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[0][symbol_mod*6*12]; + rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[1][symbol_mod*6*12]; #endif - // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) - for (i=0; illr; - - reset = 1; // x1 is set in first call to lte_gold_generic x2 = Nid; //this is c_init @@ -448,48 +347,49 @@ void nr_pbch_unscrambling(NR_UE_PBCH *pbch, s = lte_gold_generic(&x1, &x2, reset); reset = 0; } + // Scrambling is now done with offset (nushift*M)%32 offset = (nushift*M)&0x1f; for (int i=0; i>i)&1))) { s = lte_gold_generic(&x1, &x2, reset); reset = 0; - } - (pbch->pbch_a_interleaved) ^= ((unscrambling_mask>>i)&1)? ((pbch->pbch_a_prime>>i)&1)<pbch_a_prime>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<>i)&1)); -#ifdef DEBUG_PBCH_ENCODING - printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t pbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, pbch->pbch_a_interleaved, (!((unscrambling_mask>>i)&1))); -#endif } - else { + (pbch->pbch_a_interleaved) ^= ((unscrambling_mask>>i)&1)? ((pbch->pbch_a_prime>>i)&1)<pbch_a_prime>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<>i)&1)); +#ifdef DEBUG_PBCH_ENCODING + printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t pbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, pbch->pbch_a_interleaved, + (!((unscrambling_mask>>i)&1))); +#endif + } else { if (((i+offset)&0x1f)==0) { s = lte_gold_generic(&x1, &x2, reset); reset = 0; } - if (((s>>((i+offset)&0x1f))&1)==1) - demod_pbch_e[i] = -demod_pbch_e[i]; -#ifdef DEBUG_PBCH_ENCODING - if (i<8) - printf("s %d demod_pbch_e[i] %d\n", ((s>>((i+offset)&0x1f))&1), demod_pbch_e[i]); -#endif - } - } + if (((s>>((i+offset)&0x1f))&1)==1) + demod_pbch_e[i] = -demod_pbch_e[i]; + +#ifdef DEBUG_PBCH_ENCODING + + if (i<8) + printf("s %d demod_pbch_e[i] %d\n", ((s>>((i+offset)&0x1f))&1), demod_pbch_e[i]); + +#endif + } + } } void nr_pbch_quantize(int16_t *pbch_llr8, int16_t *pbch_llr, - uint16_t len) -{ - + uint16_t len) { uint16_t i; for (i=0; icommon_vars; - int max_h=0; - int symbol; //uint8_t pbch_a[64]; uint8_t *pbch_a = malloc(sizeof(uint8_t) * 32); //uint32_t pbch_a_prime; int16_t *pbch_e_rx; uint8_t *decoded_output = nr_ue_pbch_vars->decoded_output; - uint8_t nushift; + uint8_t nushift,n_hf,ssb_index; uint16_t M; - uint8_t Lmax=8; //to update - uint8_t ssb_index=0; + uint8_t Lmax=frame_parms->Lmax; //uint16_t crc; //unsigned short idx_demod =0; uint32_t decoderState=0; //uint8_t decoderListSize = 8, pathMetricAppr = 0; - //time_stats_t polar_decoder_init,polar_rate_matching,decoding,bit_extraction,deinterleaving; //time_stats_t path_metric,sorting,update_LLR; memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS); - //printf("nr_pbch_ue nid_cell %d\n",frame_parms->Nid_cell); - - int subframe_rx = proc->subframe_rx; - pbch_e_rx = &nr_ue_pbch_vars->llr[0]; - // clear LLR buffer memset(nr_ue_pbch_vars->llr,0,NR_POLAR_PBCH_E); - int symbol_offset=1; + if (ue->is_synchronized > 0) - symbol_offset=4; + symbol_offset=ue->symbol_offset; else symbol_offset=0; #ifdef DEBUG_PBCH - //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF); - write_output("rxdataF0_pbch.m","rxF0pbch", - &nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1); + //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF); + write_output("rxdataF0_pbch.m","rxF0pbch", + &nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1); #endif - // symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot + // symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot for (symbol=1; symbol<4; symbol++) { - nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF, - nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].dl_ch_estimates[eNB_id], - nr_ue_pbch_vars->rxdataF_ext, - nr_ue_pbch_vars->dl_ch_estimates_ext, - symbol, - symbol_offset, - high_speed_flag, - frame_parms); + nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].dl_ch_estimates[eNB_id], + nr_ue_pbch_vars->rxdataF_ext, + nr_ue_pbch_vars->dl_ch_estimates_ext, + symbol, + symbol_offset, + high_speed_flag, + frame_parms); #ifdef DEBUG_PBCH LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size ); LOG_I(PHY,"[PHY] PBCH starting channel_level\n"); @@ -582,113 +470,90 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, if (symbol == 1) { max_h = nr_pbch_channel_level(nr_ue_pbch_vars->dl_ch_estimates_ext, - frame_parms, - symbol); + frame_parms, + symbol); nr_ue_pbch_vars->log2_maxh = 3+(log2_approx(max_h)/2); } #ifdef DEBUG_PBCH LOG_I(PHY,"[PHY] PBCH log2_maxh = %d (%d)\n",nr_ue_pbch_vars->log2_maxh,max_h); #endif - nr_pbch_channel_compensation(nr_ue_pbch_vars->rxdataF_ext, - nr_ue_pbch_vars->dl_ch_estimates_ext, - nr_ue_pbch_vars->rxdataF_comp, - frame_parms, - symbol, - nr_ue_pbch_vars->log2_maxh); // log2_maxh+I0_shift + nr_ue_pbch_vars->dl_ch_estimates_ext, + nr_ue_pbch_vars->rxdataF_comp, + frame_parms, + symbol, + nr_ue_pbch_vars->log2_maxh); // log2_maxh+I0_shift /*if (frame_parms->nb_antennas_rx > 1) pbch_detection_mrc(frame_parms, nr_ue_pbch_vars->rxdataF_comp, symbol);*/ -/* - if (mimo_mode == ALAMOUTI) { - nr_pbch_alamouti(frame_parms,nr_ue_pbch_vars->rxdataF_comp,symbol); - } else if (mimo_mode != SISO) { - LOG_I(PHY,"[PBCH][RX] Unsupported MIMO mode\n"); - return(-1); - } -*/ + /* + if (mimo_mode == ALAMOUTI) { + nr_pbch_alamouti(frame_parms,nr_ue_pbch_vars->rxdataF_comp,symbol); + } else if (mimo_mode != SISO) { + LOG_I(PHY,"[PBCH][RX] Unsupported MIMO mode\n"); + return(-1); + } + */ if (symbol==1) { nr_pbch_quantize(pbch_e_rx, - (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]), - 144); - + (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]), + 144); pbch_e_rx+=144; } else { nr_pbch_quantize(pbch_e_rx, - (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]), - 360); - + (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]), + 360); pbch_e_rx+=360; } - - } #ifdef DEBUG_PBCH write_output("rxdataF_comp.m","rxFcomp",&nr_ue_pbch_vars->rxdataF_comp[0][240],240*3,1,1); #endif - - pbch_e_rx = nr_ue_pbch_vars->llr; //demod_pbch_e = nr_ue_pbch_vars->demod_pbch_e; pbch_a = nr_ue_pbch_vars->pbch_a; - #ifdef DEBUG_PBCH //pbch_e_rx = &nr_ue_pbch_vars->llr[0]; - short *p = (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][20*12]); + for (int cnt = 0; cnt < 864 ; cnt++) printf("pbch rx llr %d\n",*(pbch_e_rx+cnt)); #endif - - //un-scrambling M = NR_POLAR_PBCH_E; - nushift = (Lmax==4)? ssb_index&3 : ssb_index&7; + nushift = (Lmax==4)? i_ssb&3 : i_ssb&7; uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041; nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_E,0,0); - - - //polar decoding de-rate matching + const t_nrPolar_params *currentPtr = nr_polar_params( NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL); + decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&nr_ue_pbch_vars->pbch_a_prime,currentPtr); - nr_polar_init(&nr_ue_pbch_vars->nrPolar_params, - NR_POLAR_PBCH_MESSAGE_TYPE, - NR_POLAR_PBCH_PAYLOAD_BITS, - NR_POLAR_PBCH_AGGREGATION_LEVEL); - - AssertFatal(nr_ue_pbch_vars->nrPolar_params != NULL,"nr_ue_pbch_vars->nrPolar_params is null\n"); - - t_nrPolar_params *currentPtr = nr_polar_params(nr_ue_pbch_vars->nrPolar_params, NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL); - - decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t*)&nr_ue_pbch_vars->pbch_a_prime,currentPtr); - if(decoderState) return(decoderState); - - // printf("polar decoder output 0x%08x\n",nr_ue_pbch_vars->pbch_a_prime); + // printf("polar decoder output 0x%08x\n",nr_ue_pbch_vars->pbch_a_prime); // Decoder reversal uint32_t a_reversed=0; + for (int i=0; ipbch_a_prime>>i)&1)<<(31-i); nr_ue_pbch_vars->pbch_a_prime = a_reversed; - //payload un-scrambling memset(&nr_ue_pbch_vars->pbch_a_interleaved, 0, sizeof(uint32_t) ); M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) ^ (((nr_ue_pbch_vars->pbch_a_prime>>6)&1)<<1); nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_PAYLOAD_BITS,1,unscrambling_mask); //printf("nushift %d sfn 3rd %d 2nd %d", nushift,((nr_ue_pbch_vars->pbch_a_prime>>6)&1), ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) ); - //payload deinterleaving //uint32_t in=0; uint32_t out=0; + for (int i=0; i<32; i++) { out |= ((nr_ue_pbch_vars->pbch_a_interleaved>>i)&1)<<(pbch_deinterleaving_pattern[i]); #ifdef DEBUG_PBCH @@ -696,36 +561,47 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, #endif } - uint32_t payload = 0; - uint8_t xtra_byte = 0; - xtra_byte = (out>>24)&0xff; + uint32_t payload = 0; + uint8_t xtra_byte = 0; + xtra_byte = (out>>24)&0xff; for (int i=0; i>i)&1)<<(NR_POLAR_PBCH_PAYLOAD_BITS-i-1); + payload |= ((out>>i)&1)<<(NR_POLAR_PBCH_PAYLOAD_BITS-i-1); - for (int i=0; i<3; i++) - decoded_output[i] = (uint8_t)((payload>>((3-i)<<3))&0xff); + 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 + + 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)); + } + + 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); - for (i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++){ - // printf("unscrambling pbch_a[%d] = %x \n", i,pbch_a[i]); - printf("[PBCH] decoder payload[%d] = %x\n",i,decoded_output[i]); + printf("xtra_byte %x payload %x\n", 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]); + printf("[PBCH] decoder payload[%d] = %x\n",i,decoded_output[i]); } #endif - ue->dl_indication.rx_ind = &ue->rx_ind; // hang on rx_ind instance - //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 = ssb_index; // 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; + ue->dl_indication.rx_ind = &ue->rx_ind; // hang on rx_ind instance + //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; - if (ue->if_inst && ue->if_inst->dl_indication) - ue->if_inst->dl_indication(&ue->dl_indication); + if (ue->if_inst && ue->if_inst->dl_indication) + ue->if_inst->dl_indication(&ue->dl_indication); - return 0; + return 0; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 9c7146ca03..621318d2bc 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -577,7 +577,7 @@ int32_t generate_nr_prach( PHY_VARS_NR_UE *ue, uint8_t eNB_id, uint8_t subframe, uint8_t preamble_index = ue->prach_resources[eNB_id]->ra_PreambleIndex; //uint8_t tdd_mapindex = ue->prach_resources[eNB_id]->ra_TDD_map_index; int16_t *prachF = ue->prach_vars[eNB_id]->prachF; - static int16_t prach_tmp[45600*2] __attribute__((aligned(32))); + static int16_t prach_tmp[45600*4] __attribute__((aligned(32))); int16_t *prach = prach_tmp; int16_t *prach2; int16_t amp = ue->prach_vars[eNB_id]->amp; 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 3c272b9c17..e1727c4847 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -61,10 +61,10 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch); NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag); -void free_ue_ulsch(NR_UE_ULSCH_t *ulsch); +void free_nr_ue_ulsch(NR_UE_ULSCH_t *ulsch); -NR_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag); +NR_UE_ULSCH_t *new_nr_ue_ulsch(unsigned char N_RB_UL, int number_of_harq_pids, uint8_t abstraction_flag); void fill_UE_dlsch_MCH(PHY_VARS_NR_UE *ue,int mcs,int ndi,int rvidx,int eNB_id); @@ -1006,6 +1006,25 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint8_t is_crnti, uint8_t llr8_flag); +int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, + NR_DL_FRAME_PARMS* frame_parms, + uint8_t 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 +*/ + +void nr_pusch_codeword_scrambling(uint8_t *in, + uint16_t size, + uint32_t Nid, + uint32_t n_RNTI, + uint32_t* out); + + uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, int eNB_id, @@ -1118,13 +1137,18 @@ int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uin \returns number of tx antennas or -1 if error */ int nr_rx_pbch( PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, + int subframe_rx, NR_UE_PBCH *nr_ue_pbch_vars, NR_DL_FRAME_PARMS *frame_parms, uint8_t eNB_id, + uint8_t i_ssb, MIMO_mode_t mimo_mode, uint32_t high_speed_flag); +int nr_pbch_detection(PHY_VARS_NR_UE *ue, + int pbch_initial_symbol, + runmode_t mode); + uint16_t rx_pbch_emul(PHY_VARS_NR_UE *phy_vars_ue, uint8_t eNB_id, uint8_t pbch_phase); @@ -1675,7 +1699,7 @@ int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue, uint8_t eNB_id, int frame, uint8_t nr_tti_rx, - uint32_t dci_pdu[4], + uint64_t dci_pdu[2], uint16_t rnti, uint8_t dci_length, NR_DCI_format_t dci_format, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index b41b23dd32..885039c592 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -102,6 +102,8 @@ typedef struct { uint16_t first_rb; /// Current Number of RBs uint16_t nb_rb; + /// number of layers + uint8_t Nl; /// Last TPC command uint8_t TPC; /// Transport block size @@ -110,20 +112,24 @@ typedef struct { uint32_t B; /// Length of ACK information (bits) uint8_t O_ACK; - /// Pointer to the payload - uint8_t *b; - /// Pointers to transport block segments - uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; /// Index of current HARQ round for this ULSCH uint8_t round; /// MCS format of this ULSCH uint8_t mcs; /// Redundancy-version of the current sub-frame uint8_t rvidx; + /// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8) + unsigned char *a; + /// Pointer to the payload + CRC + uint8_t *b; + /// Pointers to transport block segments + uint8_t *c[MAX_NUM_NR_ULSCH_SEGMENTS]; /// LDPC-code outputs - uint8_t d[MAX_NUM_ULSCH_SEGMENTS][3*8448]; - /// Interleaver outputs - uint8_t w[MAX_NUM_ULSCH_SEGMENTS][3*8448]; + uint8_t *d[MAX_NUM_NR_ULSCH_SEGMENTS]; + /// LDPC-code outputs (TS 36.212 V15.4.0, Sec 5.3.2 p. 17) + uint8_t e[MAX_NUM_NR_CHANNEL_BITS] __attribute__((aligned(32))); + /// Rate matching (Interleaving) outputs (TS 36.212 V15.4.0, Sec 5.4.2.2 p. 30) + uint8_t f[MAX_NUM_NR_CHANNEL_BITS] __attribute__((aligned(32))); /// Number of code segments uint32_t C; /// Number of bits in code segments @@ -158,6 +164,8 @@ typedef struct { typedef struct { /// Current Number of Symbols uint8_t Nsymb_pusch; + /// number of DMRS resource elements + uint8_t nb_re_dmrs; /// SRS active flag uint8_t srs_active; //#if defined(UPGRADE_RAT_NR) @@ -168,6 +176,7 @@ typedef struct { // UL number of harq processes uint8_t number_harq_processes_for_pusch; #endif + /* /// Pointer to CQI data (+1 for 8 bits crc) uint8_t o[1+MAX_CQI_BYTES]; /// Length of CQI data (bits) @@ -180,22 +189,25 @@ typedef struct { uint8_t O_RI; /// Pointer to ACK uint8_t o_ACK[4]; + */ /// Minimum number of CQI bits for PUSCH (36-212 r8.6, Sec 5.2.4.1 p. 37) uint8_t O_CQI_MIN; /// ACK/NAK Bundling flag uint8_t bundling; - /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - uint8_t e[MAX_NUM_CHANNEL_BITS]; + /// Concatenated "g"-sequences (for definition see 36-212 V15.4.0 2018-12, p.31) + uint8_t g[MAX_NUM_NR_CHANNEL_BITS]; /// Interleaved "h"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - uint8_t h[MAX_NUM_CHANNEL_BITS]; + uint8_t h[MAX_NUM_NR_CHANNEL_BITS]; /// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14) - uint8_t b_tilde[MAX_NUM_CHANNEL_BITS]; + 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_RE]; + 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_RE]; + int32_t z[MAX_NUM_NR_RE]; + /* /// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27) uint8_t q[MAX_CQI_PAYLOAD]; + /// coded and interleaved CQI bits uint8_t o_w[(MAX_CQI_BITS+8)*3]; /// coded CQI bits @@ -204,6 +216,7 @@ typedef struct { uint8_t q_ACK[MAX_ACK_PAYLOAD]; /// coded RI bits uint8_t q_RI[MAX_RI_PAYLOAD]; + */ /// beta_offset_cqi times 8 uint16_t beta_offset_cqi_times8; /// beta_offset_ri times 8 @@ -229,9 +242,9 @@ typedef struct { /// num active cba group uint8_t num_active_cba_groups; /// num dci found for cba - uint8_t num_cba_dci[10]; + //uint8_t num_cba_dci[10]; /// allocated CBA RNTI - uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP]; + //uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP]; /// UL max-harq-retransmission uint8_t Mlimit; } NR_UE_ULSCH_t; @@ -394,7 +407,7 @@ typedef struct { /// search space dci_space_t search_space; /// DCI pdu - uint32_t dci_pdu[4]; + uint64_t dci_pdu[2]; //#if defined(UPGRADE_RAT_NR) #if 1 /// harq information diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c new file mode 100644 index 0000000000..70a34f2c66 --- /dev/null +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -0,0 +1,453 @@ +/* + * 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_coding.c +* \brief Top-level routines for coding the ULSCH transport channel as described in 38.212 V15.4 2018-12 +* \author Khalid Ahmed +* \date 2019 +* \version 0.1 +* \company Fraunhofer IIS +* \email: khalid.ahmed@iis.fraunhofer.de +* \note +* \warning +*/ + +#include "PHY/defs_UE.h" +#include "PHY/phy_extern_ue.h" +#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" +#include "PHY/CODING/coding_defs.h" +#include "PHY/CODING/coding_extern.h" +#include "PHY/CODING/lte_interleaver_inline.h" +#include "PHY/CODING/nrLDPC_encoder/defs.h" +#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + + + +void free_nr_ue_ulsch(NR_UE_ULSCH_t *ulsch) +{ + int i; + int r; + + if (ulsch) { +#ifdef DEBUG_ULSCH_FREE + printf("Freeing ulsch %p\n",ulsch); +#endif + + for (i=0; iharq_processes[i]) { + + if (ulsch->harq_processes[i]->a) { + free16(ulsch->harq_processes[i]->a,MAX_NR_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->a = NULL; + } + if (ulsch->harq_processes[i]->b) { + free16(ulsch->harq_processes[i]->b,MAX_NR_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->b = NULL; + } + for (r=0; rharq_processes[i]->c[r]) { + free16(ulsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); + ulsch->harq_processes[i]->c[r] = NULL; + } + + if (ulsch->harq_processes[i]->d[r]) { + free16(ulsch->harq_processes[i]->d[r],68*384); + ulsch->harq_processes[i]->d[r] = NULL; + } + + } + + free16(ulsch->harq_processes[i],sizeof(NR_UL_UE_HARQ_t)); + ulsch->harq_processes[i] = NULL; + } + } + free16(ulsch,sizeof(NR_UE_ULSCH_t)); + ulsch = NULL; + } + +} + + + +NR_UE_ULSCH_t *new_nr_ue_ulsch(unsigned char N_RB_UL, int number_of_harq_pids, uint8_t abstraction_flag) +{ + + NR_UE_ULSCH_t *ulsch; + unsigned char exit_flag = 0,i,j,r; + unsigned char bw_scaling =1; + + switch (N_RB_UL) { + + case 106: + bw_scaling =2; + break; + + default: + bw_scaling =1; + break; + } + + ulsch = (NR_UE_ULSCH_t *)malloc16(sizeof(NR_UE_ULSCH_t)); + + if (ulsch) { + memset(ulsch,0,sizeof(NR_UE_ULSCH_t)); + + ulsch->number_harq_processes_for_pusch = NR_MAX_ULSCH_HARQ_PROCESSES; + ulsch->Mlimit = 4; // maximum harq retransmissions + + //for (i=0; i<10; i++) + //ulsch->harq_ids[i] = 0; + + for (i=0; iharq_processes[i] = (NR_UL_UE_HARQ_t *)malloc16(sizeof(NR_UL_UE_HARQ_t)); + + // printf("ulsch->harq_processes[%d] %p\n",i,ulsch->harq_processes[i]); + if (ulsch->harq_processes[i]) { + memset(ulsch->harq_processes[i], 0, sizeof(NR_UL_UE_HARQ_t)); + ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->a = (unsigned char*)malloc16(MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling); + + if (ulsch->harq_processes[i]->a) { + bzero(ulsch->harq_processes[i]->a,MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling); + } else { + printf("Can't allocate PDU\n"); + exit_flag=1; + } + + if (ulsch->harq_processes[i]->b) + bzero(ulsch->harq_processes[i]->b,MAX_NR_ULSCH_PAYLOAD_BYTES/bw_scaling); + else { + LOG_E(PHY,"Can't get b\n"); + exit_flag=1; + } + + if (abstraction_flag==0) { + for (r=0; rharq_processes[i]->c[r] = (uint8_t*)malloc16(8448); + ulsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output + + if (ulsch->harq_processes[i]->c[r]) { + bzero(ulsch->harq_processes[i]->c[r],8448); + } else { + printf("Can't get c\n"); + exit_flag=2; + } + if (ulsch->harq_processes[i]->d[r]) { + bzero(ulsch->harq_processes[i]->d[r],(68*384)); + } else { + printf("Can't get d\n"); + exit_flag=2; + } + } + } + + ulsch->harq_processes[i]->subframe_scheduling_flag = 0; + ulsch->harq_processes[i]->first_tx = 1; + } else { + LOG_E(PHY,"Can't get harq_p %d\n",i); + exit_flag=3; + } + } + + if (exit_flag==0) { + for (i=0; iharq_processes[i]->round=0; + } + + return(ulsch); + } + } + + LOG_E(PHY,"new_ue_ulsch exit flag, size of %d , %zu\n",exit_flag, sizeof(LTE_UE_ULSCH_t)); + free_nr_ue_ulsch(ulsch); + return(NULL); + + +} + + + +int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, + NR_DL_FRAME_PARMS* frame_parms, + uint8_t harq_pid) +{ + +/////////////////////////parameters and variables declaration///////////////////////// +/////////// + + unsigned int G,crc; + NR_UL_UE_HARQ_t *harq_process; + uint16_t nb_rb ; + uint8_t nb_symb_sch ; + uint32_t A, Z, F; + uint32_t *pz; + uint8_t mod_order; + uint16_t Kr,r,r_offset,Kr_bytes; + uint8_t *d_tmp[MAX_NUM_DLSCH_SEGMENTS]; + uint8_t BG; + uint32_t E; + uint8_t Ilbrm; + uint32_t Tbslbrm; + uint8_t nb_re_dmrs; + uint16_t length_dmrs; + int i; + float Coderate; + +/////////// +/////////////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////parameters and variables initialization///////////////////////// +/////////// + + crc = 1; + harq_process = ulsch->harq_processes[harq_pid]; + nb_rb = harq_process->nb_rb; + nb_symb_sch = harq_process->nb_symbols; + A = harq_process->TBS; + pz = &Z; + mod_order = nr_get_Qm(harq_process->mcs,1); + Kr=0; + r_offset=0; + BG = 1; + F=0; + Ilbrm = 0; + Tbslbrm = 950984; //max tbs + nb_re_dmrs = ulsch->nb_re_dmrs; + length_dmrs = 1; + Coderate = 0.0; + +/////////// +///////////////////////////////////////////////////////////////////////////////////////// + + /* + uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; //unsigned char + for(j=0;jNl); + 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); + + // if (harq_process->Ndi == 1) { // this is a new packet + if (harq_process->round == 0) { // this is a new packet +#ifdef DEBUG_DLSCH_CODING + printf("encoding thinks this is a new packet \n"); +#endif + +///////////////////////// a---->| add CRC |---->b ///////////////////////// +/////////// + /* + int i; + printf("ulsch (tx): \n"); + for (i=0;i<(A>>3);i++) + printf("%02x.",a[i]); + printf("\n"); + */ + // Add 24-bit crc (polynomial A) to payload + crc = crc24a(harq_process->a,A)>>8; + harq_process->a[A>>3] = ((uint8_t*)&crc)[2]; + harq_process->a[1+(A>>3)] = ((uint8_t*)&crc)[1]; + harq_process->a[2+(A>>3)] = ((uint8_t*)&crc)[0]; + //printf("CRC %x (A %d)\n",crc,A); + //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); + + harq_process->B = A+24; + + memcpy(harq_process->b,harq_process->a,(A/8)+4); + +/////////// +/////////////////////////////////////////////////////////////////////////// + +///////////////////////// b---->| block segmentation |---->c ///////////////////////// +/////////// + + nr_segmentation(harq_process->b, + harq_process->c, + harq_process->B, + &harq_process->C, + &harq_process->K, + pz, + &harq_process->F); + + F = harq_process->F; + Coderate = (float) A /(float) G; + + if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ + BG = 2; + } + else{ + BG = 1; + } + + Kr = harq_process->K; + Kr_bytes = Kr>>3; + + +/////////// +///////////////////////////////////////////////////////////////////////////////////// + + +///////////////////////// c---->| LDCP coding |---->d ///////////////////////// +/////////// + + //printf("segment Z %d k %d Kr %d BG %d\n", *pz,harq_process->K,Kr,BG); + + //start_meas(te_stats); + for (r=0; rC; 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); + printf("start ldpc encoder segment %d/%d\n",r,harq_process->C); + printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); + for (int cnt =0 ; cnt < 22*(*pz)/8; cnt ++){ + printf("%d ", harq_process->c[r][cnt]); + } + printf("\n"); + +#endif + //ldpc_encoder_orig((unsigned char*)harq_process->c[r],harq_process->d[r],Kr,BG,0); + //ldpc_encoder_optim((unsigned char*)harq_process->c[r],(unsigned char*)&harq_process->d[r][0],Kr,BG,NULL,NULL,NULL,NULL); + } + + //for (int i=0;i<68*384;i++) + // printf("channel_input[%d]=%d\n",i,channel_input[i]); + + + + /*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], harq_process->d[0][4]); + for (int cnt =0 ; cnt < 66*(*pz); cnt ++){ + printf("%d \n", harq_process->d[0][cnt]); + } + 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); + //printf("end ldpc encoder -- output\n"); + //write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4); +#ifdef DEBUG_DLSCH_CODING + write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4); + write_output("ulsch_enc_output0.m","enc0",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,4); +#endif + +/////////// +/////////////////////////////////////////////////////////////////////////////// + + } + + for (r=0; rC; r++) { // looping over C segments + + if (harq_process->F>0) { + for (int k=(Kr-F-2*(*pz)); kd[r][k] = NR_NULL; + //if (k<(Kr-F+8)) + //printf("r %d filler bits [%d] = %d \n", r,k, harq_process->d[r][k]); + } + } + +#ifdef DEBUG_DLSCH_CODING + printf("Rate Matching, Code segment %d (coded bits (G) %d,unpunctured/repeated bits per code segment %d,mod_order %d, nb_rb %d)...\n", + r, + G, + Kr*3, + mod_order,nb_rb); +#endif + + //start_meas(rm_stats); +#ifdef DEBUG_DLSCH_CODING + printf("rvidx in encoding = %d\n", harq_process->rvidx); +#endif + +///////////////////////// d---->| Rate matching bit selection |---->e ///////////////////////// +/////////// + + E = nr_get_E(G, harq_process->C, mod_order, harq_process->Nl, r); + + nr_rate_matching_ldpc(Ilbrm, + Tbslbrm, + BG, + *pz, + harq_process->d[r], + harq_process->e+r_offset, + harq_process->C, + harq_process->rvidx, + E); + + + +#ifdef DEBUG_DLSCH_CODING + for (int i =0; i<16; i++) + printf("output ratematching e[%d]= %d r_offset %d\n", i,harq_process->e[i+r_offset], r_offset); +#endif + +/////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + + +///////////////////////// e---->| Rate matching bit interleaving |---->f ///////////////////////// +/////////// + + //stop_meas(rm_stats); + + //start_meas(i_stats); + nr_interleaving_ldpc(E, + mod_order, + harq_process->e+r_offset, + harq_process->f+r_offset); + //stop_meas(i_stats); + + +#ifdef DEBUG_DLSCH_CODING + for (int i =0; i<16; i++) + printf("output interleaving f[%d]= %d r_offset %d\n", i,harq_process->f[i+r_offset], r_offset); + + if (r==harq_process->C-1) + write_output("enc_output.m","enc",harq_process->f,G,1,4); +#endif + + r_offset += E; + +/////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + + } + + memcpy(ulsch->g,harq_process->f,G>>3); // g is the concatenated code block + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); + + return(0); +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 01481d3612..40945bebef 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "PHY/defs_nr_UE.h" @@ -662,6 +663,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int synchro_position; int **rxdata = NULL; + int fo_flag = PHY_vars_UE->UE_fo_compensation; // flag to enable freq offset estimation and compensation #ifdef DBG_PSS_NR @@ -705,7 +707,10 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) synchro_position = pss_search_time_nr(rxdata, frame_parms, - (int *)&PHY_vars_UE->common_vars.eNb_id); + fo_flag, + (int *)&PHY_vars_UE->common_vars.eNb_id, + (int *)&PHY_vars_UE->common_vars.freq_offset); + #if TEST_SYNCHRO_TIMING_PSS @@ -751,6 +756,15 @@ static inline int64_t abs64(int64_t x) return (((int64_t)((int32_t*)&x)[0])*((int64_t)((int32_t*)&x)[0]) + ((int64_t)((int32_t*)&x)[1])*((int64_t)((int32_t*)&x)[1])); } +static inline double angle64(int64_t x) +{ + + double re=((int32_t*)&x)[0]; + double im=((int32_t*)&x)[1]; + return (atan2(im,re)); +} + + /******************************************************************* * * NAME : pss_search_time_nr @@ -805,12 +819,15 @@ static inline int64_t abs64(int64_t x) int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id) + int fo_flag, + int *eNB_id, + int *f_off) { unsigned int n, ar, peak_position, pss_source; int64_t peak_value; int64_t result; int64_t avg[NUMBER_PSS_SEQUENCE]; + double ffo_est=0; unsigned int length = (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); /* 1 frame for now, it should be 2 TODO_NR */ @@ -831,7 +848,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain maxval = max(maxval,-primary_synchro_time_nr[1][i]); maxval = max(maxval,primary_synchro_time_nr[2][i]); maxval = max(maxval,-primary_synchro_time_nr[2][i]); - } int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2); @@ -859,7 +875,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain frame_parms->ofdm_symbol_size, shift); pss_corr_ue[pss_index][n] += abs64(result); - //((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */ //((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */ //((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */ @@ -867,7 +882,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain } } - + /* calculate the absolute value of sync_corr[n] */ avg[pss_index]+=pss_corr_ue[pss_index][n]; if (pss_corr_ue[pss_index][n] > peak_value) { @@ -882,11 +897,46 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain } } + if (fo_flag){ + + // fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS + // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. + + int64_t result1,result2; + // Computing cross-correlation at peak on half the symbol size for first half of data + result1 = dot_product64((short*)primary_synchro_time_nr[pss_source], + (short*) &(rxdata[0][peak_position]), + frame_parms->ofdm_symbol_size>>1, + shift); + // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size + // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift + result2 = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size), + (short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size), + frame_parms->ofdm_symbol_size>>1, + shift); + + int64_t re1,re2,im1,im2; + re1=((int*) &result1)[0]; + re2=((int*) &result2)[0]; + im1=((int*) &result1)[1]; + im2=((int*) &result2)[1]; + + // estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi + ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI; + +#ifdef DBG_PSS_NR + printf("ffo %lf\n",ffo_est); +#endif + } + + // computing absolute value of frequency offset + *f_off = ffo_est*frame_parms->subcarrier_spacing; + for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) avg[pss_index]/=(length/4); *eNB_id = pss_source; - LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source])); + LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est); if (peak_value < 5*avg[pss_source]) return(-1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index 05ab023b00..2327a5036b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -25,7 +25,7 @@ * \date 2018 * \version 0.1 * \company Eurecom -* \email: +* \email: * \note * \warning */ @@ -33,7 +33,7 @@ #include "PHY/impl_defs_nr.h" #include "PHY/defs_nr_common.h" #include "PHY/defs_nr_UE.h" -//#include "PHY/extern.h" +//#include "PHY/extern.h" //#include "LAYER2/MAC/extern.h" #include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -49,25 +49,25 @@ //#define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) void nr_group_sequence_hopping (//pucch_GroupHopping_t ue->pucch_config_common_nr.puch_GroupHopping, - //uint8_t PUCCH_GroupHopping, - PHY_VARS_NR_UE *ue, - //uint32_t n_id, - uint8_t n_hop, - int nr_tti_tx, - uint8_t *u, - uint8_t *v) { -/* - * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping - * The following variables are set by higher layers: - * - PUCCH_GroupHopping: - * - n_id: higher-layer parameter hoppingId - * - n_hop: frequency hopping index - * if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping - * n_hop=0 - * if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping - * n_hop=0 for the first hop - * n_hop=1 for the second hop - */ + //uint8_t PUCCH_GroupHopping, + PHY_VARS_NR_UE *ue, + //uint32_t n_id, + uint8_t n_hop, + int nr_tti_tx, + uint8_t *u, + uint8_t *v) { + /* + * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping + * The following variables are set by higher layers: + * - PUCCH_GroupHopping: + * - n_id: higher-layer parameter hoppingId + * - n_hop: frequency hopping index + * if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping + * n_hop=0 + * if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping + * n_hop=0 for the first hop + * n_hop=1 for the second hop + */ // depending on the value of the PUCCH_GroupHopping, we will obtain different values for u,v pucch_GroupHopping_t PUCCH_GroupHopping = ue->pucch_config_common_nr->pucch_GroupHopping; // from higher layers FIXME!!! // n_id defined as per TS 38.211 subclause 6.3.2.2.1 (is given by the higher-layer parameter hoppingId) @@ -75,43 +75,66 @@ void nr_group_sequence_hopping (//pucch_GroupHopping_t ue->pucch_config_common_n // Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled // Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) BIT STRING (SIZE (10)) uint16_t n_id = ue->pucch_config_common_nr->hoppingId; // from higher layers FIXME!!! - - - #ifdef DEBUG_NR_PUCCH_TX - // initialization to be removed - PUCCH_GroupHopping=neither; - n_id=10; - printf("\t\t [nr_group_sequence_hopping] initialization PUCCH_GroupHopping=%d, n_id=%d -> variable initializations TO BE REMOVED\n",PUCCH_GroupHopping,n_id); - #endif - - +#ifdef DEBUG_NR_PUCCH_TX + // initialization to be removed + PUCCH_GroupHopping=neither; + n_id=10; + printf("\t\t [nr_group_sequence_hopping] initialization PUCCH_GroupHopping=%d, n_id=%d -> variable initializations TO BE REMOVED\n",PUCCH_GroupHopping,n_id); +#endif uint8_t f_ss=0,f_gh=0; *u=0; *v=0; uint32_t c_init = (1<<5)*floor(n_id/30)+(n_id%30); // we initialize c_init to calculate u,v uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1 - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_group_sequence_hopping] calculating u,v -> "); - #endif + int l = 32, minShift = ((2*nr_tti_tx+n_hop)<<3); + int tmpShift =0; +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_group_sequence_hopping] calculating u,v -> "); +#endif - if (PUCCH_GroupHopping == neither){ // PUCCH_GroupHopping 'neither' + if (PUCCH_GroupHopping == neither) { // PUCCH_GroupHopping 'neither' f_ss = n_id%30; } - if (PUCCH_GroupHopping == enable){ // PUCCH_GroupHopping 'enabled' - for (int m=0; m<8; m++){ - f_gh = f_gh + ((1<>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!! + + if (PUCCH_GroupHopping == enable) { // PUCCH_GroupHopping 'enabled' + for (int m=0; m<8; m++) { + while(minShift >= l) { + s = lte_gold_generic(&x1, &c_init, 0); + l = l+32; + } + + tmpShift = (minShift&((1<<5)-1)); //minShift%32; + f_gh = f_gh + ((1<>tmpShift)&1))); + minShift ++; } + f_gh = f_gh%30; f_ss = n_id%30; + /* for (int m=0; m<8; m++){ + f_gh = f_gh + ((1<>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!! + } + f_gh = f_gh%30; + f_ss = n_id%30;*/ } - if (PUCCH_GroupHopping == disable){ // PUCCH_GroupHopping 'disabled' + + if (PUCCH_GroupHopping == disable) { // PUCCH_GroupHopping 'disabled' f_ss = n_id%30; - *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!! + l = 32, minShift = (2*nr_tti_tx+n_hop); + + while(minShift >= l) { + s = lte_gold_generic(&x1, &c_init, 0); + l = l+32; + } + + tmpShift = (minShift&((1<<5)-1)); //minShift%32; + *v = (uint8_t)((s>>tmpShift)&1); + // *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!! } + *u = (f_gh+f_ss)%30; - #ifdef DEBUG_NR_PUCCH_TX - printf("%d,%d\n",*u,*v); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("%d,%d\n",*u,*v); +#endif } double nr_cyclic_shift_hopping(PHY_VARS_NR_UE *ue, @@ -120,37 +143,47 @@ double nr_cyclic_shift_hopping(PHY_VARS_NR_UE *ue, uint8_t lnormal, uint8_t lprime, int nr_tti_tx) { -/* - * Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping - * - n_id: higher-layer parameter hoppingId - * - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config - * - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2 - * - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission - * - lprime: 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] - */ + /* + * Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping + * - n_id: higher-layer parameter hoppingId + * - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config + * - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2 + * - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission + * - lprime: 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] + */ // alpha_init initialized to 2*PI/12=0.5235987756 double alpha = 0.5235987756; uint32_t c_init = ue->pucch_config_common_nr->hoppingId; // we initialize c_init again to calculate n_cs - - #ifdef DEBUG_NR_PUCCH_TX - // initialization to be removed - c_init=10; - printf("\t\t [nr_cyclic_shift_hopping] initialization c_init=%d -> variable initialization TO BE REMOVED\n",c_init); - #endif - +#ifdef DEBUG_NR_PUCCH_TX + // initialization to be remo.ved + c_init=10; + printf("\t\t [nr_cyclic_shift_hopping] initialization c_init=%d -> variable initialization TO BE REMOVED\n",c_init); +#endif uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1 uint8_t n_cs=0; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%d -> ",c_init); - #endif - for (int m=0; m<8; m++){ + int l = 32, minShift = (14*8*nr_tti_tx )+ 8*(lnormal+lprime); + int tmpShift =0; +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%d -> \n",c_init); +#endif + + for (int m=0; m<8; m++) { + while(minShift >= l) { + s = lte_gold_generic(&x1, &c_init, 0); + l = l+32; + } + + tmpShift = (minShift&((1<<5)-1)); //minShift%32; + minShift ++; + n_cs = n_cs+((1<>tmpShift)&1))); // calculating n_cs (Not sure we have to use nr_tti_tx FIXME!!!) - n_cs = n_cs+((1<>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1))); + // n_cs = n_cs+((1<>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1))); } + alpha = (alpha * (double)((m0+mcs+n_cs)%12)); - #ifdef DEBUG_NR_PUCCH_TX - printf("n_cs=%d -> %lf\n",n_cs,alpha); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("n_cs=%d -> %lf\n",n_cs,alpha); +#endif return(alpha); } void nr_generate_pucch0(PHY_VARS_NR_UE *ue, @@ -164,18 +197,16 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, uint8_t nrofSymbols, uint8_t startingSymbolIndex, uint16_t startingPRB) { - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] start function at slot(nr_tti_tx)=%d\n",nr_tti_tx); - #endif - +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] start function at slot(nr_tti_tx)=%d\n",nr_tti_tx); +#endif /* * Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation * */ - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] sequence generation\n"); - #endif - +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch0] sequence generation\n"); +#endif /* * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 */ @@ -187,13 +218,11 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, //uint8_t lprime; // mcs is provided by TC 38.213 subclauses 9.2.3, 9.2.4, 9.2.5 FIXME! //uint8_t mcs; - /* * 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 */ - /* * Implementing TS 38.211 Subclause 6.3.2.3.1, the sequence x(n) shall be generated according to: * x(l*12+n) = r_u_v_alpha_delta(n) @@ -207,70 +236,78 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, // n_hop = 1 for second hop uint8_t n_hop = 0; //uint8_t PUCCH_Frequency_Hopping; // from higher layers FIXME!! - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n"); + printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n"); #endif - // x_n contains the sequence r_u_v_alpha_delta(n) int16_t x_n_re[24],x_n_im[24]; + // we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2 - for (int l=0; l>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 + - (((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 x_n_im[(12*l)+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 - #ifdef DEBUG_NR_PUCCH_TX - 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 + + (((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 +#ifdef DEBUG_NR_PUCCH_TX + 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 } } + /* * Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources FIXME! */ //int32_t *txptr; uint32_t re_offset=0; + for (int l=0; lN_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++){ + 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); } + ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)(((int32_t)(amp) * x_n_re[(12*l)+n])>>15); ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)(((int32_t)(amp) * x_n_im[(12*l)+n])>>15); //((int16_t *)txptr[0][re_offset])[0] = (int16_t)((int32_t)amp * x_n_re[(12*l)+n])>>15; //((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15; //txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n]; - #ifdef DEBUG_NR_PUCCH_TX - 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 *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + 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 *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif re_offset++; } } @@ -292,41 +329,45 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, uint8_t nr_bit) { #ifdef DEBUG_NR_PUCCH_TX 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); + 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; + if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 if (((payload&1)==0) && (((payload>>1)&1)==0)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==0) && (((payload>>1)&1)==1)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==0)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==1)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } } - #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 +#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 /* * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 */ @@ -346,7 +387,6 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, * 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) */ @@ -363,57 +403,63 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, // 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){ + + if (startingPRB != startingPRB_intraSlotHopping) { intraSlotFrequencyHopping=1; } + #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping); #endif -/* - * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources - */ + /* + * 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 +#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[MAX_SIZE_Z],z_im[MAX_SIZE_Z]; int16_t z_dmrs_re[MAX_SIZE_Z],z_dmrs_im[MAX_SIZE_Z]; for (int l=0; l= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop - #ifdef DEBUG_NR_PUCCH_TX - 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 + +#ifdef DEBUG_NR_PUCCH_TX + 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(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value alpha = nr_cyclic_shift_hopping(ue,m0,mcs,l,lprime,nr_tti_tx); - for (int n=0; n<12; n++){ + + for (int n=0; n<12; n++) { 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 + - (((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 + + (((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 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 + - (((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 + + (((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); // 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) + - (((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_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]); - #endif + + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(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]); +#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) @@ -439,202 +485,222 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, 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_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + 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_TX - 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 (int m=0; m < N_SF_mprime_PUCCH_1; m++){ - for (int n=0; n<12 ; n++){ +#ifdef DEBUG_NR_PUCCH_TX + 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 (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)); + - (((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 + + (((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++){ + + 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)); + - (((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)); - #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]); - #endif + + (((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)); +#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]); +#endif } } } + if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + 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_TX - 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 (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]); + 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 (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_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],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],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)); +#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]); +#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) - } } } + if ((intraSlotFrequencyHopping == 1) && (lN_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++){ + 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 ((int16_t *)&txdataF[0][re_offset])[0] = z_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - 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 +#ifdef DEBUG_NR_PUCCH_TX + 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 ((int16_t *)&txdataF[0][re_offset])[0] = z_dmrs_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_dmrs_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - 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 +#ifdef DEBUG_NR_PUCCH_TX + 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 } + re_offset++; } + if (l%2 == 1) i+=12; } } #if 0 void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, - int32_t **txdataF, - NR_DL_FRAME_PARMS *frame_parms, - PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, - uint64_t payload, - 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) { + int32_t **txdataF, + NR_DL_FRAME_PARMS *frame_parms, + PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, + uint64_t payload, + 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_TX 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); + 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, d_im; + if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2 d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2 if (((payload&1)==0) && (((payload>>1)&1)==0)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==0) && (((payload>>1)&1)==1)) { d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==0)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((payload&1)==1) && (((payload>>1)&1)==1)) { d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } } - #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 +#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 /* * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2 */ @@ -654,7 +720,6 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, * 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) */ @@ -671,11 +736,12 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, // 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){ + + if (startingPRB != startingPRB_intraSlotHopping) { intraSlotFrequencyHopping=1; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); +#endif // n_hop = 1 for second hop; // FIXME // When hopping will be activated we have to implement this function differently as PUCH signal generation depends on n_hop value for u,v calculation @@ -683,30 +749,32 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, // y_n contains the complex value d multiplied by the sequence r_u_v int16_t y_n_re[12],y_n_im[12]; - #ifdef DEBUG_NR_PUCCH_TX - 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 +#ifdef DEBUG_NR_PUCCH_TX + 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(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value alpha = nr_cyclic_shift_hopping(ue,m0,mcs,lnormal,lprime,nr_tti_tx); - for (int n=0; n<12; n++){ + + for (int n=0; n<12; n++) { 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 + - (((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 + + (((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 // 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) + - (((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) + + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n) // DM-RS sequence r_u_v_alpha_delta_re[n] = (int16_t)(((int32_t)amp*r_u_v_alpha_delta_re[n])>>15); r_u_v_alpha_delta_im[n] = (int16_t)(((int32_t)amp*r_u_v_alpha_delta_im[n])>>15); - #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]); - #endif +#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]); +#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) @@ -736,124 +804,144 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, 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_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\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) - for (int m=0; m < N_SF_mprime_PUCCH_1; m++){ - for (int n=0; n<12 ; n++){ + + 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)); + - (((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\t z_pucch[%d] \t= ((%d \t* %d \t-%d \t* %d), (%d \t* %d \t+%d \t*%d)) = (%d,%d)\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 + + (((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\t z_pucch[%d] \t= ((%d \t* %d \t-%d \t* %d), (%d \t* %d \t+%d \t*%d)) = (%d,%d)\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++){ + + 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_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_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_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_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_re[n])>>15)); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t z_dm-rs[%d] = ((),()) =(%d,%d)\n", - (mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+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 + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t z_dm-rs[%d] = ((),()) =(%d,%d)\n", + (mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+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 } } } + if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n", - intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\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) - 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++){ + + 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)); + - (((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)); + + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)); } } - for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++){ - for (int n=0; n<12 ; n++){ + + 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_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_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_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_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_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_re[n])>>15)); } } + 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) } } -/* - * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources - */ + + /* + * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources + */ int32_t *txptr; uint32_t re_offset; int i=0; + for (int l=0; lN_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++){ + + 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 ((int16_t *)&txdataF[0][re_offset])[0] = z_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - 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 +#ifdef DEBUG_NR_PUCCH_TX + 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 ((int16_t *)&txdataF[0][re_offset])[0] = z_dmrs_re[i+n]; ((int16_t *)&txdataF[0][re_offset])[1] = z_dmrs_im[i+n]; - #ifdef DEBUG_NR_PUCCH_TX - 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 +#ifdef DEBUG_NR_PUCCH_TX + 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 } + re_offset++; } + if (l%2 == 1) i+=12; } } @@ -861,7 +949,6 @@ void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue, inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint32_t B,uint8_t *btilde) __attribute__((always_inline)); inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint32_t B,uint8_t *btilde) { - uint32_t x1, x2, s=0; int i; uint8_t c; @@ -869,20 +956,21 @@ inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id, //x2 = (rnti) + ((uint32_t)(1+nr_tti_tx)<<16)*(1+(fp->Nid_cell<<1)); x2 = ((rnti)<<15)+n_id; s = lte_gold_generic(&x1, &x2, 1); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%lx\n",s); - #endif - for (i=0;i>i)&1); btilde[i] = (((B>>i)&1) ^ c); - #ifdef DEBUG_NR_PUCCH_TX - //printf("\t\t\t btilde[%d]=%lx from scrambled bit %d\n",i,btilde[i],((B>>i)&1)); - #endif +#ifdef DEBUG_NR_PUCCH_TX + //printf("\t\t\t btilde[%d]=%lx from scrambled bit %d\n",i,btilde[i],((B>>i)&1)); +#endif } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_pucch2_3_4_scrambling] scrambling M_bit=%d bits\n", M_bit); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_pucch2_3_4_scrambling] scrambling M_bit=%d bits\n", M_bit); +#endif } void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, @@ -899,79 +987,90 @@ void nr_uci_encoding(uint64_t payload, * Implementing TS 38.212 Subclause 6.3.1.2 * */ - // A is the payload size, to be provided in function call uint8_t A = nr_bit; // L is the CRC size uint8_t L; // E is the rate matching output sequence length as given in TS 38.212 subclause 6.3.1.4.1 uint16_t E=0,E_init; + if (fmt == pucch_format2_nr) E = 16*nrofSymbols*nrofPRB; - if (fmt == pucch_format3_nr){ + + if (fmt == pucch_format3_nr) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; + if (nrofSymbols == 4) { E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)*nrofPRB):((E_init*(nrofSymbols-1)*nrofPRB)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 3 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); +#endif } + if (nrofSymbols > 4) { E = E_init*(nrofSymbols-2)*nrofPRB; - #ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 3 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); +#endif } + if (nrofSymbols > 9) { E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)*nrofPRB):((E_init*(nrofSymbols-4)*nrofPRB)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 3 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 3 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); +#endif } } - if (fmt == pucch_format4_nr){ + + if (fmt == pucch_format4_nr) { E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12; + if (nrofSymbols == 4) { E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)/n_SF_PUCCH_s):((E_init*(nrofSymbols-1)/n_SF_PUCCH_s)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 4 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E); +#endif } + if (nrofSymbols > 4) { E = E_init*(nrofSymbols-2)/n_SF_PUCCH_s; - #ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 4 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E); +#endif } + if (nrofSymbols > 9) { E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)/n_SF_PUCCH_s):((E_init*(nrofSymbols-4)/n_SF_PUCCH_s)); - #ifdef DEBUG_NR_PUCCH_TX - printf("format 4 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("format 4 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E); +#endif } } + *M_bit = E; int I_seg; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t\t [nr_uci_encoding] start function with fmt=%d, encoding A=%d bits into M_bit=%d (where nrofSymbols=%d,nrofPRB=%d)\n",fmt,A,*M_bit,nrofSymbols,nrofPRB); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t\t [nr_uci_encoding] start function with fmt=%d, encoding A=%d bits into M_bit=%d (where nrofSymbols=%d,nrofPRB=%d)\n",fmt,A,*M_bit,nrofSymbols,nrofPRB); +#endif - if (A<=11){ + if (A<=11) { // procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2) // CRC bits are not attached, and coding small block lengths (subclause 5.3.3) - } else if (A>=12){ + } else if (A>=12) { // procedure in subclause 6.3.1.2.1 (UCI encoded by Polar code -> subclause 6.3.1.3.1) - if ((A>=360 && E>=1088)||(A>=1013)){ + if ((A>=360 && E>=1088)||(A>=1013)) { I_seg = 1; } else { I_seg = 0; } - if (A>=20){ + + if (A>=20) { // parity bits (subclause 5.2.1) computed by setting L=11 and using generator polynomial gCRC11(D) (subclause 5.1) L=11; - } else if (A<=19){ + } else if (A<=19) { // parity bits (subclause 5.2.1) computed by setting L=6 and using generator polynomial gCRC6(D) (subclause 5.1) L=6; } + // code block segmentation and CRC attachment is performed according to subclause 5.2.1 // polar coding subclause 5.3.1 } @@ -990,15 +1089,14 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint8_t nrofPRB, uint16_t startingPRB, uint8_t nr_bit) { - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n",nr_tti_tx, payload, nr_bit); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n",nr_tti_tx, payload, nr_bit); +#endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b; // M_bit is the number of bits of block b (payload after encoding) uint16_t M_bit; nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,&b,&M_bit); - /* * Implementing TS 38.211 * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2) @@ -1011,53 +1109,52 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, * n_id = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured * n_id = N_ID_cell if higher layer parameter not configured */ - uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI uint16_t rnti=crnti, n_id=0; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch2] rnti = %d ,\n",rnti); #endif - /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde); - /* * Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2 * btilde shall be modulated as described in subclause 5.1 using QPSK * resulting in a block of complex-valued modulation symbols d(0),...,d(m_symbol) where m_symbol=M_bit/2 */ - -//#define ONE_OVER_SQRT2_S 23171 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) - + //#define ONE_OVER_SQRT2_S 23171 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2) // complex-valued symbol d(0) int16_t *d_re = malloc(sizeof(int16_t)*M_bit); int16_t *d_im = malloc(sizeof(int16_t)*M_bit); uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1; - for (int i=0; i < m_symbol; i++){ // QPSK modulation subclause 5.1.3 + + for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3 if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] modulation of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]); - #endif - } +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] modulation of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]); +#endif + } /* * Implementing TS 38.211 Subclause 6.3.2.5.3 Mapping to physical resources @@ -1067,58 +1164,76 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint32_t x1, x2, s=0; int i=0; int m=0; + for (int l=0; lN_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*(rb+startingPRB)) + frame_parms->first_carrier_offset; } + if (((rb+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*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))); } + if (((rb+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*(rb+startingPRB)) + frame_parms->first_carrier_offset; } + if (((rb+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*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6; } + if (((rb+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*(rb+startingPRB)) + frame_parms->first_carrier_offset; } + //txptr = &txdataF[0][re_offset]; int k=0; int kk=0; - for (int n=0; n<12; n++){ + + for (int n=0; n<12; n++) { if ((n==6) && ((rb+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 (n%3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3 ((int16_t *)&txdataF[0][re_offset])[0] = d_re[i+k]; ((int16_t *)&txdataF[0][re_offset])[1] = d_im[i+k]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] (n=%d,i=%d) 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", - n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+k,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] (n=%d,i=%d) 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", + n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+k,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif k++; } + if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2 ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>(2*m))&1)))))>>15); ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>((2*m)+1))&1)))))>>15); m++; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch2] (n=%d,i=%d) 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", - n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+kk,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch2] (n=%d,i=%d) 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", + n,i,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+kk,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif kk++; } + re_offset++; } + i+=8; + + if ((m&((1<<4)-1))==0) { + s = lte_gold_generic(&x1, &x2, 0); + m = 0; + } } } } @@ -1140,10 +1255,9 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, uint8_t nr_bit, uint8_t occ_length_format4, uint8_t occ_index_format4) { - - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n", nr_tti_tx, payload, nr_bit); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] start function at slot(nr_tti_tx)=%d with payload=%d and nr_bit=%d\n", nr_tti_tx, payload, nr_bit); +#endif // b is the block of bits transmitted on the physical channel after payload coding uint64_t b; // M_bit is the number of bits of block b (payload after encoding) @@ -1156,19 +1270,21 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, // 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){ + + if (startingPRB != startingPRB_intraSlotHopping) { intraSlotFrequencyHopping=1; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping); +#endif } + // add_dmrs indicates if we are using or not Additional DM-RS for formats 3 and 4. From higher layers. FIXME!!! uint8_t add_dmrs = 0; + //nrofPRB = 2; // only for test purposes if (fmt == pucch_format4_nr) nrofPRB = 1; nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,&b,&M_bit); - /* * Implementing TS 38.211 * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) @@ -1181,19 +1297,16 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, * n_id = {0,1,...,1023} equals the higher-layer parameter Data-scrambling-Identity if configured * n_id = N_ID_cell if higher layer parameter not configured */ - uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI uint16_t rnti=crnti, n_id=0; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] rnti = %d ,\n",rnti); #endif - /* * Implementing TS 38.211 Subclause 6.3.2.6.1 scrambling formats 3 and 4 */ nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde); - /* * Implementing TS 38.211 Subclause 6.3.2.6.2 modulation formats 3 and 4 * @@ -1204,53 +1317,64 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, int16_t *d_re = malloc(sizeof(int16_t)*M_bit); int16_t *d_im = malloc(sizeof(int16_t)*M_bit); uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1; - if (is_pi_over_2_bpsk_enabled == 0){ + + if (is_pi_over_2_bpsk_enabled == 0) { // using QPSK if PUCCH format 3,4 and pi/2-BPSK is not configured, according to subclause 6.3.2.6.2 - for (int i=0; i < m_symbol; i++){ // QPSK modulation subclause 5.1.3 + for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3 if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } + if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - #ifdef DEBUG_NR_PUCCH_TX + +#ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] modulation QPSK of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]); - #endif +#endif } } - if (is_pi_over_2_bpsk_enabled == 1){ + + if (is_pi_over_2_bpsk_enabled == 1) { // using PI/2-BPSK if PUCCH format 3,4 and pi/2-BPSK is configured, according to subclause 6.3.2.6.2 m_symbol = M_bit; - for (int i=0; i>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (((btilde[i]&1)==0) && (i%2 == 1)){ + + if (((btilde[i]&1)==0) && (i%2 == 1)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (((btilde[i]&1)==1) && (i%2 == 0)){ + + if (((btilde[i]&1)==1) && (i%2 == 0)) { d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - if (((btilde[i]&1)==1) && (i%2 == 1)){ + + if (((btilde[i]&1)==1) && (i%2 == 1)) { d_re[i] = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); } - #ifdef DEBUG_NR_PUCCH_TX + +#ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch3_4] modulation PI/2-BPSK of bit btilde(%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[i]&1),m_symbol,i,d_re[i],d_im[i]); - #endif +#endif } } @@ -1269,67 +1393,76 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, // Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1) // k={0,..11} n={0,1,2,3} // parameter PUCCH-F4-preDFT-OCC-index set of {0,1,2,3} -> n - uint16_t table_6_3_2_6_3_1_Wn_Re[2][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1}}; + uint16_t table_6_3_2_6_3_1_Wn_Re[2][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1} + }; // Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1) // k={0,..11} n={0,1} uint16_t table_6_3_2_6_3_1_Wn_Im[2][12] = {{0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0}}; + {0,0,0,0,0,0,0,0,0,0,0,0} + }; // Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2) // k={0,..11} n={0,1,2.3} uint16_t table_6_3_2_6_3_2_Wn_Re[4][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}, - {1, 1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1}, - {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}}; + {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}, + {1, 1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1}, + {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0} + }; // Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2) // k={0,..11} n={0,1,2,3} uint16_t table_6_3_2_6_3_2_Wn_Im[4][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0,-1,-1,-1, 0, 0, 0, 1, 1, 1}, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1}}; + {0, 0, 0,-1,-1,-1, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1} + }; //uint8_t occ_Length = occ_length_format4; // higher layer parameter occ-Length uint8_t occ_Index = occ_index_format4; // higher layer parameter occ-Index -//occ_Index = 1; //only for testing purposes; to be removed FIXME!!! - if (fmt == pucch_format3_nr){ // no block-wise spreading for format 3 + + //occ_Index = 1; //only for testing purposes; to be removed FIXME!!! + if (fmt == pucch_format3_nr) { // no block-wise spreading for format 3 n_SF_PUCCH_s = 1; - for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++){ - for (int k=0; k < (12*nrofPRB); k++){ + + for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++) { + for (int k=0; k < (12*nrofPRB); k++) { y_n_re[l*(12*nrofPRB)+k] = d_re[l*(12*nrofPRB)+k]; y_n_im[l*(12*nrofPRB)+k] = d_im[l*(12*nrofPRB)+k]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] block-wise spreading for format 3 (no block-wise spreading): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", - l,k,l*(12*nrofPRB)+k,d_re[l*(12*nrofPRB)+k],d_im[l*(12*nrofPRB)+k]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] block-wise spreading for format 3 (no block-wise spreading): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", + l,k,l*(12*nrofPRB)+k,d_re[l*(12*nrofPRB)+k],d_im[l*(12*nrofPRB)+k]); +#endif } } } - if (fmt == pucch_format4_nr){ + + if (fmt == pucch_format4_nr) { nrofPRB = 1; - for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++){ - for (int k=0; k < (12*nrofPRB); k++){ - if (n_SF_PUCCH_s == 2){ + + for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) { + for (int k=0; k < (12*nrofPRB); k++) { + if (n_SF_PUCCH_s == 2) { y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k]) - - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); + - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k]) - + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 2) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", - occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); -// printf("\t\t d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); -// printf("\t\t d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); -// printf("\t\t table_6_3_2_6_3_1_Wn_Re[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Re[occ_Index][k]); -// printf("\t\t table_6_3_2_6_3_1_Wn_Im[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Im[occ_Index][k]); - #endif + + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k])); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 2) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", + occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); + // printf("\t\t d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); + // printf("\t\t d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]); + // printf("\t\t table_6_3_2_6_3_1_Wn_Re[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Re[occ_Index][k]); + // printf("\t\t table_6_3_2_6_3_1_Wn_Im[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Im[occ_Index][k]); +#endif } - if (n_SF_PUCCH_s == 4){ + + if (n_SF_PUCCH_s == 4) { y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k]) - - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); + - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k]) - + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 4) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", - occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); - #endif + + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k])); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 4) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d) = \t(d_re=%d, d_im=%d)\n", + occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]); +#endif } } } @@ -1340,37 +1473,40 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, */ int16_t *z_re = malloc(sizeof(int16_t)*4*M_bit); // 4 is the maximum number n_SF_PUCCH_s int16_t *z_im = malloc(sizeof(int16_t)*4*M_bit); - #define M_PI 3.14159265358979323846 // pi +#define M_PI 3.14159265358979323846 // pi + //int16_t inv_sqrt_nrofPRBs = (int16_t)round(32767/sqrt(12*nrofPRB)); - for (int l=0; l>15) -// + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); -// z_im_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) -// - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); + // z_re_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + // + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); + // z_im_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + // - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); z_re[l*(12*nrofPRB)+k] = z_re[l*(12*nrofPRB)+k] - + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) - + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); + + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); z_im[l*(12*nrofPRB)+k] = z_im[l*(12*nrofPRB)+k] - + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) - - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); - #ifdef DEBUG_NR_PUCCH_TX -// printf("\t\t z_re_tmp[%d] = %d\n",m,z_re_tmp[m]); -// printf("\t\t z_im_tmp[%d] = %d\n",m,z_im_tmp[m]); -// printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k,m)=(%d,%d,%d)\tz(%d) = \t(%d, %d)\n", -// l,k,m,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); - #endif + + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15) + - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15); +#ifdef DEBUG_NR_PUCCH_TX + // printf("\t\t z_re_tmp[%d] = %d\n",m,z_re_tmp[m]); + // printf("\t\t z_im_tmp[%d] = %d\n",m,z_im_tmp[m]); + // printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k,m)=(%d,%d,%d)\tz(%d) = \t(%d, %d)\n", + // l,k,m,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); +#endif } - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k)=(%d,%d)\tz(%d) = \t(%d, %d)\n", - l,k,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); - #endif + +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k)=(%d,%d)\tz(%d) = \t(%d, %d)\n", + l,k,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]); +#endif } } @@ -1392,160 +1528,178 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, // m0 is the cyclic shift index calculated depending on the Orthogonal sequence index n, according to table 6.4.1.3.3.1-1 from TS 38.211 subclause 6.4.1.3.3.1 uint8_t m0; uint8_t mcs=0; + if (fmt == pucch_format3_nr) m0 = 0; + if (fmt == pucch_format4_nr) { if (n_SF_PUCCH_s == 2) { m0 = (occ_Index == 0) ? 0 : 6; } + if (n_SF_PUCCH_s == 4) { m0 = (occ_Index == 3) ? 9 : ((occ_Index == 2) ? 3 : ((occ_Index == 1) ? 6 : 0)); } } + double alpha; uint8_t N_ZC = 12*nrofPRB; int16_t *r_u_v_base_re = malloc(sizeof(int16_t)*12*nrofPRB); int16_t *r_u_v_base_im = malloc(sizeof(int16_t)*12*nrofPRB); //int16_t *r_u_v_alpha_delta_re = malloc(sizeof(int16_t)*12*nrofPRB); //int16_t *r_u_v_alpha_delta_im = malloc(sizeof(int16_t)*12*nrofPRB); - // Next we proceed to mapping to physical resources according to TS 38.211, subclause 6.3.2.6.5 dor PUCCH formats 3 and 4 and subclause 6.4.1.3.3.2 for DM-RS //int32_t *txptr; uint32_t re_offset=0; //uint32_t x1, x2, s=0; // intraSlotFrequencyHopping // uint8_t intraSlotFrequencyHopping = 0; - uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] ={ - {(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4 - {1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5 - {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 6 - {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 7 - {0,1,0,0,0,1,0,0,0,0,0,0,0,0}, // PUCCH length = 8 - {0,1,0,0,0,0,1,0,0,0,0,0,0,0}, // PUCCH length = 9 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,0,0,0}, // PUCCH length = 10 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0,0}, // PUCCH length = 11 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0}, // PUCCH length = 12 - {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13 - {0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0} // PUCCH length = 14 + uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] = { + {(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4 + {1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5 + {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 6 + {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 7 + {0,1,0,0,0,1,0,0,0,0,0,0,0,0}, // PUCCH length = 8 + {0,1,0,0,0,0,1,0,0,0,0,0,0,0}, // PUCCH length = 9 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,0,0,0}, // PUCCH length = 10 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0,0}, // PUCCH length = 11 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0}, // PUCCH length = 12 + {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13 + {0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0} // PUCCH length = 14 }; uint16_t k=0; + for (int l=0; l= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop - nr_group_sequence_hopping(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value + nr_group_sequence_hopping(ue,n_hop,nr_tti_tx,&u,&v); // calculating u and v value // Next we proceed to calculate base sequence for DM-RS signal, according to TS 38.211 subclause 6.4.1.33 if (nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies int i = 4; + while (list_of_prime_numbers[i] < (12*nrofPRB)) i++; + N_ZC = list_of_prime_numbers[i+1]; // N_ZC is given by the largest prime number such that N_ZC < (12*nrofPRB) double q_base = (N_ZC*(u+1))/31; int8_t q = (uint8_t)floor(q_base + (1/2)); q = ((uint8_t)floor(2*q_base)%2 == 0 ? q+v : q-v); - for (int n=0; n<(12*nrofPRB); n++){ + + for (int n=0; n<(12*nrofPRB); n++) { r_u_v_base_re[n] = (int16_t)(((int32_t)amp*(int16_t)(32767*cos(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15); r_u_v_base_im[n] = -(int16_t)(((int32_t)amp*(int16_t)(32767*sin(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d >= 3: r_u_v_base[n=%d]=(%d,%d)\n", - nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d >= 3: r_u_v_base[n=%d]=(%d,%d)\n", + nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); +#endif } } + if (nrofPRB == 2) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-4) applies - for (int n=0; n<(12*nrofPRB); n++){ + for (int n=0; n<(12*nrofPRB); n++) { r_u_v_base_re[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_4_Re[u][n])>>15); r_u_v_base_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_4_Im[u][n])>>15); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 2: r_u_v_base[n=%d]=(%d,%d)\n", - nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 2: r_u_v_base[n=%d]=(%d,%d)\n", + nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); +#endif } } + if (nrofPRB == 1) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-2) applies - for (int n=0; n<(12*nrofPRB); n++){ + for (int n=0; n<(12*nrofPRB); n++) { r_u_v_base_re[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_2_Re[u][n])>>15); r_u_v_base_im[n] = (int16_t)(((int32_t)amp*table_5_2_2_2_2_Im[u][n])>>15); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 1: r_u_v_base[n=%d]=(%d,%d)\n", - nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 1: r_u_v_base[n=%d]=(%d,%d)\n", + nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]); +#endif } } - - uint16_t j=0; alpha = nr_cyclic_shift_hopping(ue,m0,mcs,l,startingSymbolIndex,nr_tti_tx); - for (int rb=0; rbN_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*(rb+startingPRB)) + frame_parms->first_carrier_offset; - #ifdef DEBUG_NR_PUCCH_TX - printf("1 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("1 "); +#endif } + if (((rb+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*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))); - #ifdef DEBUG_NR_PUCCH_TX - printf("2 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("2 "); +#endif } + if (((rb+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*(rb+startingPRB)) + frame_parms->first_carrier_offset; - #ifdef DEBUG_NR_PUCCH_TX - printf("3 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("3 "); +#endif } + if (((rb+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*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6; - #ifdef DEBUG_NR_PUCCH_TX - printf("4 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("4 "); +#endif } + if (((rb+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*(rb+startingPRB)) + frame_parms->first_carrier_offset; - #ifdef DEBUG_NR_PUCCH_TX - printf("5 "); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("5 "); +#endif } - #ifdef DEBUG_NR_PUCCH_TX - printf("re_offset=%d,(rb+startingPRB)=%d\n",re_offset,(rb+startingPRB)); - #endif + +#ifdef DEBUG_NR_PUCCH_TX + printf("re_offset=%d,(rb+startingPRB)=%d\n",re_offset,(rb+startingPRB)); +#endif + //txptr = &txdataF[0][re_offset]; - for (int n=0; n<12; n++){ + for (int n=0; n<12; n++) { if ((n==6) && ((rb+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 (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 0) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3 ((int16_t *)&txdataF[0][re_offset])[0] = z_re[n+k]; ((int16_t *)&txdataF[0][re_offset])[1] = z_im[n+k]; - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(z(l=%d,n=%d)=(%d,%d))\n", - l,rb,n,k,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+k,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%d)=(z(l=%d,n=%d)=(%d,%d))\n", + l,rb,n,k,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+k,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2 ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15) - - (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15)); + - (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15)); ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15) - + (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15)); - #ifdef DEBUG_NR_PUCCH_TX - printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) 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)=(r_u_v(l=%d,n=%d)=(%d,%d))\n", - l,rb,n,j,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+j,re_offset, - l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); - #endif + + (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15)); +#ifdef DEBUG_NR_PUCCH_TX + printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) 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)=(r_u_v(l=%d,n=%d)=(%d,%d))\n", + l,rb,n,j,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+j,re_offset, + l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]); +#endif } + re_offset++; } + if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 0) k+=12; + if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) j+=12; } } - } diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index eb10c27857..79c243d899 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -116,7 +116,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, * Where base sequence r_u_v(n)=exp[j*phi(n)*pi/4] 0<=n<=M_ZC-1 and M_ZC={6,12,18,24} * For M_ZC=30, base sequence r_u_v(n)=exp[-j((pi*[u+1]*[n+1]*[n+2])/31)] */ - int16_t table_5_2_2_2_1_Re[30][6]={ // Table 5.2.2.2-1 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) + static const int16_t table_5_2_2_2_1_Re[30][6]={ // Table 5.2.2.2-1 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) {-23170, 23170,-23170,-23170, 23170,-23170}, {-23170,-23170, 23170, 23170,-23170,-23170}, {-23170,-23170,-23170,-23170, 23170,-23170}, @@ -148,7 +148,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, { 23170, 23170, 23170,-23170,-23170, 23170}, { 23170, 23170,-23170, 23170, 23170, 23170} }; - int16_t table_5_2_2_2_1_Im[30][6]={ // Table 5.2.2.2-1 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) + static const int16_t table_5_2_2_2_1_Im[30][6]={ // Table 5.2.2.2-1 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=6) {-23170,-23170, 23170, 23170,-23170,-23170}, {-23170, 23170,-23170,-23170, 23170,-23170}, {-23170,-23170,-23170, 23170, 23170,-23170}, @@ -180,7 +180,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, { 23170, 23170,-23170, 23170,-23170,-23170}, { 23170, 23170,-23170, 23170,-23170,-23170} }; - int16_t table_5_2_2_2_2_Re[30][12]={ // Table 5.2.2.2-2 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) + static const int16_t table_5_2_2_2_2_Re[30][12]={ // Table 5.2.2.2-2 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) {-23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170}, {-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, {-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170}, @@ -212,7 +212,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, { 23170, 23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170, 23170}, {-23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170} }; - int16_t table_5_2_2_2_2_Im[30][12]={ // Table 5.2.2.2-2 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) + static const int16_t table_5_2_2_2_2_Im[30][12]={ // Table 5.2.2.2-2 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=12) {-23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170,-23170}, {-23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170}, {-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170}, @@ -244,7 +244,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, { 23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170}, {-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170} }; - int16_t table_5_2_2_2_3_Re[30][18]={ // Table 5.2.2.2-3 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) + static const int16_t table_5_2_2_2_3_Re[30][18]={ // Table 5.2.2.2-3 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) { 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170}, {-23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170}, {-23170,-23170, 23170, 23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170}, @@ -276,7 +276,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, { 23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170, 23170}, {-23170,-23170, 23170, 23170, 23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170} }; - int16_t table_5_2_2_2_3_Im[30][18]={ // Table 5.2.2.2-3 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) + static const int16_t table_5_2_2_2_3_Im[30][18]={ // Table 5.2.2.2-3 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=18) {-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, { 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170}, {-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170, 23170, 23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170}, @@ -308,7 +308,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, {-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170, 23170}, {-23170, 23170, 23170,-23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170} }; - int16_t table_5_2_2_2_4_Re[30][24]={ // Table 5.2.2.2-4 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) + static const int16_t table_5_2_2_2_4_Re[30][24]={ // Table 5.2.2.2-4 (Re part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) { 23170,-23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170,-23170}, { 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170,-23170, 23170,-23170,-23170,-23170,-23170}, { 23170,-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170}, @@ -340,7 +340,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, {-23170, 23170,-23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170}, {-23170,-23170, 23170, 23170,-23170, 23170, 23170,-23170, 23170,-23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170} }; - int16_t table_5_2_2_2_4_Im[30][24]={ // Table 5.2.2.2-4 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) + static const int16_t table_5_2_2_2_4_Im[30][24]={ // Table 5.2.2.2-4 (Im part) TS 38.211 Subclause 5.2.2.2 Base sequences of length less than 36 (M_ZC=24) {-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170, 23170, 23170, 23170,-23170,-23170,-23170}, {-23170,-23170, 23170, 23170, 23170,-23170, 23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170,-23170, 23170, 23170, 23170,-23170, 23170, 23170, 23170,-23170,-23170}, {-23170,-23170,-23170, 23170,-23170,-23170,-23170, 23170, 23170,-23170,-23170,-23170,-23170,-23170, 23170, 23170, 23170, 23170,-23170,-23170,-23170, 23170,-23170,-23170}, @@ -378,17 +378,17 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, * One table for no intra-slot hopping * Two tables for intra-slot hopping (mprime=0 and mprime=1) */ - uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,2,3,3,4,4,5,5,6,6,7}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping - uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,1,1,2,2,2,2,3,3,3}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 - uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 + static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,2,3,3,4,4,5,5,6,6,7}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping + static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,1,1,2,2,2,2,3,3,3}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 + static const uint8_t table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 /* * The following tables implement TS 38.211 table 6.4.1.3.1.1-1: Number of DM-RS symbols and the corresponding N_SF_mprime_PUCCH_1 * One table for no intra-slot hopping * Two tables for intra-slot hopping (mprime=0 and mprime=1) */ - uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,3,3,4,4,5,5,6,6,7,7}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping - uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 - uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,2,1,2,2,3,2,3,3,4,3}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 + static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[14] = {0,0,0,2,3,3,4,4,5,5,6,6,7,7}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when no intra-slot hopping + static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[14] = {0,0,0,1,1,2,2,2,2,3,3,3,3,4}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=0 + static const uint8_t table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[14] = {0,0,0,1,2,1,2,2,3,2,3,3,4,3}; // for index PUCCH-DM-RS-length, we obtain N_SF_mprime_PUCCH_1 when intra-slot hopping and mprime=1 /* The following tables implement TS 38.211 table 6.3.2.4.1-2: Orthogonal sequences wi(m)=exp(j*2*pi*phi(m)/N_SF) for PUCCH format 1 uint16_t table_6_3_2_4_1_2_W2[2][2] = {{0,0}, {0,1}}; uint16_t table_6_3_2_4_1_2_W3[3][3] = {{0,0,0}, {0,1,2}, {0,2,1}}; @@ -397,7 +397,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, uint16_t table_6_3_2_4_1_2_W6[2][2] = {{0,0,0,0,0,0}, {0,1,2,3,4,5}, {0,2,4,0,2,4}, {0,3,0,3,0,3}, {0,4,2,0,4,2}, {0,5,4,3,2,1}}; uint16_t table_6_3_2_4_1_2_W7[2][2] = {{0,0,0,0,0,0,0},{0,1,2,3,4,5,6},{0,2,4,6,1,3,5},{0,3,6,2,5,1,4},{0,4,1,5,2,6,3},{0,5,3,1,6,4,2},{0,6,5,4,3,2,1}}; */ - int16_t table_6_3_2_4_1_2_Wi_Re[8][7][7] = { + static const int16_t table_6_3_2_4_1_2_Wi_Re[8][7][7] = { {{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, {{32767,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, {{32767,32767,0,0,0,0,0}, {32767,-32767,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, @@ -407,7 +407,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, {{32767,32767,32767,32767,32767,32767,0}, {32767,16384,-16384,-32767,-16384,16384,0}, {32767,-16384,-16384,32767,-16384,-16384,0}, {32767,-32767,32767,-32767,32767,-32767,0}, {32767,-16384,-16384,32767,-16384,-16384,0}, {32767,16384,-16384,-32767,-16384,16384,0}, {0,0,0,0,0,0,0}}, {{32767,32767,32767,32767,32767,32767,32767},{32767,20430,-7291,-29522,-29522,-7291,20430},{32767,-7291,-29522,20430,20430,-29522,-7291},{32767,-29522,20430,-7291,-7291,20430,-29522},{32767,-29522,20430,-7291,-7291,20430,-29522},{32767,-7291,-29522,20430,20430,-29522,-7291},{32767,20430,-7291,-29522,-29522,-7291,20430}} }; - int16_t table_6_3_2_4_1_2_Wi_Im[8][7][7] = { + static const int16_t table_6_3_2_4_1_2_Wi_Im[8][7][7] = { {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}}, @@ -418,7 +418,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, {{0,0,0,0,0,0,0},{0,25618,31945,14217,-14217,-31945,-25618},{0,31945,-14217,-25618,25618,14217,-31945},{0,14217,-25618,31945,-31945,25618,-14217},{0,-14217,25618,-31945,31945,-25618,14217},{0,-31945,14217,25618,-25618,-14217,31945},{0,-25618,-31945,-14217,14217,31945,25618}} }; - uint8_t list_of_prime_numbers[46] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + static const uint8_t list_of_prime_numbers[46] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,103,107,109,113, 127,131,137,139,149,151,157,163,167,173, diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 26639a5134..3d36822956 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -430,39 +430,6 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric,uint8_t *phase_max) int32_t metric, metric_re; int16_t *d; - /* slop_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */ - /* for NR this is not the case but slot_fep is still used for computing FFT of samples */ - /* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */ - /* symbol number are from beginning of SS/PBCH blocks as below: */ - /* Signal PSS PBCH SSS PBCH */ - /* symbol number 0 1 2 3 */ - /* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */ - /* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */ - - int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - // For now, symbol 0 = PSS/PBCH and it is never in symbol 0 or 7*2^mu (i.e. always shorter prefix) - frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples; - - // Do FFTs for SSS/PSS - // SSS - nr_slot_fep(ue, - SSS_SYMBOL_NB-PSS_SYMBOL_NB, // symbol number w.r.t. PSS - 0, // Ns slot number - ue->ssb_offset, // sample_offset of int16_t - 0, // no_prefix - 1, // reset frequency estimation - NR_SSS_EST); - - // PSS - nr_slot_fep(ue, - 0, - 0, - ue->ssb_offset, - 0, - 1, - NR_SSS_EST); - - frame_parms->nb_prefix_samples0 = nb_prefix_samples0; // pss sss extraction pss_sss_extract_nr(ue, diff --git a/openair1/PHY/TOOLS/cdot_prod.c b/openair1/PHY/TOOLS/cdot_prod.c index 63b74afe6d..843a9605f1 100644 --- a/openair1/PHY/TOOLS/cdot_prod.c +++ b/openair1/PHY/TOOLS/cdot_prod.c @@ -169,7 +169,7 @@ int64_t dot_product64(int16_t *x, #if defined(__x86_64__) || defined(__i386__) __m128i *x128,*y128,mmtmp1,mmtmp2,mmtmp3,mmcumul,mmcumul_re,mmcumul_im; __m128i minus_i = _mm_set_epi16(-1,1,-1,1,-1,1,-1,1); - int32_t result; + int64_t result; x128 = (__m128i*) x; y128 = (__m128i*) y; @@ -180,14 +180,13 @@ int64_t dot_product64(int16_t *x, for (n=0; n<(N>>2); n++) { // printf("n=%d, x128=%p, y128=%p\n",n,x128,y128); - // print_shorts("x",&x128[0]); - // print_shorts("y",&y128[0]); + // print_shorts("x",&x128[0]); + // print_shorts("y",&y128[0]); // this computes Re(z) = Re(x)*Re(y) + Im(x)*Im(y) mmtmp1 = _mm_madd_epi16(x128[0],y128[0]); // print_ints("retmp",&mmtmp1); // mmtmp1 contains real part of 4 consecutive outputs (32-bit) - // shift and accumulate results mmtmp1 = _mm_srai_epi32(mmtmp1,output_shift); mmcumul_re = _mm_add_epi32(mmcumul_re,mmtmp1); @@ -205,7 +204,6 @@ int64_t dot_product64(int16_t *x, mmtmp3 = _mm_madd_epi16(x128[0],mmtmp2); //print_ints("imtmp",&mmtmp3); // mmtmp3 contains imag part of 4 consecutive outputs (32-bit) - // shift and accumulate results mmtmp3 = _mm_srai_epi32(mmtmp3,output_shift); mmcumul_im = _mm_add_epi32(mmcumul_im,mmtmp3); @@ -218,13 +216,10 @@ int64_t dot_product64(int16_t *x, // this gives Re Re Im Im mmcumul = _mm_hadd_epi32(mmcumul_re,mmcumul_im); //print_ints("cumul1",&mmcumul); - // this gives Re Im Re Im mmcumul = _mm_hadd_epi32(mmcumul,mmcumul); - //print_ints("cumul2",&mmcumul); - //mmcumul = _mm_srai_epi32(mmcumul,output_shift); // extract the lower half result = _mm_extract_epi64(mmcumul,0); diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 0100dd44c4..3dd16ff0da 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -498,10 +498,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, float **rxsig_t_dB; float *time; float *corr; - /* int16_t **chest_t; int16_t **chest_f; - */ int16_t *pdsch_llr; int16_t *pdsch_comp; //int16_t *pdsch_mag; @@ -519,10 +517,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, int coded_bits_per_codeword = num_re*Qm; int symbol, first_symbol,nb_re; int nb_rb_pdsch =50; + float ymax=1; + float **chest_t_abs; + float Re,Im; + float *chest_f_abs; + float *freq; + static int overlay = 0; /* - float Re,Im,ymax=1; - float **chest_t_abs, *chest_f_abs; - float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx; int mcs = 0; unsigned char harq_pid = 0; @@ -565,15 +566,15 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, */ I = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float)); Q = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float)); - /* + chest_t_abs = (float**) malloc(nb_antennas_rx*sizeof(float*)); for (arx=0; arxofdm_symbol_size,sizeof(float)); } - chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); - */ + chest_f_abs = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); + freq = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero bit = malloc(coded_bits_per_codeword*sizeof(float)); @@ -589,10 +590,9 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, time = calloc(samples_per_frame,sizeof(float)); corr = calloc(samples_per_frame,sizeof(float)); - /* chest_t = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id]; chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id]; - */ + pbch_llr = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; @@ -628,29 +628,37 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } if (phy_vars_ue->is_synchronized==0) { - for (ind=0;ind<3;ind++) { - if (pss_corr_ue[ind]) { - for (i=0; ichest_t,time,corr,samples_per_frame,"","",""); + else + fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]); + + overlay = 1; } - - if (ind==0) - fl_set_xyplot_data(form->chest_t,time,corr,samples_per_frame,"","",""); - else - fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]); } - } + } + else { + + if (overlay) { //there was a previous overlay + fl_clear_xyplot(form->chest_t); + overlay = 0; } - /* - // Channel Impulse Response (still repeated format) + // Channel Impulse Response if (chest_t != NULL) { ymax = 0; if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { - chest_t_abs[0][i] = (float) (chest_t[0][4*i]*chest_t[0][4*i]+chest_t[0][4*i+1]*chest_t[0][4*i+1]); + chest_t_abs[0][i] = (float) (chest_t[0][2*i]*chest_t[0][2*i]+chest_t[0][2*i+1]*chest_t[0][2*i+1]); + time[i] = (float) i; if (chest_t_abs[0][i] > ymax) ymax = chest_t_abs[0][i]; @@ -658,7 +666,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_data(form->chest_t,time,chest_t_abs[0],(frame_parms->ofdm_symbol_size>>3),"","",""); } - + /* for (arx=1; arxofdm_symbol_size>>3); i++) { @@ -672,11 +680,12 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT); } } - + */ // Avoid flickering effect // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); // Does not always work... fl_set_xyplot_ybounds(form->chest_t,0,(double) ymax); } + } // Channel Frequency Response (includes 5 complex sample for filter) if (chest_f != NULL) { @@ -685,7 +694,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, for (atx=0; atxofdm_symbol_size; k++) { freq[ind] = (float)ind; Re = (float)(chest_f[(atx<<1)+arx][(2*k)]); Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]); @@ -698,12 +707,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } // tx antenna 0 - fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); + //fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); - fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); - fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); + //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); + fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,frame_parms->ofdm_symbol_size,"","",""); + /* for (arx=1; arxchest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } @@ -722,8 +732,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } } + */ } - */ // PBCH LLRs if (pbch_llr != NULL) { @@ -735,10 +745,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_data(form->pbch_llr,bit_pbch,llr_pbch,864,"","",""); } - if (phy_vars_ue->is_synchronized==1) - first_symbol=5; - else - first_symbol=1; + first_symbol=1; // PBCH I/Q of MF Output if (pbch_comp!=NULL) { diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 585f28f90f..76769ed4db 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -399,7 +399,7 @@ typedef struct RU_t_s{ /// function pointer to release function for radio interface int (*stop_rf)(struct RU_t_s *ru); /// function pointer to initialization function for radio interface - int (*start_if)(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB); + int (*start_if)(struct RU_t_s *ru,struct PHY_VARS_gNB_s *gNB); /// function pointer to RX front-end processing routine (DFTs/prefix removal or NULL) void (*feprx)(struct RU_t_s *ru); /// function pointer to TX front-end processing routine (IDFTs and prefix removal or NULL) diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 24a9fd45c8..24be9688dc 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -38,6 +38,10 @@ #include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/impl_defs_top.h" +#include "PHY/defs_common.h" +#include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h" +#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" #define MAX_NUM_RU_PER_gNB MAX_NUM_RU_PER_eNB @@ -72,6 +76,7 @@ typedef struct { uint64_t dci_pdu[2]; } NR_gNB_DCI_ALLOC_t; + typedef struct { uint8_t num_dci; uint8_t num_pdsch_rnti; @@ -79,6 +84,14 @@ typedef struct { } NR_gNB_PDCCH; +typedef enum { + NR_SCH_IDLE, + NR_ACTIVE, + NR_CBA_ACTIVE, + NR_DISABLED +} NR_SCH_status_t; + + typedef struct { /// Nfapi DLSCH PDU nfapi_nr_dl_config_dlsch_pdu dlsch_pdu; @@ -114,7 +127,6 @@ typedef struct { typedef struct { - /// Pointers to 16 HARQ processes for the DLSCH NR_DL_gNB_HARQ_t *harq_processes[NR_MAX_NB_HARQ_PROCESSES]; /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding) @@ -160,6 +172,170 @@ typedef struct { } NR_gNB_DLSCH_t; +typedef struct { + /// Nfapi ULSCH PDU + nfapi_nr_ul_config_ulsch_pdu ulsch_pdu; + /// Frame where current HARQ round was sent + uint32_t frame; + /// Subframe where current HARQ round was sent + uint32_t subframe; + /// Index of current HARQ round for this DLSCH + uint8_t round; + /// Last TPC command + uint8_t TPC; + /// MIMO mode for this DLSCH + MIMO_mode_t mimo_mode; + /// Flag indicating that this ULSCH has been allocated by a DCI (otherwise it is a retransmission based on PHICH NAK) + uint8_t dci_alloc; + /// Flag indicating that this ULSCH has been allocated by a RAR (otherwise it is a retransmission based on PHICH NAK or DCI) + uint8_t rar_alloc; + /// Status Flag indicating for this ULSCH (idle,active,disabled) + NR_SCH_status_t status; + /// Subframe scheduling indicator (i.e. Transmission opportunity indicator) + uint8_t subframe_scheduling_flag; + /// Subframe cba scheduling indicator (i.e. CBA Transmission opportunity indicator) + uint8_t subframe_cba_scheduling_flag; + /// PHICH active flag + uint8_t phich_active; + /// PHICH ACK + uint8_t phich_ACK; + /// First Allocated RB - previous scheduling. This is needed for PHICH generation which is done after a new scheduling + uint16_t previous_first_rb; + /// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around + uint8_t handled; + /// Flag to indicate that this ULSCH is for calibration information sent from UE (i.e. no MAC SDU to pass up) + // int calibration_flag; + /// delta_TF for power control + int32_t delta_TF; + + + /////////////////////// ulsch decoding /////////////////////// + /// Transport block size (This is A from 38.212 V15.4.0 section 5.1) + uint32_t TBS; + /// Pointer to the payload (38.212 V15.4.0 section 5.1) + uint8_t *b; + /// The payload + CRC (24 bits) in bits (38.212 V15.4.0 section 5.1) + uint32_t B; + /// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2) + uint8_t *c[MAX_NUM_NR_ULSCH_SEGMENTS]; + /// Number of bits in each code block (38.212 V15.4.0 section 5.2.2) + uint32_t K; + /// Number of "Filler" bits added in the code block segmentation (38.212 V15.4.0 section 5.2.2) + uint32_t F; + /// Number of code blocks after code block segmentation (38.212 V15.4.0 section 5.2.2) + uint32_t C; + /// Pointers to code blocks after LDPC coding (38.212 V15.4.0 section 5.3.2) + int16_t *d[MAX_NUM_NR_ULSCH_SEGMENTS]; + /// LDPC processing buffer + t_nrLDPC_procBuf* p_nrLDPC_procBuf[MAX_NUM_NR_ULSCH_SEGMENTS]; + /// LDPC lifting size (38.212 V15.4.0 table 5.3.2-1) + uint32_t Z; + /// 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]; + /// 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; + ////////////////////////////////////////////////////////////// + + + /////////////////////////// DMRS ///////////////////////////// + /// n_DMRS for cyclic shift of DMRS (36.213 Table 9.1.2-2) + uint8_t n_DMRS; + /// n_DMRS 2 for cyclic shift of DMRS (36.211 Table 5.5.1.1.-1) + uint8_t n_DMRS2; + /// n_DMRS for cyclic shift of DMRS (36.213 Table 9.1.2-2) - previous scheduling + /// This is needed for PHICH generation which + /// is done after a new scheduling + uint8_t previous_n_DMRS; + ////////////////////////////////////////////////////////////// + + + ///////////////////// UCI multiplexing /////////////////////// + /// CQI CRC status + uint8_t cqi_crc_status; + /// Pointer to CQI data + uint8_t o[MAX_CQI_BYTES]; + /// Format of CQI data + UCI_format_t uci_format; + /// Length of CQI data under RI=1 assumption(bits) + uint8_t Or1; + /// Length of CQI data under RI=2 assumption(bits) + uint8_t Or2; + /// Rank information + uint8_t o_RI[2]; + /// Length of rank information (bits) + uint8_t O_RI; + /// Pointer to ACK + uint8_t o_ACK[4]; + /// Length of ACK information (bits) + uint8_t O_ACK; + /// The value of DAI in DCI format 0 + uint8_t V_UL_DAI; + /// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27) + int8_t q[MAX_CQI_PAYLOAD]; + /// number of coded CQI bits after interleaving + uint8_t o_RCC; + /// coded and interleaved CQI bits + int8_t o_w[(MAX_CQI_BITS+8)*3]; + /// coded CQI bits + int8_t o_d[96+((MAX_CQI_BITS+8)*3)]; + /// coded ACK bits + int16_t q_ACK[MAX_ACK_PAYLOAD]; + /// coded RI bits + int16_t q_RI[MAX_RI_PAYLOAD]; + /// Temporary h sequence to flag PUSCH_x/PUSCH_y symbols which are not scrambled + uint8_t h[MAX_NUM_CHANNEL_BITS]; + /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) + int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; + ////////////////////////////////////////////////////////////// +} NR_UL_gNB_HARQ_t; + + +typedef struct { + /// Pointers to 16 HARQ processes for the ULSCH + NR_UL_gNB_HARQ_t *harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES]; + /// Current HARQ process id + int harq_process_id[NR_MAX_SLOTS_PER_FRAME]; + /// HARQ process mask, indicates which processes are currently active + uint16_t harq_mask; + /// ACK/NAK Bundling flag + uint8_t bundling; + /// beta_offset_cqi times 8 + uint16_t beta_offset_cqi_times8; + /// beta_offset_ri times 8 + uint16_t beta_offset_ri_times8; + /// beta_offset_harqack times 8 + uint16_t beta_offset_harqack_times8; + /// Flag to indicate that gNB awaits UE Msg3 + uint8_t Msg3_active; + /// Flag to indicate that gNB should decode UE Msg3 + uint8_t Msg3_flag; + /// Subframe for Msg3 + uint8_t Msg3_subframe; + /// Frame for Msg3 + uint32_t Msg3_frame; + /// Allocated RNTI for this ULSCH + uint16_t rnti; + /// RNTI type + uint8_t rnti_type; + /// cyclic shift for DM RS + uint8_t cyclicShift; + /// for cooperative communication + uint8_t cooperation_flag; + /// Maximum number of HARQ rounds + uint8_t Mlimit; + /// Maximum number of LDPC iterations + uint8_t max_ldpc_iterations; + /// number of iterations used in last LDPC decoding + uint8_t last_iteration_cnt; + /// num active cba group + uint8_t num_active_cba_groups; + /// num active cba group + uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; +} NR_gNB_ULSCH_t; + + typedef struct { /// \brief Pointers (dynamic) to the received data in the time domain. /// - first index: rx antenna [0..nb_antennas_rx[ @@ -391,21 +567,21 @@ typedef struct PHY_VARS_gNB_s { Sched_Rsp_t Sched_INFO; NR_gNB_PDCCH pdcch_vars; NR_gNB_PBCH pbch; - t_nrPolar_paramsPtr nrPolar_params; LTE_eNB_PHICH phich_vars[2]; NR_gNB_COMMON common_vars; - LTE_eNB_UCI uci_vars[NUMBER_OF_UE_MAX]; - LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; - LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX]; - LTE_eNB_PRACH prach_vars; - NR_gNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams - LTE_eNB_ULSCH_t *ulsch[NUMBER_OF_UE_MAX+1]; // Nusers + number of RA + LTE_eNB_UCI uci_vars[NUMBER_OF_UE_MAX]; + LTE_eNB_SRS srs_vars[NUMBER_OF_UE_MAX]; + LTE_eNB_PUSCH *pusch_vars[NUMBER_OF_UE_MAX]; + LTE_eNB_PRACH prach_vars; + NR_gNB_DLSCH_t *dlsch[NUMBER_OF_UE_MAX][2]; // Nusers times two spatial streams + NR_gNB_ULSCH_t *ulsch[NUMBER_OF_UE_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 NR_gNB_DLSCH_t *dlsch_SI,*dlsch_ra,*dlsch_p; NR_gNB_DLSCH_t *dlsch_MCH; NR_gNB_DLSCH_t *dlsch_PCH; - LTE_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX]; - LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX]; + LTE_eNB_UE_stats UE_stats[NUMBER_OF_UE_MAX]; + LTE_eNB_UE_stats *UE_stats_ptr[NUMBER_OF_UE_MAX]; uint8_t pbch_configured; uint8_t pbch_pdu[4]; //PBCH_PDU_SIZE diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index c11ba8933f..f447c6895e 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -37,7 +37,7 @@ #include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" -#define _GNU_SOURCE +#define _GNU_SOURCE #include #include #include @@ -49,28 +49,28 @@ //#include #include "assertions.h" #ifdef MEX -# define msg mexPrintf + #define msg mexPrintf #else -# ifdef OPENAIR2 -# if ENABLE_RAL -# include "collection/hashtable/hashtable.h" -# include "COMMON/ral_messages_types.h" -# include "UTIL/queue.h" -# endif -# define msg(aRGS...) LOG_D(PHY, ##aRGS) -# else -# define msg printf -# endif + #ifdef OPENAIR2 + #if ENABLE_RAL + #include "collection/hashtable/hashtable.h" + #include "COMMON/ral_messages_types.h" + #include "UTIL/queue.h" + #endif + #define msg(aRGS...) LOG_D(PHY, ##aRGS) + #else + #define msg printf + #endif #endif //use msg in the real-time thread context #define msg_nrt printf //use msg_nrt in the non real-time context (for initialization, ...) #ifndef malloc16 -# ifdef __AVX2__ -# define malloc16(x) memalign(32,x) -# else -# define malloc16(x) memalign(16,x) -# endif + #ifdef __AVX2__ + #define malloc16(x) memalign(32,x) + #else + #define malloc16(x) memalign(16,x) + #endif #endif #define free16(y,x) free(y) #define bigmalloc malloc @@ -146,7 +146,7 @@ #if defined(UPGRADE_RAT_NR) -#include "PHY/NR_REFSIG/ss_pbch_nr.h" + #include "PHY/NR_REFSIG/ss_pbch_nr.h" #endif @@ -167,12 +167,12 @@ typedef struct { uint8_t CC_id; /// timestamp transmitted to HW openair0_timestamp timestamp_tx; -//#ifdef UE_NR_PHY_DEMO + //#ifdef UE_NR_PHY_DEMO /// NR TTI index within subframe_tx [0 .. ttis_per_subframe - 1] to act upon for transmission int nr_tti_tx; /// NR TTI index within subframe_rx [0 .. ttis_per_subframe - 1] to act upon for reception int nr_tti_rx; -//#endif + //#endif /// subframe to act upon for transmission int subframe_tx; /// subframe to act upon for reception @@ -202,7 +202,7 @@ typedef struct { //pthread_t pthread_slot0_dl_processing; pthread_t pthread_slot1_dl_processing; /// pthread attributes for fep_slot1 processing thread - // pthread_attr_t attr_slot0_dl_processing; + // pthread_attr_t attr_slot0_dl_processing; pthread_attr_t attr_slot1_dl_processing; /// condition variable for UE fep_slot1 thread; //pthread_cond_t cond_slot0_dl_processing; @@ -216,7 +216,7 @@ typedef struct { //pthread_t pthread_slot0_dl_processing; pthread_t pthread_dlsch_td; /// pthread attributes for fep_slot1 processing thread - // pthread_attr_t attr_slot0_dl_processing; + // pthread_attr_t attr_slot0_dl_processing; pthread_attr_t attr_dlsch_td; /// condition variable for UE fep_slot1 thread; //pthread_cond_t cond_slot0_dl_processing; @@ -250,7 +250,7 @@ typedef struct { //pthread_t pthread_slot0_dl_processing; pthread_t pthread_dlsch_td1; /// pthread attributes for fep_slot1 processing thread - // pthread_attr_t attr_slot0_dl_processing; + // pthread_attr_t attr_slot0_dl_processing; pthread_attr_t attr_dlsch_td1; /// condition variable for UE fep_slot1 thread; //pthread_cond_t cond_slot0_dl_processing; @@ -267,27 +267,6 @@ typedef struct { uint8_t CC_id; /// Last RX timestamp openair0_timestamp timestamp_rx; - /// pthread attributes for main UE thread - pthread_attr_t attr_ue; - /// scheduling parameters for main UE thread - struct sched_param sched_param_ue; - /// pthread descriptor main UE thread - pthread_t pthread_ue; - /// \brief Instance count for synch thread. - /// \internal This variable is protected by \ref mutex_synch. - int instance_cnt_synch; - /// pthread attributes for synch processing thread - pthread_attr_t attr_synch; - /// scheduling parameters for synch thread - struct sched_param sched_param_synch; - /// pthread descriptor synch thread - pthread_t pthread_synch; - /// condition variable for UE synch thread; - pthread_cond_t cond_synch; - /// mutex for UE synch thread - pthread_mutex_t mutex_synch; - /// set of scheduling variables RXn-TXnp4 threads - UE_nr_rxtx_proc_t proc_rxtx[RX_NB_TH]; } UE_nr_proc_t; typedef enum { @@ -394,23 +373,23 @@ typedef struct { typedef struct { - /// \brief Holds the received data in the frequency domain. - /// - first index: rx antenna [0..nb_antennas_rx[ - /// - second index: symbol [0..28*ofdm_symbol_size[ - int32_t **rxdataF; + /// \brief Holds the received data in the frequency domain. + /// - first index: rx antenna [0..nb_antennas_rx[ + /// - second index: symbol [0..28*ofdm_symbol_size[ + int32_t **rxdataF; - /// \brief Hold the channel estimates in frequency domain. - /// - first index: eNB id [0..6] (hard coded) - /// - second index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - third index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[ - int32_t **dl_ch_estimates[7]; + /// \brief Hold the channel estimates in frequency domain. + /// - first index: eNB id [0..6] (hard coded) + /// - second index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx + /// - third index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[ + int32_t **dl_ch_estimates[7]; - /// \brief Hold the channel estimates in time domain (used for tracking). - /// - first index: eNB id [0..6] (hard coded) - /// - second index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - third index: samples? [0..2*ofdm_symbol_size[ - int32_t **dl_ch_estimates_time[7]; -}NR_UE_COMMON_PER_THREAD; + /// \brief Hold the channel estimates in time domain (used for tracking). + /// - first index: eNB id [0..6] (hard coded) + /// - second index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx + /// - third index: samples? [0..2*ofdm_symbol_size[ + int32_t **dl_ch_estimates_time[7]; +} NR_UE_COMMON_PER_THREAD; typedef struct { /// \brief Holds the transmit data in time domain. @@ -512,9 +491,9 @@ typedef struct { int16_t *llr[2]; /// \f$\log_2(\max|H_i|^2)\f$ int16_t log2_maxh; - /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer1 channel compensation + /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer1 channel compensation int16_t log2_maxh0; - /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer2 channel commpensation + /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer2 channel commpensation int16_t log2_maxh1; /// \brief LLR shifts for subband scaling. /// - first index: ? [0..168*N_RB_DL[ @@ -663,7 +642,8 @@ typedef enum { _format_2_0_found=4, _format_2_1_found=5, _format_2_2_found=6, - _format_2_3_found=7} format_found_t; + _format_2_3_found=7 +} format_found_t; #define TOTAL_NBR_SCRAMBLED_VALUES 13 #define _C_RNTI_ 0 #define _CS_RNTI_ 1 @@ -678,20 +658,21 @@ typedef enum { #define _TPC_PUSCH_RNTI_ 10 #define _TPC_PUCCH_RNTI_ 11 #define _TPC_SRS_RNTI_ 12 - typedef enum { /* see 38.321 Table 7.1-2 RNTI usage */ - _c_rnti = _C_RNTI_, /* Cell RNTI */ - _cs_rnti = _CS_RNTI_, /* Configured Scheduling RNTI */ - _new_rnti = _NEW_RNTI_, /* ? */ - _tc_rnti = _TC_RNTI_, /* Temporary C-RNTI */ - _p_rnti = _P_RNTI_, /* Paging RNTI */ - _si_rnti = _SI_RNTI_, /* System information RNTI */ - _ra_rnti = _RA_RNTI_, /* Random Access RNTI */ - _sp_csi_rnti = _SP_CSI_RNTI_, /* Semipersistent CSI reporting on PUSCH */ - _sfi_rnti = _SFI_RNTI_, /* Slot Format Indication on the given cell */ - _int_rnti = _INT_RNTI_, /* Indication pre-emption in DL */ - _tpc_pusch_rnti = _TPC_PUSCH_RNTI_, /* PUSCH power control */ - _tpc_pucch_rnti = _TPC_PUCCH_RNTI_, /* PUCCH power control */ - _tpc_srs_rnti = _TPC_SRS_RNTI_} crc_scrambled_t; +typedef enum { /* see 38.321 Table 7.1-2 RNTI usage */ + _c_rnti = _C_RNTI_, /* Cell RNTI */ + _cs_rnti = _CS_RNTI_, /* Configured Scheduling RNTI */ + _new_rnti = _NEW_RNTI_, /* ? */ + _tc_rnti = _TC_RNTI_, /* Temporary C-RNTI */ + _p_rnti = _P_RNTI_, /* Paging RNTI */ + _si_rnti = _SI_RNTI_, /* System information RNTI */ + _ra_rnti = _RA_RNTI_, /* Random Access RNTI */ + _sp_csi_rnti = _SP_CSI_RNTI_, /* Semipersistent CSI reporting on PUSCH */ + _sfi_rnti = _SFI_RNTI_, /* Slot Format Indication on the given cell */ + _int_rnti = _INT_RNTI_, /* Indication pre-emption in DL */ + _tpc_pusch_rnti = _TPC_PUSCH_RNTI_, /* PUSCH power control */ + _tpc_pucch_rnti = _TPC_PUCCH_RNTI_, /* PUCCH power control */ + _tpc_srs_rnti = _TPC_SRS_RNTI_ +} crc_scrambled_t; typedef enum {bundle_n2=2,bundle_n3=3,bundle_n6=6} NR_UE_CORESET_REG_bundlesize_t; @@ -712,33 +693,33 @@ typedef struct { /* * define CORESET structure according to 38.331 * - * controlResourceSetId: Corresponds to L1 parameter 'CORESET-ID' - * Value 0 identifies the common CORESET configured in MIB and in ServingCellConfigCommon - * Values 1..maxNrofControlResourceSets-1 identify CORESETs configured by dedicated signalling - * frequencyDomainResources: BIT STRING (SIZE (45)) - * Corresponds to L1 parameter 'CORESET-freq-dom'(see 38.211, section 7.3.2.2) - * Frequency domain resources for the CORESET. Each bit corresponds a group of 6 RBs, with grouping starting from PRB 0, - * which is fully contained in the bandwidth part within which the CORESET is configured. - * duration: INTEGER (1..maxCoReSetDuration) - * Corresponds to L1 parameter 'CORESET-time-duration' (see 38.211, section 7.3.2.2FFS_Section) - * Contiguous time duration of the CORESET in number of symbols - * cce-REG-MappingType: interleaved - * reg-BundleSize: ENUMERATED {n2, n3, n6} - * interleaverSize: ENUMERATED {n2, n3, n6} - * shiftIndex: INTEGER - * nonInterleaved NULL - * precoderGranularity: ENUMERATED {sameAsREG-bundle, allContiguousRBs} - * Corresponds to L1 parameter 'CORESET-precoder-granuality' (see 38.211, sections 7.3.2.2 and 7.4.1.3.2) - * tci-StatesPDCCH: SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL - * A subset of the TCI states defined in TCI-States used for providing QCL relationships between the DL RS(s) - * in one RS Set (TCI-State) and the PDCCH DMRS ports. - * Corresponds to L1 parameter 'TCI-StatesPDCCH' (see 38.214, section FFS_Section) - * tci-PresentInDCI: ENUMERATED {enabled} OPTIONAL - * Corresponds to L1 parameter 'TCI-PresentInDCI' (see 38,213, section 5.1.5) - * pdcch-DMRS-ScramblingID: BIT STRING (SIZE (16)) OPTIONAL - * PDCCH DMRS scrambling initalization. - * Corresponds to L1 parameter 'PDCCH-DMRS-Scrambling-ID' (see 38.214, section 5.1) - * When the field is absent the UE applies the value '0'. + * controlResourceSetId: Corresponds to L1 parameter 'CORESET-ID' + * Value 0 identifies the common CORESET configured in MIB and in ServingCellConfigCommon + * Values 1..maxNrofControlResourceSets-1 identify CORESETs configured by dedicated signalling + * frequencyDomainResources: BIT STRING (SIZE (45)) + * Corresponds to L1 parameter 'CORESET-freq-dom'(see 38.211, section 7.3.2.2) + * Frequency domain resources for the CORESET. Each bit corresponds a group of 6 RBs, with grouping starting from PRB 0, + * which is fully contained in the bandwidth part within which the CORESET is configured. + * duration: INTEGER (1..maxCoReSetDuration) + * Corresponds to L1 parameter 'CORESET-time-duration' (see 38.211, section 7.3.2.2FFS_Section) + * Contiguous time duration of the CORESET in number of symbols + * cce-REG-MappingType: interleaved + * reg-BundleSize: ENUMERATED {n2, n3, n6} + * interleaverSize: ENUMERATED {n2, n3, n6} + * shiftIndex: INTEGER + * nonInterleaved NULL + * precoderGranularity: ENUMERATED {sameAsREG-bundle, allContiguousRBs} + * Corresponds to L1 parameter 'CORESET-precoder-granuality' (see 38.211, sections 7.3.2.2 and 7.4.1.3.2) + * tci-StatesPDCCH: SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL + * A subset of the TCI states defined in TCI-States used for providing QCL relationships between the DL RS(s) + * in one RS Set (TCI-State) and the PDCCH DMRS ports. + * Corresponds to L1 parameter 'TCI-StatesPDCCH' (see 38.214, section FFS_Section) + * tci-PresentInDCI: ENUMERATED {enabled} OPTIONAL + * Corresponds to L1 parameter 'TCI-PresentInDCI' (see 38,213, section 5.1.5) + * pdcch-DMRS-ScramblingID: BIT STRING (SIZE (16)) OPTIONAL + * PDCCH DMRS scrambling initalization. + * Corresponds to L1 parameter 'PDCCH-DMRS-Scrambling-ID' (see 38.214, section 5.1) + * When the field is absent the UE applies the value '0'. */ int controlResourceSetId; uint64_t frequencyDomainResources; @@ -762,21 +743,21 @@ typedef enum {uformat0_0_and_1_0=0,uformat0_1_and_1_1=1} NR_UE_SEARCHSPACE_USS_D // Corresponds to L1 parameter 'SRS-Num-PDCCH-cand' (see 38.212, 38.213, section 7.3.1, 11.3) typedef enum {mp1=1,mp2=2,mp4=4,mp5=5,mp8=8,mp10=10,mp16=16,mp20=20} NR_UE_SEARCHSPACE_MON_PERIOD_t; //typedef enum {n1=1,n2=2} NR_UE_SEARCHSPACE_nbrCAND_2_3_t; - // The number of PDCCH candidates for DCI format 2-3 for the configured aggregation level. - // Corresponds to L1 parameter 'SRS-Num-PDCCH-cand' (see 38.212, 38.213, section 7.3.1, 11.3) +// The number of PDCCH candidates for DCI format 2-3 for the configured aggregation level. +// Corresponds to L1 parameter 'SRS-Num-PDCCH-cand' (see 38.212, 38.213, section 7.3.1, 11.3) typedef enum {common=0,ue_specific=1} NR_SEARCHSPACE_TYPE_t; typedef struct { -/* - * searchSpaceType: Indicates whether this is a common search space (present) or a UE specific search space (CHOICE) - * as well as DCI formats to monitor for (description in struct NR_UE_PDCCH_SEARCHSPACE_TYPE - * common: Configures this search space as common search space (CSS) and DCI formats to monitor - * ue-Specific: Configures this search space as UE specific search space (USS) - * The UE monitors the DCI format with CRC scrambled by - * C-RNTI, CS-RNTI (if configured), TC-RNTI (if a certain condition is met), - * and SP-CSI-RNTI (if configured) - */ + /* + * searchSpaceType: Indicates whether this is a common search space (present) or a UE specific search space (CHOICE) + * as well as DCI formats to monitor for (description in struct NR_UE_PDCCH_SEARCHSPACE_TYPE + * common: Configures this search space as common search space (CSS) and DCI formats to monitor + * ue-Specific: Configures this search space as UE specific search space (USS) + * The UE monitors the DCI format with CRC scrambled by + * C-RNTI, CS-RNTI (if configured), TC-RNTI (if a certain condition is met), + * and SP-CSI-RNTI (if configured) + */ NR_SEARCHSPACE_TYPE_t type; NR_UE_SEARCHSPACE_CSS_DCI_FORMAT_t common_dci_formats; @@ -793,32 +774,32 @@ typedef struct { } NR_UE_PDCCH_SEARCHSPACE_TYPE; typedef struct { -/* - * define SearchSpace structure according to 38.331 - * - * searchSpaceId: Identity of the search space. SearchSpaceId = 0 identifies the SearchSpace configured via PBCH (MIB) - * The searchSpaceId is unique among the BWPs of a Serving Cell - * controlResourceSetId: CORESET applicable for this SearchSpace - * 0 identifies the common CORESET configured in MIB - * 1..maxNrofControlResourceSets-1 identify CORESETs configured by dedicated signalling - * monitoringSlotPeriodicityAndOffset: - * Slots for PDCCH Monitoring configured as periodicity and offset. - * Corresponds to L1 parameters 'Montoring-periodicity-PDCCH-slot' and - * 'Montoring-offset-PDCCH-slot' (see 38.213, section 10) - * monitoringSymbolsWithinSlot: - * Symbols for PDCCH monitoring in the slots configured for PDCCH monitoring - * The most significant (left) bit represents the first OFDM in a slot - * - * nrofCandidates: Number of PDCCH candidates per aggregation level - * - * searchSpaceType: Indicates whether this is a common search space (present) or a UE specific search space - * as well as DCI formats to monitor for (description in struct NR_UE_PDCCH_SEARCHSPACE_TYPE - * common: Configures this search space as common search space (CSS) and DCI formats to monitor - * ue-Specific: Configures this search space as UE specific search space (USS) - * The UE monitors the DCI format with CRC scrambled by - * C-RNTI, CS-RNTI (if configured), TC-RNTI (if a certain condition is met), - * and SP-CSI-RNTI (if configured) - */ + /* + * define SearchSpace structure according to 38.331 + * + * searchSpaceId: Identity of the search space. SearchSpaceId = 0 identifies the SearchSpace configured via PBCH (MIB) + * The searchSpaceId is unique among the BWPs of a Serving Cell + * controlResourceSetId: CORESET applicable for this SearchSpace + * 0 identifies the common CORESET configured in MIB + * 1..maxNrofControlResourceSets-1 identify CORESETs configured by dedicated signalling + * monitoringSlotPeriodicityAndOffset: + * Slots for PDCCH Monitoring configured as periodicity and offset. + * Corresponds to L1 parameters 'Montoring-periodicity-PDCCH-slot' and + * 'Montoring-offset-PDCCH-slot' (see 38.213, section 10) + * monitoringSymbolsWithinSlot: + * Symbols for PDCCH monitoring in the slots configured for PDCCH monitoring + * The most significant (left) bit represents the first OFDM in a slot + * + * nrofCandidates: Number of PDCCH candidates per aggregation level + * + * searchSpaceType: Indicates whether this is a common search space (present) or a UE specific search space + * as well as DCI formats to monitor for (description in struct NR_UE_PDCCH_SEARCHSPACE_TYPE + * common: Configures this search space as common search space (CSS) and DCI formats to monitor + * ue-Specific: Configures this search space as UE specific search space (USS) + * The UE monitors the DCI format with CRC scrambled by + * C-RNTI, CS-RNTI (if configured), TC-RNTI (if a certain condition is met), + * and SP-CSI-RNTI (if configured) + */ // INTEGER (0..maxNrofSearchSpaces-1) (0..40-1) int searchSpaceId; int controlResourceSetId; @@ -892,18 +873,17 @@ typedef struct { //Check for specific DCIFormat and AgregationLevel uint8_t dciFormat; uint8_t agregationLevel; - t_nrPolar_paramsPtr nrPolar_params; - #ifdef NR_PDCCH_DEFS_NR_UE +#ifdef NR_PDCCH_DEFS_NR_UE int nb_searchSpaces; // CORESET structure, where maximum number of CORESETs to be handled is 3 (according to 38.331 V15.1.0) NR_UE_PDCCH_CORESET coreset[NR_NBR_CORESET_ACT_BWP]; // SEARCHSPACE structure, where maximum number of SEARCHSPACEs to be handled is 10 (according to 38.331 V15.1.0) - // Each SearchSpace is associated with one ControlResourceSet + // Each SearchSpace is associated with one ControlResourceSet NR_UE_PDCCH_SEARCHSPACE searchSpace[NR_NBR_SEARCHSPACE_ACT_BWP]; int n_RB_BWP[NR_NBR_SEARCHSPACE_ACT_BWP]; uint32_t nb_search_space; - #endif +#endif } NR_UE_PDCCH; #define PBCH_A 24 @@ -933,8 +913,6 @@ typedef struct { /// \brief Pointer to PBCH decoded output. /// - first index: ? [0..63] (hard coded) uint8_t *decoded_output; - /// polar decoder parameters - t_nrPolar_paramsPtr nrPolar_params; /// \brief Total number of PDU errors. uint32_t pdu_errors; /// \brief Total number of PDU errors 128 frames ago. @@ -951,6 +929,16 @@ typedef struct { int16_t *prach; } NR_UE_PRACH; +// structure used for multiple SSB detection +typedef struct NR_UE_SSB { + uint8_t i_ssb; // i_ssb between 0 and 7 (it corresponds to ssb_index only for Lmax=4,8) + uint8_t n_hf; // n_hf = 0,1 for Lmax =4 or n_hf = 0 for Lmax =8,64 + uint32_t metric; // metric to order SSB hypothesis + uint32_t c_re; + uint32_t c_im; + struct NR_UE_SSB *next_ssb; +} NR_UE_SSB; + /*typedef enum { /// do not detect any DCIs in the current subframe NO_DCI = 0x0, @@ -983,6 +971,8 @@ typedef struct { int UE_scan; /// \brief Indicator that UE should perform coarse scanning around carrier int UE_scan_carrier; + /// \brief Indicator that UE should enable estimation and compensation of frequency offset + int UE_fo_compensation; /// \brief Indicator that UE is synchronized to an eNB int is_synchronized; /// Data structure for UE process scheduling @@ -1019,18 +1009,20 @@ typedef struct { NR_UE_COMMON common_vars; nr_ue_if_module_t *if_inst; + nr_downlink_indication_t dl_indication; nr_uplink_indication_t ul_indication; /// UE FAPI DCI request nr_dcireq_t dcireq; + // CHECK if we need those as they are also included in dl_indictation /// UE FAPI indication for DLSCH reception fapi_nr_rx_indication_t rx_ind; /// UE FAPI indication for DCI reception fapi_nr_dci_indication_t dci_ind; // point to the current rxTx thread index - uint8_t current_thread_id[10]; + uint8_t current_thread_id[40]; NR_UE_PDSCH *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads NR_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; @@ -1041,8 +1033,8 @@ 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_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][2]; // two RxTx Threads - NR_UE_ULSCH_t *ulsch[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]; NR_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX]; NR_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_eNB_MAX]; @@ -1076,7 +1068,7 @@ typedef struct { uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD]; /// PDSCH DMRS - uint32_t nr_gold_pdsch[2][20][2][21]; + uint32_t nr_gold_pdsch[2][20][2][52]; /// PDCCH DMRS uint32_t nr_gold_pdcch[7][20][3][52]; @@ -1140,6 +1132,7 @@ typedef struct { uint8_t decode_MIB; /// temporary offset during cell search prior to MIB decoding int ssb_offset; + uint16_t symbol_offset; // offset in terms of symbols for detected ssb in sync int rx_offset; /// Timing offset int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP int time_sync_cell; @@ -1188,7 +1181,7 @@ typedef struct { PUCCH_CONFIG_DEDICATED pucch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; -//#if defined(UPGRADE_RAT_NR) + //#if defined(UPGRADE_RAT_NR) #if 1 SystemInformationBlockType1_nr_t systemInformationBlockType1_nr; @@ -1230,7 +1223,7 @@ typedef struct { /// Scheduling Request Config SCHEDULING_REQUEST_CONFIG scheduling_request_config[NUMBER_OF_CONNECTED_eNB_MAX]; -//#if defined(UPGRADE_RAT_NR) + //#if defined(UPGRADE_RAT_NR) #if 1 scheduling_request_config_t scheduling_request_config_nr[NUMBER_OF_CONNECTED_eNB_MAX]; @@ -1304,6 +1297,7 @@ typedef struct { } PHY_VARS_NR_UE; + /* this structure is used to pass both UE phy vars and * proc to the function UE_thread_rxn_txnp4 */ diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 58a8833b18..a589f555ff 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -87,10 +87,10 @@ #define NR_MAX_CSET_DURATION 3 #define NR_MAX_NB_RBG 18 -#define NR_MAX_NB_LAYERS 8 +#define NR_MAX_NB_LAYERS 8 // SU-MIMO (3GPP TS 38.211 V15.4.0 section 7.3.1.3) #define NR_MAX_NB_CODEWORDS 2 #define NR_MAX_NB_HARQ_PROCESSES 16 -#define NR_MAX_PDSCH_ENCODED_LENGTH 950984 +#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_PDSCH_TBS 3824 typedef enum { @@ -303,11 +303,15 @@ typedef struct NR_DL_FRAME_PARMS { /// TDD configuration uint16_t tdd_uplink_nr[2*NR_MAX_SLOTS_PER_FRAME]; /* this is a bitmap of symbol of each slot given for 2 frames */ - //SSB related params + //SSB related params /// Start in Subcarrier index of the SSB block uint16_t ssb_start_subcarrier; /// SSB type nr_ssb_type_e ssb_type; + /// Max number of SSB in frame + uint8_t Lmax; + /// SS block pattern (max 64 ssb, each bit is on/off ssb) + uint64_t L_ssb; /// PBCH polar encoder params t_nrPolar_params pbch_polar_params; @@ -317,5 +321,23 @@ typedef struct NR_DL_FRAME_PARMS { } NR_DL_FRAME_PARMS; +#define KHz (1000UL) +#define MHz (1000*KHz) + +typedef struct nr_bandentry_s { + int16_t band; + uint64_t ul_min; + uint64_t ul_max; + uint64_t dl_min; + uint64_t dl_max; + uint64_t N_OFFs_DL; + uint64_t step_size; +} nr_bandentry_t; + +typedef struct nr_band_info_s { + int nbands; + nr_bandentry_t band_info[100]; +} nr_band_info_t; + #endif diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h index ae17c48533..05e14f5e8d 100644 --- a/openair1/PHY/impl_defs_nr.h +++ b/openair1/PHY/impl_defs_nr.h @@ -736,7 +736,7 @@ typedef struct { -- Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) hoppingId BIT STRING (SIZE (10)) OPTIONAL, -- Need R */ - uint16_t hoppingId; + uint32_t hoppingId; /* -- Power control parameter P0 for PUCCH transmissions. Value in dBm. Only even values (step size 2) allowed. -- Corresponds to L1 parameter 'p0-nominal-pucch' (see 38.213, section 7.2) diff --git a/openair1/PHY/sse_intrin.h b/openair1/PHY/sse_intrin.h index da4d1db846..9995909acc 100644 --- a/openair1/PHY/sse_intrin.h +++ b/openair1/PHY/sse_intrin.h @@ -26,11 +26,11 @@ * The host CPU needs to have support for SSE2 at least. SSE3 and SSE4.1 functions are emulated if the CPU lacks support for them. * This will slow down the softmodem, but may be valuable if only offline signal processing is required. * - * \author S. Held - * \email sebastian.held@imst.de - * \company IMST GmbH - * \date 2015 - * \version 0.1 + * \author S. Held, Laurent THOMAS + * \email sebastian.held@imst.de, laurent.thomas@open-cells.com + * \company IMST GmbH, Open Cells Project + * \date 2019 + * \version 0.2 */ #ifndef SSE_INTRIN_H @@ -40,23 +40,23 @@ #if defined(__x86_64) || defined(__i386__) #ifndef __SSE2__ -# error SSE2 processor intrinsics disabled + # error SSE2 processor intrinsics disabled #endif #include #include #ifdef __SSE3__ -# include -# include + #include + #include #endif #ifdef __SSE4_1__ -# include + #include #endif #ifdef __AVX2__ -# include + #include #endif // ------------------------------------------------ @@ -108,8 +108,7 @@ typedef union { * \date 2006-2008 * \copyright Apache License 2.0 */ -static inline __m128i ssp_comge_epi8_SSE2(__m128i a, __m128i b) -{ +static inline __m128i ssp_comge_epi8_SSE2(__m128i a, __m128i b) { __m128i c; c = _mm_cmpgt_epi8( a, b ); a = _mm_cmpeq_epi8( a, b ); @@ -126,13 +125,11 @@ static inline __m128i ssp_comge_epi8_SSE2(__m128i a, __m128i b) * \date 2006-2008 * \copyright Apache License 2.0 */ -static inline __m128i ssp_shuffle_epi8_SSE2 (__m128i a, __m128i mask) -{ +static inline __m128i ssp_shuffle_epi8_SSE2 (__m128i a, __m128i mask) { ssp_m128 A,B, MASK, maskZero; A.i = a; maskZero.i = ssp_comge_epi8_SSE2( mask, _mm_setzero_si128() ); MASK.i = _mm_and_si128 ( mask, _mm_set1_epi8( (char)0x0F) ); - B.s8[ 0] = A.s8[ (MASK.s8[ 0]) ]; B.s8[ 1] = A.s8[ (MASK.s8[ 1]) ]; B.s8[ 2] = A.s8[ (MASK.s8[ 2]) ]; @@ -149,7 +146,6 @@ static inline __m128i ssp_shuffle_epi8_SSE2 (__m128i a, __m128i mask) B.s8[13] = A.s8[ (MASK.s8[13]) ]; B.s8[14] = A.s8[ (MASK.s8[14]) ]; B.s8[15] = A.s8[ (MASK.s8[15]) ]; - B.i = _mm_and_si128( B.i, maskZero.i ); return B.i; } @@ -182,8 +178,7 @@ static inline __m128i ssp_shuffle_epi8_SSE2 (__m128i a, __m128i mask) * \date 2006-2008 * \copyright Apache License 2.0 */ -static inline __m128i ssp_insert_epi8_SSE2( __m128i a, int b, const int ndx ) -{ +static inline __m128i ssp_insert_epi8_SSE2( __m128i a, int b, const int ndx ) { ssp_m128 Ahi, Alo; b = b & 0xFF; /* Convert to 8-bit integer */ Ahi.i = _mm_unpackhi_epi8( a, _mm_setzero_si128() ); /* Ahi = a_8[8:15] Simulate 8bit integers as 16-bit integers */ @@ -191,72 +186,71 @@ static inline __m128i ssp_insert_epi8_SSE2( __m128i a, int b, const int ndx ) /* Insert b as a 16-bit integer to upper or lower half of a */ switch( ndx & 0xF ) { - case 0: - Alo.i = _mm_insert_epi16( Alo.i, b, 0 ); - break; + case 0: + Alo.i = _mm_insert_epi16( Alo.i, b, 0 ); + break; - case 1: - Alo.i = _mm_insert_epi16( Alo.i, b, 1 ); - break; + case 1: + Alo.i = _mm_insert_epi16( Alo.i, b, 1 ); + break; - case 2: - Alo.i = _mm_insert_epi16( Alo.i, b, 2 ); - break; + case 2: + Alo.i = _mm_insert_epi16( Alo.i, b, 2 ); + break; - case 3: - Alo.i = _mm_insert_epi16( Alo.i, b, 3 ); - break; + case 3: + Alo.i = _mm_insert_epi16( Alo.i, b, 3 ); + break; - case 4: - Alo.i = _mm_insert_epi16( Alo.i, b, 4 ); - break; + case 4: + Alo.i = _mm_insert_epi16( Alo.i, b, 4 ); + break; - case 5: - Alo.i = _mm_insert_epi16( Alo.i, b, 5 ); - break; + case 5: + Alo.i = _mm_insert_epi16( Alo.i, b, 5 ); + break; - case 6: - Alo.i = _mm_insert_epi16( Alo.i, b, 6 ); - break; + case 6: + Alo.i = _mm_insert_epi16( Alo.i, b, 6 ); + break; - case 7: - Alo.i = _mm_insert_epi16( Alo.i, b, 7 ); - break; + case 7: + Alo.i = _mm_insert_epi16( Alo.i, b, 7 ); + break; - case 8: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 0 ); - break; + case 8: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 0 ); + break; - case 9: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 1 ); - break; + case 9: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 1 ); + break; - case 10: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 2 ); - break; + case 10: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 2 ); + break; - case 11: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 3 ); - break; + case 11: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 3 ); + break; - case 12: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 4 ); - break; + case 12: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 4 ); + break; - case 13: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 5 ); - break; + case 13: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 5 ); + break; - case 14: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 6 ); - break; + case 14: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 6 ); + break; - default: - Ahi.i = _mm_insert_epi16( Ahi.i, b, 7 ); + default: + Ahi.i = _mm_insert_epi16( Ahi.i, b, 7 ); } return _mm_packus_epi16( Alo.i, Ahi.i ); // Pack the 16-bit integers to 8bit again. - ///* Another implementation, but slower: */ //ssp_m128 A, B, mask; //mask.i = _mm_setzero_si128(); @@ -277,16 +271,13 @@ static inline __m128i ssp_insert_epi8_SSE2( __m128i a, int b, const int ndx ) * \date 2006-2008 * \copyright Apache License 2.0 */ -static inline __m128i ssp_cvtepi8_epi16_SSE2 ( __m128i a) -{ +static inline __m128i ssp_cvtepi8_epi16_SSE2 ( __m128i a) { __m128i b = _mm_setzero_si128 (); __m128i c = _mm_unpacklo_epi8(a, b); __m128i d = _mm_set1_epi16 (128); - b = _mm_and_si128(d, c); d = _mm_set1_epi16(0x1FE); b = _mm_mullo_epi16(b, d); - return _mm_add_epi16(c, b); } @@ -299,8 +290,7 @@ static inline __m128i ssp_cvtepi8_epi16_SSE2 ( __m128i a) * \date 2006-2008 * \copyright Apache License 2.0 */ -static inline __m128i ssp_logical_bitwise_select_SSE2( __m128i a, __m128i b, __m128i mask ) // Bitwise (mask ? a : b) -{ +static inline __m128i ssp_logical_bitwise_select_SSE2( __m128i a, __m128i b, __m128i mask ) { // Bitwise (mask ? a : b) a = _mm_and_si128 ( a, mask ); // clear a where mask = 0 b = _mm_andnot_si128( mask, b ); // clear b where mask = 1 a = _mm_or_si128 ( a, b ); // a = a OR b @@ -316,8 +306,7 @@ static inline __m128i ssp_logical_bitwise_select_SSE2( __m128i a, __m128i b, __m * \date 2006-2008 * \copyright Apache License 2.0 */ -static inline __m128i ssp_max_epi8_SSE2( __m128i a, __m128i b ) -{ +static inline __m128i ssp_max_epi8_SSE2( __m128i a, __m128i b ) { __m128i mask = _mm_cmpgt_epi8( a, b ); // FFFFFFFF where a > b a = ssp_logical_bitwise_select_SSE2( a, b, mask ); return a; @@ -332,15 +321,12 @@ static inline __m128i ssp_max_epi8_SSE2( __m128i a, __m128i b ) * \date 2006-2008 * \copyright Apache License 2.0 */ -static inline __m128i ssp_cvtepi16_epi32_SSE2 ( __m128i a) -{ +static inline __m128i ssp_cvtepi16_epi32_SSE2 ( __m128i a) { __m128i b = _mm_set1_epi32 (-1); //0xFFFFFFFF __m128i c = _mm_unpacklo_epi16(a, b); //FFFFa0**FFFFa1**.... __m128i d = _mm_set1_epi32 (0x8000); //0x8000 - b = _mm_andnot_si128(c, d); // 0x80 for positive, 0x00 for negative d = _mm_slli_epi32(b, 1); // 0x100 for positive, 0x000 for negative - return _mm_add_epi32(c, d); } #endif // __SSE4_1__ @@ -350,5 +336,46 @@ static inline __m128i ssp_cvtepi16_epi32_SSE2 ( __m128i a) #endif // x86_64 || i386 -#endif // SSE_INTRIN_H +#if defined(__x86_64__) || defined(__i386__) + #define vect128 __m128i +#elif defined(__arm__) + #define vect128 int16x8_t +#endif +static const short minusConjug128[8]__attribute__((aligned(16))) = {-1,1,-1,1,-1,1,-1,1}; +static inline vect128 mulByConjugate128(vect128 *a, vect128 *b, int8_t output_shift) { + +#if defined(__x86_64__) || defined(__i386__) + vect128 realPart = _mm_madd_epi16(*a,*b); + realPart = _mm_srai_epi32(realPart,output_shift); + vect128 imagPart = _mm_shufflelo_epi16(*b,_MM_SHUFFLE(2,3,0,1)); + imagPart = _mm_shufflehi_epi16(imagPart,_MM_SHUFFLE(2,3,0,1)); + imagPart = _mm_sign_epi16(imagPart,*(vect128 *)minusConjug128); + imagPart = _mm_madd_epi16(imagPart,*a); + imagPart = _mm_srai_epi32(imagPart,output_shift); + vect128 lowPart = _mm_unpacklo_epi32(realPart,imagPart); + vect128 highPart = _mm_unpackhi_epi32(realPart,imagPart); + return ( _mm_packs_epi32(lowPart,highPart)); +#elif defined(__arm__) + AssertFatal(false, "not developped\n"); +#endif +} + +#if defined(__x86_64__) || defined(__i386__) +#define displaySamples128(vect) {\ + __m128i x=vect; \ + printf("vector: %s = (%hd,%hd) (%hd,%hd) (%hd,%hd) (%hd,%hd)\n", #vect, \ + _mm_extract_epi16(x,0), \ + _mm_extract_epi16(x,1),\ + _mm_extract_epi16(x,2),\ + _mm_extract_epi16(x,3),\ + _mm_extract_epi16(x,4),\ + _mm_extract_epi16(x,5),\ + _mm_extract_epi16(x,6),\ + _mm_extract_epi16(x,7));\ + } +#elif defined(__arm__) + displaySamples128(vect) {} +//TBD +#endif +#endif // SSE_INTRIN_H diff --git a/openair1/SCHED_NR/phy_procedures_nr_common.c b/openair1/SCHED_NR/phy_procedures_nr_common.c old mode 100644 new mode 100755 index 1a0a02f22d..030a3733c2 --- a/openair1/SCHED_NR/phy_procedures_nr_common.c +++ b/openair1/SCHED_NR/phy_procedures_nr_common.c @@ -36,4 +36,6 @@ nr_subframe_t nr_slot_select(nfapi_nr_config_request_t *cfg,unsigned char slot) { if (cfg->subframe_config.duplex_mode.value == FDD) return(SF_DL); + LOG_E(PHY,"Not developped TDD mode\n"); + return -1; } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 7cbb70242e..aeda4b3549 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -30,6 +30,7 @@ #include "SCHED/fapi_l1.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "PHY/INIT/phy_init.h" #include "T.h" @@ -39,7 +40,7 @@ #include #if defined(ENABLE_ITTI) -# include "intertask_interface.h" + #include "intertask_interface.h" #endif extern uint8_t nfapi_mode; @@ -76,133 +77,99 @@ int return_ssb_type(nfapi_config_request_t *cfg) }*/ -// First SSB starting symbol candidate is used and type B is chosen for 30kHz SCS -int nr_get_ssb_start_symbol(nfapi_nr_config_request_t *cfg, NR_DL_FRAME_PARMS *fp) -{ - int mu = cfg->subframe_config.numerology_index_mu.value; - int symbol = 0; - switch(mu) { - case NR_MU_0: - symbol = 2; - break; - - case NR_MU_1: // case B - symbol = 4; - break; - - case NR_MU_3: - symbol = 4; - break; - - case NR_MU_4: - symbol = 8; - break; - - default: - AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu); - } - - if (cfg->sch_config.half_frame_index.value) - symbol += (5 * fp->symbols_per_slot * fp->slots_per_subframe); - - return symbol; -} - -void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_t *cfg, NR_DL_FRAME_PARMS *fp) -{ +void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_t *cfg, NR_DL_FRAME_PARMS *fp) { fp->ssb_start_subcarrier = (12 * cfg->sch_config.n_ssb_crb.value + cfg->sch_config.ssb_subcarrier_offset.value)/(1<subframe_config.numerology_index_mu.value); LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier,cfg->sch_config.n_ssb_crb.value,cfg->sch_config.ssb_subcarrier_offset.value); } void nr_common_signal_procedures (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; int **txdataF = gNB->common_vars.txdataF; uint8_t *pbch_pdu=&gNB->pbch_pdu[0]; - int ss_slot = (cfg->sch_config.half_frame_index.value)? 10 : 0; - uint8_t Lmax, ssb_index=0, n_hf=0; + uint8_t ssb_index, n_hf; + int ssb_start_symbol, rel_slot; + n_hf = cfg->sch_config.half_frame_index.value; + // to set a effective slot number between 0 to 9 in the half frame where the SSB is supposed to be + rel_slot = (n_hf)? (slot-10) : slot; + + LOG_D(PHY,"common_signal_procedures: frame %d, slot %d\n",frame,slot); - int ssb_start_symbol = nr_get_ssb_start_symbol(cfg, fp); - nr_set_ssb_first_subcarrier(cfg, fp); - Lmax = (fp->dl_CarrierFreq < 3e9)? 4:8; + if(rel_slot<10 && rel_slot>=0) { + for (int i=0; i<2; i++) { // max two SSB per frame + + ssb_index = i + 2*rel_slot; // computing the ssb_index + if ((fp->L_ssb >> ssb_index) & 0x01) { // generating the ssb only if the bit of L_ssb at current ssb index is 1 + + int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp, ssb_index, n_hf); // computing the starting symbol for current ssb + ssb_start_symbol = ssb_start_symbol_abs % 14; // start symbol wrt slot + nr_set_ssb_first_subcarrier(cfg, fp); // setting the first subcarrier + + LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol); + nr_generate_pss(gNB->d_pss, txdataF[0], AMP, ssb_start_symbol, cfg, fp); + nr_generate_sss(gNB->d_sss, txdataF[0], AMP, ssb_start_symbol, cfg, fp); - if (slot == ss_slot) - { - // Current implementation is based on SSB in first half frame, first candidate - LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol); + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp); - nr_generate_pss(gNB->d_pss, txdataF[0], AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(gNB->d_sss, txdataF[0], AMP_OVER_2, ssb_start_symbol, cfg, fp); - - if (!(frame&7)){ - LOG_D(PHY,"%d.%d : pbch_configured %d\n",frame,slot,gNB->pbch_configured); - if (gNB->pbch_configured != 1)return; - gNB->pbch_configured = 0; - } - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP_OVER_2, ssb_start_symbol, cfg, fp); - nr_generate_pbch(&gNB->pbch, - gNB->nrPolar_params, + nr_generate_pbch(&gNB->pbch, pbch_pdu, gNB->nr_pbch_interleaver, txdataF[0], - AMP_OVER_2, + AMP, ssb_start_symbol, - n_hf,Lmax,ssb_index, + n_hf,fp->Lmax,ssb_index, frame, cfg, fp); + } + } } - } void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, - gNB_L1_rxtx_proc_t *proc, - int do_meas) -{ + gNB_L1_rxtx_proc_t *proc, + int do_meas) { int aa; int frame=proc->frame_tx; - int slot=proc->slot_tx; uint8_t num_dci=0,num_pdsch_rnti; - NR_DL_FRAME_PARMS *fp=&gNB->frame_parms; nfapi_nr_config_request_t *cfg = &gNB->gNB_config; - int offset = gNB->CC_id; if ((cfg->subframe_config.duplex_mode.value == TDD) && (nr_slot_select(cfg,slot)==SF_UL)) return; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1); + if (do_meas==1) start_meas(&gNB->phy_proc_tx); // clear the transmit data array for the current subframe - for (aa=0; aa<1/*15*/; aa++) { + for (aa=0; aa<1/*15*/; aa++) { memset(gNB->common_vars.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t)); } if (nfapi_mode == 0 || nfapi_mode == 1) { nr_common_signal_procedures(gNB,frame, slot); //if (frame == 9) - //write_output("txdataF.m","txdataF",gNB->common_vars.txdataF[aa],fp->samples_per_frame_wCP, 1, 1); + //write_output("txdataF.m","txdataF",gNB->common_vars.txdataF[aa],fp->samples_per_frame_wCP, 1, 1); } num_dci = gNB->pdcch_vars.num_dci; - num_pdsch_rnti = gNB->pdcch_vars.num_pdsch_rnti; + if (num_dci) { LOG_I(PHY, "[gNB %d] Frame %d slot %d \ Calling nr_generate_dci_top (number of DCI %d)\n", gNB->Mod_id, frame, slot, num_dci); - if (nfapi_mode == 0 || nfapi_mode == 1){ + if (nfapi_mode == 0 || nfapi_mode == 1) { nr_generate_dci_top(gNB->pdcch_vars, - &gNB->nrPolar_params, gNB->nr_gold_pdcch_dmrs[slot], gNB->common_vars.txdataF[0], AMP, *fp, *cfg); + if (num_pdsch_rnti) { LOG_I(PHY, "PDSCH generation started (%d)\n", num_pdsch_rnti); nr_generate_pdsch(*gNB->dlsch[0][0], @@ -213,6 +180,6 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, } } } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0); } diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 9b53dd050c..a120b8c140 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -49,6 +49,9 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* p nr_frequency_range_e freq_range, uint8_t rmsi_pdcch_config, uint8_t ssb_idx, + uint8_t k_ssb, + uint16_t sfn_ssb, + uint8_t n_ssb, uint16_t nb_slots_per_frame, uint16_t N_RB); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 1daaf90cd6..7c17987980 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -48,11 +48,13 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ /// component carrier id 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. - NR_UE_PDCCH *pdcch_vars2 = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[0][0]; - NR_UE_DLSCH_t *dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[0][0][0]; + 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[0]; NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms; PRACH_RESOURCES_t *prach_resources = PHY_vars_UE_g[module_id][cc_id]->prach_resources[0]; @@ -88,8 +90,8 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ pdcch_vars2->coreset[i].cce_reg_mappingType.interleaversize = dci_config->coreset.cce_reg_interleaved_interleaver_size; }else{ //CCE_REG_MAPPING_TYPE_NON_INTERLEAVED pdcch_vars2->coreset[i].cce_reg_mappingType.shiftIndex = 0; - pdcch_vars2->coreset[i].cce_reg_mappingType.reg_bundlesize = 0; - pdcch_vars2->coreset[i].cce_reg_mappingType.interleaversize = 0; + pdcch_vars2->coreset[i].cce_reg_mappingType.reg_bundlesize = 6; + pdcch_vars2->coreset[i].cce_reg_mappingType.interleaversize = 1; } pdcch_vars2->coreset[i].precoderGranularity = dci_config->coreset.precoder_granularity; @@ -230,7 +232,6 @@ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){ printf("half frame bit: %d\n", phy_config->config_req.pbch_config.half_frame_bit); printf("-------------------------------\n"); - PHY_vars_UE_g[0][0]->proc.proc_rxtx[0].frame_rx = phy_config->config_req.pbch_config.system_frame_number; } if(phy_config->config_req.config_mask & FAPI_NR_CONFIG_REQUEST_MASK_DL_BWP_COMMON){ diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 23d828ec93..31dcfcacbe 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -150,7 +150,7 @@ void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_i * *********************************************************************/ -void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_harq_processes_pusch) +void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx, uint8_t number_harq_processes_pusch) { NR_UE_ULSCH_t *ulsch; @@ -160,7 +160,7 @@ void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_h memset(ulsch,0,sizeof(NR_UE_ULSCH_t)); - ue->ulsch[gNB_id] = ulsch; + ue->ulsch[thread_id][gNB_id][code_word_idx] = ulsch; } else { LOG_E(PHY, "Fatal memory allocation problem at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); @@ -185,7 +185,7 @@ void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_h } for (int slot_tx = 0; slot_tx < NR_MAX_SLOTS_PER_FRAME; slot_tx++) { - ue->ulsch[gNB_id]->harq_process_id[slot_tx] = NR_MAX_HARQ_PROCESSES; + ue->ulsch[thread_id][gNB_id][code_word_idx]->harq_process_id[slot_tx] = NR_MAX_HARQ_PROCESSES; } } @@ -202,9 +202,9 @@ void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_h * *********************************************************************/ -void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id) +void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx) { - NR_UE_ULSCH_t *ulsch = ue->ulsch[gNB_id]; + NR_UE_ULSCH_t *ulsch = ue->ulsch[thread_id][gNB_id][code_word_idx]; for (int process_id = 0; process_id < ulsch->number_harq_processes_for_pusch; process_id++) { @@ -215,7 +215,7 @@ void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id) free16(ulsch, sizeof(NR_UE_ULSCH_t)); - ue->ulsch[gNB_id] = NULL; + ue->ulsch[thread_id][gNB_id][code_word_idx] = NULL; } /******************************************************************* diff --git a/openair1/SCHED_NR_UE/harq_nr.h b/openair1/SCHED_NR_UE/harq_nr.h index 2d3e87ddab..ee6e8625b0 100644 --- a/openair1/SCHED_NR_UE/harq_nr.h +++ b/openair1/SCHED_NR_UE/harq_nr.h @@ -83,17 +83,21 @@ void get_dci_info_for_harq(PHY_VARS_NR_UE *ue, NR_DCI_INFO_EXTRACTED_t *nr_dci_i /** \brief This function configures uplink HARQ context @param PHY_VARS_NR_UE ue context @param gNB_id gNodeB identifier + @param thread_id RXTX thread index + @param code_word_idx code word index @param number_harq_processes_pusch maximum number of uplink HARQ processes @returns none */ -void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, uint8_t number_harq_processes_pusch); +void config_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx, uint8_t number_harq_processes_pusch); /** \brief This function releases uplink HARQ context @param PHY_VARS_NR_UE ue context @param gNB_id gNodeB identifier + @param thread_id RXTX thread index + @param code_word_idx code word index @returns none */ -void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id); +void release_uplink_harq_process(PHY_VARS_NR_UE *ue, int gNB_id, int thread_id, int code_word_idx); /** \brief This function stores slot for transmission in HARQ context @param ulsch uplink context diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 5ff6c0d559..e3aa12323e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -56,7 +56,7 @@ //#define DEBUG_PHY_PROC #define NR_PDCCH_SCHED -#define NR_PDCCH_SCHED_DEBUG +//#define NR_PDCCH_SCHED_DEBUG //#define NR_PUCCH_SCHED //#define NR_PUCCH_SCHED_DEBUG @@ -123,7 +123,7 @@ int nr_generate_ue_ul_dlsch_params_from_dci(PHY_VARS_NR_UE *ue, uint8_t eNB_id, int frame, uint8_t nr_tti_rx, - uint32_t dci_pdu[4], + uint64_t dci_pdu[2], uint16_t rnti, uint8_t dci_length, NR_DCI_format_t dci_format, @@ -1595,22 +1595,10 @@ void ue_ulsch_uespec_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8 int harq_pid; int frame_tx=proc->frame_tx; int nr_tti_tx=proc->nr_tti_tx; - int Mod_id = ue->Mod_id; - int CC_id = ue->CC_id; - uint8_t Msg3_flag=0; - uint16_t first_rb, nb_rb; unsigned int input_buffer_length; int i; int aa; int tx_amp; - uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32))); - uint8_t access_mode; - uint8_t Nbundled=0; - uint8_t NbundledCw1=0; - uint8_t ack_status_cw0=0; - uint8_t ack_status_cw1=0; - uint8_t cqi_status = 0; - uint8_t ri_status = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_IN); /* reset harq for tx of current rx slot because it is sure that transmission has already been achieved for this slot */ @@ -1621,6 +1609,18 @@ void ue_ulsch_uespec_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8 #if 0 + int Mod_id = ue->Mod_id; + int CC_id = ue->CC_id; + uint8_t Msg3_flag=0; + uint16_t first_rb, nb_rb; + uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32))); + uint8_t access_mode; + uint8_t Nbundled=0; + uint8_t NbundledCw1=0; + uint8_t ack_status_cw0=0; + uint8_t ack_status_cw1=0; + uint8_t cqi_status = 0; + uint8_t ri_status = 0; if (ue->mac_enabled == 1) { if ((ue->ulsch_Msg3_active[eNB_id] == 1) && (ue->ulsch_Msg3_frame[eNB_id] == frame_tx) && @@ -2760,40 +2760,6 @@ void nr_ue_measurement_procedures( } #endif - // accumulate and filter timing offset estimation every nr_tti_rx (instead of every frame) - if (( slot == 2) && (l==(1-frame_parms->Ncp))) { - - // AGC -/* - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_IN); - -#ifndef OAI_USRP -#ifndef OAI_BLADERF -#ifndef OAI_LMSSDR -#ifndef OAI_ADRV9371_ZC706 - phy_adjust_gain (ue,dB_fixed(ue->measurements.rssi),0); -#endif -#endif -#endif -#endif - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); -*/ - eNB_id = 0; - - - - LOG_D(PHY,"start adjust sync l = %d slot = %d no timing %d\n",l, slot, ue->no_timing_correction); - if (ue->no_timing_correction==0) - nr_adjust_synch_ue(&ue->frame_parms, - ue, - eNB_id, - nr_tti_rx, - 0, - 16384); - - - } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT); } @@ -2972,10 +2938,11 @@ void nr_ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t * VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN); //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, eNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,eNB_id); - ret = nr_rx_pbch(ue, proc, + ret = nr_rx_pbch(ue, proc->subframe_rx, ue->pbch_vars[eNB_id], &ue->frame_parms, eNB_id, + ue->rx_ind.rx_indication_body[0].mib_pdu.ssb_index, SISO, ue->high_speed_flag); @@ -3082,12 +3049,14 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, // Higher layers have updated the number of searchSpaces with are active in the current slot and this value is stored in variable nb_searchspace_total int nb_searchspace_total = pdcch_vars2->nb_search_space; + pdcch_vars[eNB_id]->crnti = 0x1234; //to be check how to set when using loop memory + uint16_t c_rnti=pdcch_vars[eNB_id]->crnti; - uint16_t cs_rnti,new_rnti,tc_rnti; + uint16_t cs_rnti=0,new_rnti=0,tc_rnti; uint16_t p_rnti=P_RNTI; uint16_t si_rnti=SI_RNTI; uint16_t ra_rnti=99; - uint16_t sp_csi_rnti,sfi_rnti,int_rnti,tpc_pusch_rnti,tpc_pucch_rnti,tpc_srs_rnti; //FIXME + uint16_t sp_csi_rnti=0,sfi_rnti=0,int_rnti=0,tpc_pusch_rnti=0,tpc_pucch_rnti=0,tpc_srs_rnti=0; //FIXME uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES] = {c_rnti,cs_rnti,new_rnti,tc_rnti,p_rnti,si_rnti,ra_rnti,sp_csi_rnti,sfi_rnti,int_rnti,tpc_pusch_rnti,tpc_pucch_rnti,tpc_srs_rnti}; #ifdef NR_PDCCH_SCHED_DEBUG @@ -3157,7 +3126,7 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, // FIXME! A table of five enum elements // searchSpaceType indicates whether this is a common search space or a UE-specific search space //int searchSpaceType = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceType.type; - NR_SEARCHSPACE_TYPE_t searchSpaceType = common; + NR_SEARCHSPACE_TYPE_t searchSpaceType = ue_specific;//common; #ifdef NR_PDCCH_SCHED_DEBUG printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> searchSpaceType=%d is hardcoded THIS HAS TO BE FIXED!!!\n", searchSpaceType); @@ -3356,7 +3325,7 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, } // end for loop dci_cnt // TODO: check where should we send up this message. - ue->if_inst->dl_indication(&ue->dl_indication); + //ue->if_inst->dl_indication(&ue->dl_indication); #if UE_TIMING_TRACE @@ -3366,7 +3335,7 @@ int nr_ue_pdcch_procedures(uint8_t eNB_id, } // end for loop nb_searchspace_active - return(0); + return(dci_cnt); } #endif // NR_PDCCH_SCHED @@ -4968,96 +4937,22 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, int frame_rx = proc->frame_rx; int nr_tti_rx = proc->nr_tti_rx; + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][0]; uint16_t nb_symb_sch = 8; // to be updated by higher layer - uint8_t nb_symb_pdcch =2; - //proc->decoder_switch = 0; - //int counter_decoder = 0; + uint8_t nb_symb_pdcch = pdcch_vars->coreset[0].duration; + uint8_t dci_cnt = 0; - LOG_D(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); + LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx%1024, nr_tti_rx); uint8_t next1_thread_id = ue->current_thread_id[nr_tti_rx]== (RX_NB_TH-1) ? 0:(ue->current_thread_id[nr_tti_rx]+1); uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1); -#if 0 - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); - -#if T_TRACER - T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx)); - - T(T_UE_PHY_INPUT_SIGNAL, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_tti_rx), T_INT(0), - T_BUFFER(&ue->common_vars.rxdata[0][nr_tti_rx*ue->frame_parms.samples_per_subframe], - ue->frame_parms.samples_per_subframe * 4)); -#endif - - // start timers - //#ifdef UE_DEBUG_TRACE - LOG_I(PHY," ****** start RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_tti_rx); - //#endif - -#if UE_TIMING_TRACE - start_meas(&ue->phy_proc_rx[ue->current_thread_id[nr_tti_rx]]); - start_meas(&ue->generic_stat); -#endif - - if (do_pdcch_flag) { - // deactivate reception until we scan pdcch - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]) - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active = 0; - if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]) - ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][1]->active = 0; - - if (ue->dlsch_SI[eNB_id]) - ue->dlsch_SI[eNB_id]->active = 0; - if (ue->dlsch_p[eNB_id]) - ue->dlsch_p[eNB_id]->active = 0; - if (ue->dlsch_ra[eNB_id]) - ue->dlsch_ra[eNB_id]->active = 0; - } - -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[%s %d] Frame %d nr_tti_rx %d: Doing phy_procedures_UE_RX\n", - (r_type == multicast_relay) ? "RN/UE" : "UE", - ue->Mod_id,frame_rx, nr_tti_rx); -#endif - - - if (ue->frame_parms.Ncp == 0) { // normal prefix - pilot1 = 4; - } else { // extended prefix - pilot1 = 3; - } - - /* - if (nr_subframe_select(&ue->frame_parms,nr_tti_rx) == SF_S) { // S-subframe, do first 5 symbols only - l2 = 5; - } else */ - { // normal nr_tti_rx, last symbol to be processed is the first of the second slot - l2 = (ue->frame_parms.symbols_per_tti/2)-1; - } - - int prev_nr_tti_rx = (nr_tti_rx - 1)<0? 9: (nr_tti_rx - 1);/* - if (nr_subframe_select(&ue->frame_parms,prev_nr_tti_rx) != SF_DL) { - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // RX processing of symbols l=0...l2 - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - l=0; - } else */ - { - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - // RX processing of symbols l=1...l2 (l=0 is done in last scheduling epoch) - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - l=1; - } - - LOG_D(PHY," ------ slot 0 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); -#endif - #ifdef NR_PDCCH_SCHED - //nr_gold_pdcch(ue,0, 2); + nr_gold_pdcch(ue,0, 2); - if (nr_tti_rx==1){ - for (uint16_t l=0; l PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + for (uint16_t l=0; lofdm_demod_stats); @@ -5068,7 +4963,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_tti_rx, 0, 0, - 1, NR_PDCCH_EST); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE @@ -5076,30 +4970,43 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, #endif //printf("phy procedure pdcch start measurement l =%d\n",l); - nr_ue_measurement_procedures(l,ue,proc,eNB_id,(nr_tti_rx<<1),mode); + //nr_ue_measurement_procedures(l,ue,proc,eNB_id,(nr_tti_rx),mode); } - if (nr_ue_pdcch_procedures(eNB_id,ue,proc) == -1) { - LOG_E(PHY,"[UE %d] Frame %d, nr_tti_rx %d: Error in pdcch procedures\n",ue->Mod_id,frame_rx,nr_tti_rx); - return(-1); + dci_cnt = nr_ue_pdcch_procedures(eNB_id,ue,proc); + + if (dci_cnt > 0) { + + LOG_I(PHY,"[UE %d] Frame %d, nr_tti_rx %d: found %d DCIs\n",ue->Mod_id,frame_rx,nr_tti_rx,dci_cnt); + + if (0/*ue->no_timing_correction==0*/) { + LOG_I(PHY,"start adjust sync slot = %d no timing %d\n", nr_tti_rx, ue->no_timing_correction); + nr_adjust_synch_ue(&ue->frame_parms, + ue, + eNB_id, + nr_tti_rx, + 0, + 16384); + } + } + else { + LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: No DCIs found\n",ue->Mod_id,frame_rx,nr_tti_rx); } - } #endif //NR_PDCCH_SCHED - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); if (nr_tti_rx==1){ + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); //to update from pdsch config nr_gold_pdsch(ue,nb_symb_pdcch,0, 1); for (uint16_t m=nb_symb_pdcch;m<=(nb_symb_sch+nb_symb_pdcch-1) ; m++){ nr_slot_fep(ue, m, //to be updated from higher layer - nr_tti_rx<<1, + nr_tti_rx, 0, 0, - 1, NR_PDSCH_EST); //printf("phy procedure pdsch start measurement\n"); @@ -5130,7 +5037,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT); } - LOG_D(PHY," ------ end PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); // do procedures for SI-RNTI if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN); @@ -5172,76 +5078,37 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ue->frame_parms.symbols_per_tti>>1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); } -//#if 0 - LOG_D(PHY," ------ slot 1 Processing: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - LOG_D(PHY," ------ --> FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - /*if (nr_subframe_select(&ue->frame_parms,nr_tti_rx) != SF_S)*/ - { // do front-end processing for second slot, and first symbol of next nr_tti_rx - for (l=1; lframe_parms.symbols_per_tti>>1; l++) { -#if UE_TIMING_TRACE - start_meas(&ue->ofdm_demod_stats); -#endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); - /*nr_slot_fep(ue, - l, - 1+(nr_tti_rx<<1), - 0, - 0, - 0, - NR_PDSCH_EST);*/ - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); -#if UE_TIMING_TRACE - stop_meas(&ue->ofdm_demod_stats); -#endif - - - //ue_measurement_procedures(l-1,ue,proc,eNB_id,1+(nr_tti_rx<<1),abstraction_flag,mode); - - } // for l=1..l2 - - // do first symbol of next downlink nr_tti_rx for channel estimation - //int next_nr_tti_rx = (1+nr_tti_rx)%10; - /* if (nr_subframe_select(&ue->frame_parms,next_nr_tti_rx) != SF_UL)*/ - { - /*nr_slot_fep(ue, - 0, - (next_nr_tti_rx<<1), - 0, - 0, - 0, - NR_PDSCH_EST);*/ - } - } // not an S-subframe -#if UE_TIMING_TRACE - stop_meas(&ue->generic_stat); -#if DISABLE_LOG_X - printf("[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#else - LOG_D(PHY, "[SFN %d] Slot1: FFT + Channel Estimate + Pdsch Proc Slot0 %5.2f \n",nr_tti_rx,ue->generic_stat.p_time/(cpuf*1000.0)); -#endif - -#endif - - //LOG_D(PHY," ------ end FFT/ChannelEst/PDCCH slot 1: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); if ( (nr_tti_rx == 0) && (ue->decode_MIB == 1)) { - for (int i=0; i<3; i++) + LOG_D(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + + uint8_t i_ssb = ue->rx_ind.rx_indication_body[0].mib_pdu.ssb_index; + uint8_t n_hf = (((ue->rx_ind.rx_indication_body[0].mib_pdu.additional_bits)>>4)&0x01); + + for (int i=1; i<4; i++) { nr_slot_fep(ue, - (5+i), //mu=1 case B + (ue->symbol_offset+i), //mu=1 case B nr_tti_rx, 0, 0, - 1, NR_PBCH_EST); + +#if UE_TIMING_TRACE + start_meas(&ue->dlsch_channel_estimation_stats); +#endif + nr_pbch_channel_estimation(ue,0,0,ue->symbol_offset+i,i-1,i_ssb,n_hf); +#if UE_TIMING_TRACE + stop_meas(&ue->dlsch_channel_estimation_stats); +#endif + } nr_ue_pbch_procedures(eNB_id,ue,proc,0); } // do procedures for C-RNTI - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR slot 0: AbsSubframe %d.%d ------ \n", frame_rx%1024, nr_tti_rx); if (ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->active == 1) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_IN); diff --git a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c b/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c index 4541c7fdc6..f0005f25b1 100644 --- a/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_power_control_ue_nr.c @@ -32,6 +32,7 @@ #include "PHY/defs_nr_UE.h" #include "SCHED_NR_UE/pucch_uci_ue_nr.h" #include "SCHED_NR_UE/pucch_power_control_ue_nr.h" +#include int16_t get_PL(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 5c80040e2b..161ee0b57c 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -36,7 +36,8 @@ #include "PHY/NR_REFSIG/ss_pbch_nr.h" #include "PHY/defs_nr_UE.h" -//#include "PHY/NR_UE_TRANSPORT/pucch_nr.h" +#include +#include #ifndef NO_RAT_NR @@ -229,7 +230,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ /* Part - III */ /* Choice PUCCH format and its related parameters */ pucch_format_nr_t format = pucch_format0_nr; - uint8_t starting_symbol_index; + uint8_t starting_symbol_index=0; uint8_t nb_symbols_total = 0; uint8_t nb_symbols = 0; uint16_t starting_prb = 0;; /* it can be considered as first hop on case of pucch hopping */ @@ -510,7 +511,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ nr_generate_pucch0(ue, ue->common_vars.txdataF, &ue->frame_parms, - &ue->pucch_config_dedicated_nr[gNB_id], + &ue->pucch_config_dedicated[gNB_id], tx_amp, nr_tti_tx, (uint8_t)m_0, @@ -525,7 +526,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ nr_generate_pucch1(ue, ue->common_vars.txdataF, &ue->frame_parms, - &ue->pucch_config_dedicated_nr[gNB_id], + &ue->pucch_config_dedicated[gNB_id], pucch_payload, tx_amp, nr_tti_tx, @@ -544,7 +545,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti, ue->common_vars.txdataF, &ue->frame_parms, - &ue->pucch_config_dedicated_nr[gNB_id], + &ue->pucch_config_dedicated[gNB_id], pucch_payload, tx_amp, nr_tti_tx, @@ -563,7 +564,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ ue->common_vars.txdataF, &ue->frame_parms, format, - &ue->pucch_config_dedicated_nr[gNB_id], + &ue->pucch_config_dedicated[gNB_id], pucch_payload, tx_amp, nr_tti_tx, @@ -682,7 +683,7 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t } } if (do_reset == TRUE) { - init_downlink_harq_status(&ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->harq_processes[dl_harq_pid]); + init_downlink_harq_status(ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][code_word]->harq_processes[dl_harq_pid]); } } } diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index 3ace8ee79a..3b24814951 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -36,7 +36,7 @@ #include "PHY/defs_UE.h" #include "PHY/phy_extern_ue.h" #include -#include "targets/RT/USER/lte-softmodem.h" +#include "executables/nr-uesoftmodem.h" #include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h" #include "SCHED_UE/sched_UE.h" @@ -322,10 +322,10 @@ void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) // if contention resolution fails, go back to PRACH PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PRACH; - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti_is_temporary = 0; - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti = 0; - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti_is_temporary = 0; - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti = 0; + for (int i=0; i pdcch_vars[i][eNB_index]->crnti_is_temporary = 0; + PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[i][eNB_index]->crnti = 0; + } LOG_E(PHY,"[UE %d] Random-access procedure fails, going back to PRACH, setting SIStatus = 0, discard temporary C-RNTI and State RRC_IDLE\n",Mod_id); } @@ -336,16 +336,18 @@ void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) LOG_I(PHY,"[UE %d][RAPROC] Random-access procedure succeeded. Set C-RNTI = Temporary C-RNTI\n",Mod_id); - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti_is_temporary = 0; - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti_is_temporary = 0; + for (int i=0; i pdcch_vars[i][eNB_index]->crnti_is_temporary = 0; + } PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0; PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH; for (i=0; i<8; i++) { if (PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]) { PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->status=SCH_IDLE; - PHY_vars_UE_g[Mod_id][CC_id]->dlsch[0][eNB_index][0]->harq_processes[i]->round=0; - PHY_vars_UE_g[Mod_id][CC_id]->dlsch[1][eNB_index][0]->harq_processes[i]->round=0; + for (int i=0; i dlsch[i][eNB_index][0]->harq_processes[i]->round=0; + } PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->subframe_scheduling_flag=0; } } @@ -2885,10 +2887,10 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint { ue->dlsch[th_id][eNB_id][0]->g_pucch += delta_pucch; } - LOG_D(PHY,"update TPC for PUCCH %d.%d / pid %d delta_PUCCH %d g_pucch %d %d \n",frame_rx, subframe_rx,ue->dlsch[ue->current_thread_id[subframe_rx]][eNB_id][0]->current_harq_pid, + LOG_D(PHY,"update TPC for PUCCH %d.%d / pid %d delta_PUCCH %d g_pucch %d\n", + frame_rx, subframe_rx,ue->dlsch[ue->current_thread_id[subframe_rx]][eNB_id][0]->current_harq_pid, delta_pucch, - ue->dlsch[0][eNB_id][0]->g_pucch, - ue->dlsch[1][eNB_id][0]->g_pucch + ue->dlsch[0][eNB_id][0]->g_pucch //ue->dlsch[2][eNB_id][0]->g_pucch ); } @@ -5114,13 +5116,13 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u if (msg_p != NULL) { switch (ITTI_MSG_ID(msg_p)) { case PHY_FIND_CELL_REQ: - LOG_I(PHY, "[UE %d] Received %s\n", ITTI_MSG_INSTANCE (msg_p) - NB_eNB_INST, ITTI_MSG_NAME (msg_p)); + LOG_I(PHY, "[UE ] Received %s\n", ITTI_MSG_NAME (msg_p)); /* TODO process the message */ break; default: - LOG_E(PHY, "[UE %d] Received unexpected message %s\n", ITTI_MSG_INSTANCE (msg_p) - NB_eNB_INST, ITTI_MSG_NAME (msg_p)); + LOG_E(PHY, "[UE %d] Received unexpected message %s\n", ITTI_MSG_INSTANCE (msg_p) , ITTI_MSG_NAME (msg_p)); break; } diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index c648d19264..1404fb79f4 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -144,8 +144,9 @@ int main(int argc, char **argv) { //char input_val_str[50],input_val_str2[50]; //uint16_t NB_RB=25; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; - uint8_t N_RB_DL = 106, mu = 1; - unsigned char frame_type = 0, pbch_phase = 0; + uint16_t N_RB_DL = 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; @@ -159,7 +160,7 @@ int main(int argc, char **argv) { //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; uint8_t Imcs = 9; @@ -173,7 +174,7 @@ int main(int argc, char **argv) { //logInit(); randominit(0); - while ((c = getopt(argc, argv, "df:hpg:i:j:n:l:m:r:s:S:y:z:N:F:R:P:")) != -1) { + 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; @@ -284,6 +285,10 @@ int main(int argc, char **argv) { break; + case 'M': + SSB_positions = atoi(optarg); + break; + case 'N': Nid_cell = atoi(optarg); break; @@ -340,8 +345,9 @@ int main(int argc, char **argv) { 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 interfering eNB (in dB) - cell_id mod 3 = 1\n"); - printf("-j Relative strength of second interfering eNB (in dB) - cell_id mod 3 = 2\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"); @@ -361,9 +367,10 @@ int main(int argc, char **argv) { 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); + 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"); @@ -379,8 +386,9 @@ int main(int argc, char **argv) { frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; frame_parms->N_RB_DL = N_RB_DL; + frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; crcTableInit(); - nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell); + 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; @@ -401,7 +409,7 @@ int main(int argc, char **argv) { 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)); + bzero(r_re[i], frame_length_complex_samples * sizeof(int)); // [hna] r_re should be txdata } if (pbch_file_fd != NULL) { @@ -477,7 +485,7 @@ int main(int argc, char **argv) { rel15->nb_layers = Nl; rel15->nb_re_dmrs = nb_re_dmrs; rel15->transport_block_size = TBS; - double *modulated_input = malloc16(sizeof(double) * 16 * 68 * 384); + 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); double errors_bit_uncoded = 0; @@ -485,7 +493,10 @@ int main(int argc, char **argv) { unsigned char *estimated_output_bit = malloc16(sizeof(unsigned char) * 16 * 68 * 384); unsigned char *test_input_bit = malloc16(sizeof(unsigned char) * 16 * 68 * 384); unsigned int errors_bit = 0; - NR_UE_DLSCH_t *dlsch0_ue = UE->dlsch[UE->current_thread_id[subframe]][0][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); + NR_UE_DLSCH_t *dlsch0_ue = UE->dlsch[0][0][0]; NR_DL_UE_HARQ_t *harq_process = dlsch0_ue->harq_processes[harq_pid]; harq_process->mcs = Imcs; harq_process->Nl = Nl; @@ -595,8 +606,10 @@ int main(int argc, char **argv) { (float) n_errors / (float) n_trials, (float) n_false_positive / (float) n_trials); - if ((float) n_errors / (float) n_trials < target_error_rate) - break; + if ((float) n_errors / (float) n_trials < target_error_rate) { + printf("PDSCH test OK\n"); + break; + } } /*LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); @@ -636,7 +649,7 @@ int main(int argc, char **argv) { printf("gNB %d\n", i); free_gNB_dlsch(gNB->dlsch[0][i]); printf("UE %d\n", i); - free_nr_ue_dlsch(UE->dlsch[UE->current_thread_id[subframe]][0][i]); + free_nr_ue_dlsch(UE->dlsch[0][0][i]); } for (i = 0; i < 2; i++) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 8582c70e13..c9a8d58b04 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -105,6 +105,15 @@ int rlc_module_init (void) {return(0);} void pdcp_layer_init(void) {} int rrc_init_nr_global_param(void){return(0);} +void config_common(int Mod_idP, + int CC_idP, + int Nid_cell, + int nr_bandP, + uint64_t ssb_pattern, + uint64_t dl_CarrierFreqP, + uint32_t dl_BandwidthP + ); + // needed for some functions PHY_VARS_NR_UE ***PHY_vars_UE_g; @@ -132,6 +141,7 @@ int main(int argc, char **argv) //int n_errors2=0,n_alamouti=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; //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0; @@ -149,12 +159,15 @@ int main(int argc, char **argv) //int pbch_tx_ant; int N_RB_DL=273,mu=1; + uint64_t ssb_pattern = 0x01; + unsigned char frame_type = 0; unsigned char pbch_phase = 0; int frame=0,slot=1; int frame_length_complex_samples; int frame_length_complex_samples_no_prefix; + int slot_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; nfapi_nr_config_request_t *gNB_config; gNB_L1_rxtx_proc_t gNB_proc; @@ -179,7 +192,7 @@ int main(int argc, char **argv) randominit(0); - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dP:IL:")) != -1) { switch (c) { case 'f': write_output_file=1; @@ -306,6 +319,10 @@ int main(int argc, char **argv) break; + case 'M': + SSB_positions = atoi(optarg); + break; + case 'N': Nid_cell = atoi(optarg); break; @@ -356,8 +373,9 @@ int main(int argc, char **argv) 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 interfering eNB (in dB) - cell_id mod 3 = 1\n"); - printf("-j Relative strength of second interfering eNB (in dB) - cell_id mod 3 = 2\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"); @@ -393,11 +411,11 @@ int main(int argc, char **argv) frame_parms->N_RB_UL = N_RB_DL; // stub to configure frame_parms - nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell); + nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); // call MAC to configure common parameters phy_init_nr_gNB(gNB,0,0); - + mac_top_init_gNB(); double fs,bw; @@ -435,7 +453,8 @@ int main(int argc, char **argv) } frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP; + frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + slot_length_complex_samples_no_prefix = frame_parms->samples_per_slot_wCP; s_re = malloc(2*sizeof(double*)); s_im = malloc(2*sizeof(double*)); @@ -478,6 +497,7 @@ int main(int argc, char **argv) else {UE->is_synchronized = 1; UE->UE_mode[0]=PUSCH;} UE->perfect_ce = 0; + for (i=0;i<10;i++) UE->current_thread_id[i] = 0; if (init_nr_ue_signal(UE, 1, 0) != 0) { @@ -494,11 +514,13 @@ int main(int argc, char **argv) mac_top_init_gNB(); gNB_mac = RC.nrmac[0]; - config_common(0,0,78,(uint64_t)3640000000L,N_RB_DL); - config_nr_mib(0,0,1,kHz30,0,0,0,0,0); + config_common(0,0,Nid_cell,78,ssb_pattern,(uint64_t)3640000000L,N_RB_DL); + config_nr_mib(0,0,1,kHz30,0,0,0,0); nr_l2_init_ue(); UE_mac = get_mac_inst(0); + + UE->pdcch_vars[0][0]->crnti = 0x1234; UE->if_inst = nr_ue_if_module_init(0); UE->if_inst->scheduled_response = nr_ue_scheduled_response; @@ -515,7 +537,7 @@ int main(int argc, char **argv) gNB->pbch_configured = 1; for (int i=0;i<4;i++) gNB->pbch_pdu[i]=i+1; - nr_schedule_css_dlsch_phytest(0,frame,slot); + nr_schedule_uss_dlsch_phytest(0,frame,slot); Sched_INFO.module_id = 0; Sched_INFO.CC_id = 0; Sched_INFO.frame = frame; @@ -532,22 +554,24 @@ int main(int argc, char **argv) //nr_common_signal_procedures (gNB,frame,subframe); - 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); + 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); + + int tx_offset = slot*frame_parms->samples_per_slot; //TODO: loop over slots for (aa=0; aaframe_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], + &txdata[aa][tx_offset], 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], + &txdata[aa][tx_offset], 14, frame_parms); } @@ -560,7 +584,7 @@ int main(int argc, char **argv) frame_length_complex_samples, input_fd) != frame_length_complex_samples) { printf("error reading from file\n"); - exit(-1); + //exit(-1); } } @@ -596,7 +620,7 @@ int main(int argc, char **argv) // Type0 PDCCH search space dl_config.number_pdus = 1; dl_config.dl_config_list[0].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 3; // to be set + dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 0x1234; // to be set uint64_t mask = 0x0; uint16_t num_rbs=24; @@ -611,9 +635,9 @@ int main(int argc, char **argv) dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.rb_offset = rb_offset; // additional parameter other than coreset dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.duration = num_symbols; - dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_mapping_type =CCE_REG_MAPPING_TYPE_INTERLEAVED; - dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_reg_bundle_size = 6; // L 38.211 7.3.2.2 - dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_interleaver_size = 2; // R 38.211 7.3.2.2 + dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_mapping_type =CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; + dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_reg_bundle_size = 0; // L 38.211 7.3.2.2 + dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_interleaver_size = 0; // R 38.211 7.3.2.2 dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_shift_index = cell_id; dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.precoder_granularity = PRECODER_GRANULARITY_SAME_AS_REG_BUNDLE; dl_config.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.pdcch_dmrs_scrambling_id = cell_id; @@ -661,7 +685,7 @@ int main(int argc, char **argv) if (n_trials==1) { LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0],frame_length_complex_samples,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) + if (UE->frame_parms.nb_antennas_rx>1) LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1],frame_length_complex_samples,1,1); } if (UE->is_synchronized == 0) { @@ -687,7 +711,12 @@ int main(int argc, char **argv) do_pdcch_flag, normal_txrx); - + 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++; } } //noise trials diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 956c8ecd1f..e4ff2f48d7 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.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/NR_UE_ESTIMATION/nr_estimation.h" #include "SCHED_NR/sched_nr.h" @@ -87,11 +88,13 @@ int main(int argc, char **argv) int i,aa;//,l; double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0; + double cfo=0; uint8_t snr1set=0; int **txdata; double **s_re,**s_im,**r_re,**r_im; - //double iqim = 0.0; - //unsigned char pbch_pdu[6]; + double iqim = 0.0; + double ip =0.0; + unsigned char pbch_pdu[6]; // int sync_pos, sync_pos_slot; // FILE *rx_frame_file; FILE *output_fd = NULL; @@ -103,6 +106,7 @@ int main(int argc, char **argv) int trial,n_trials=1,n_errors=0,n_errors_payload=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; @@ -125,7 +129,7 @@ int main(int argc, char **argv) unsigned char frame_type = 0; unsigned char pbch_phase = 0; - int frame=0,subframe=0; + int frame=0; int frame_length_complex_samples; int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; @@ -146,7 +150,7 @@ int main(int argc, char **argv) randominit(0); - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:o:s:S:t:x:y:z:M:N:F:GR:dP:IL:")) != -1) { switch (c) { case 'f': write_output_file=1; @@ -212,6 +216,11 @@ int main(int argc, char **argv) n_trials = atoi(optarg); break; + case 'o': + cfo = atof(optarg); + msg("Setting CFO to %f Hz\n",cfo); + break; + case 's': snr0 = atof(optarg); msg("Setting SNR0 to %f\n",snr0); @@ -273,6 +282,10 @@ int main(int argc, char **argv) break; + case 'M': + SSB_positions = atoi(optarg); + break; + case 'N': Nid_cell = atoi(optarg); break; @@ -325,6 +338,8 @@ int main(int argc, char **argv) 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("-o Carrier frequency offset in Hz\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"); @@ -357,29 +372,53 @@ int main(int argc, char **argv) frame_parms->N_RB_DL = N_RB_DL; frame_parms->N_RB_UL = N_RB_DL; frame_parms->Nid_cell = Nid_cell; + frame_parms->nushift = Nid_cell%4; + frame_parms->ssb_type = nr_ssb_type_C; - nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell); + nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); phy_init_nr_gNB(gNB,0,0); - double fs,bw; + uint8_t n_hf = gNB_config->sch_config.half_frame_index.value; - if (mu == 1 && N_RB_DL == 217) { - fs = 122.88e6; - bw = 80e6; - } - else if (mu == 1 && N_RB_DL == 245) { - fs = 122.88e6; - bw = 90e6; + double fs,bw,scs,eps; + + switch (mu) { + case 1: + scs = 30000; + if (N_RB_DL == 217) { + fs = 122.88e6; + bw = 80e6; + + } + else if (N_RB_DL == 245) { + fs = 122.88e6; + bw = 90e6; + } + else if (N_RB_DL == 273) { + fs = 122.88e6; + bw = 100e6; + } + else if (N_RB_DL == 106) { + fs = 61.44e6; + bw = 40e6; + } + else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL); + break; } - else if (mu == 1 && N_RB_DL == 273) { - fs = 122.88e6; - bw = 100e6; + + // cfo with respect to sub-carrier spacing + eps = cfo/scs; + + // computation of integer and fractional FO to compare with estimation results + int IFO; + if(eps!=0.0){ + printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000)); + if (eps>0) + IFO=(int)(eps+0.5); + else + IFO=(int)(eps-0.5); + printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO); } - else if (mu == 1 && N_RB_DL == 106) { - fs = 61.44e6; - bw = 40e6; - } - else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL); gNB2UE = new_channel_desc_scm(n_tx, n_rx, @@ -436,6 +475,9 @@ int main(int argc, char **argv) UE->perfect_ce = 0; + if(eps!=0.0) + UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation + if (init_nr_ue_signal(UE, 1, 0) != 0) { printf("Error at UE NR initialisation\n"); @@ -447,31 +489,38 @@ int main(int argc, char **argv) if (input_fd==NULL) { gNB->pbch_configured = 1; for (int i=0;i<4;i++) gNB->pbch_pdu[i]=i+1; - nr_common_signal_procedures (gNB,frame,subframe); - 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; aaframe_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); + for (int slot=0;slotslots_per_frame;slot++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) + memset(gNB->common_vars.txdataF[aa],0,frame_parms->samples_per_slot_wCP*sizeof(int32_t)); + + nr_common_signal_procedures (gNB,frame,slot); + + for (aa=0; aaframe_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][slot*frame_parms->samples_per_slot], + 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][slot*frame_parms->samples_per_slot], + 14, + frame_parms); + } } } + + 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); + + } else { printf("Reading %d samples from file to antenna buffer %d\n",frame_length_complex_samples,0); - + UE->UE_fo_compensation = 1; // perform fo compensation when samples from file are used if (fread(txdata[0], sizeof(int32_t), frame_length_complex_samples, @@ -493,6 +542,7 @@ int main(int argc, char **argv) // printf("txlev %d (%f)\n",txlev,10*log10(txlev)); + for (i=0; inb_antennas_tx; aa++) { r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); @@ -506,7 +556,6 @@ int main(int argc, char **argv) n_errors_payload = 0; for (trial=0; trialsamples_per_subframe; i++) { + if(eps!=0.0) + rf_rx(r_re, // real part of txdata + r_im, // imag part of txdata + NULL, // interference real part + NULL, // interference imag part + 0, // interference power + frame_parms->nb_antennas_rx, // number of rx antennas + frame_length_complex_samples, // number of samples in frame + 1.0e9/fs, //sampling time (ns) + cfo, // frequency offset in Hz + 0.0, // drift (not implemented) + 0.0, // noise figure (not implemented) + 0.0, // rx gain in dB ? + 200, // 3rd order non-linearity in dB ? + &ip, // initial phase + 30.0e3, // phase noise cutoff in kHz + -500.0, // phase noise amplitude in dBc + 0.0, // IQ imbalance (dB), + 0.0); // IQ phase imbalance (rad) + + + for (i=0; inb_antennas_rx; aa++) { ((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); @@ -524,9 +594,9 @@ int main(int argc, char **argv) } if (n_trials==1) { - LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0],frame_parms->samples_per_subframe,1,1); + LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0],frame_parms->samples_per_frame,1,1); if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1],frame_parms->samples_per_subframe,1,1); + LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1],frame_parms->samples_per_frame,1,1); } if (UE->is_synchronized == 0) { @@ -536,40 +606,30 @@ int main(int argc, char **argv) } else { UE->rx_offset=0; - //symbol 1 - nr_slot_fep(UE, - 5, - 0, - 0, - 0, - 1, - NR_PBCH_EST); - //symbol 2 - nr_slot_fep(UE, - 6, - 0, - 0, - 0, - 1, - NR_PBCH_EST); - - //symbol 3 - nr_slot_fep(UE, - 7, - 0, - 0, - 0, - 1, - NR_PBCH_EST); - - ret = nr_rx_pbch(UE, - &UE->proc.proc_rxtx[0], - UE->pbch_vars[0], - frame_parms, - 0, - SISO, - UE->high_speed_flag); + uint8_t ssb_index = 0; + while (!((SSB_positions >> ssb_index) & 0x01)) ssb_index++; // to select the first transmitted ssb + + UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms, ssb_index, n_hf); + for (int i=UE->symbol_offset+1; isymbol_offset+4; i++) { + nr_slot_fep(UE, + i, + 0, + 0, + 0, + NR_PBCH_EST); + + nr_pbch_channel_estimation(UE,0,0,i,i-(UE->symbol_offset+1),ssb_index%8,n_hf); + } + + ret = nr_rx_pbch(UE, + 0, + UE->pbch_vars[0], + frame_parms, + 0, + ssb_index%8, + SISO, + UE->high_speed_flag); if (ret==0) { //UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically @@ -592,11 +652,11 @@ int main(int argc, char **argv) if (ret!=0) n_errors++; } } //noise trials - printf("SNR %f: trials %d, n_errors_crc = %d, n_errors_payload %d\n", SNR,n_trials,n_errors,n_errors_payload); 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/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c new file mode 100644 index 0000000000..ca3860c5b0 --- /dev/null +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -0,0 +1,744 @@ +/* +* 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 +#include +#include +#include +#include +#include + +#include "common/config/config_userapi.h" +#include "common/utils/LOG/log.h" +#include "common/ran_context.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/modulation_eNB.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_UE_TRANSPORT/nr_transport_proto_ue.h" + +#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; +PHY_VARS_NR_UE *UE; +RAN_CONTEXT_t RC; + +double cpuf; + +// dummy functions +int nfapi_mode = 0; +int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { + return (0); +} +int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { + return (0); +} + +int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { + return (0); +} + +int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { + return (0); +} + +int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) { + return (0); +} + +uint32_t from_nrarfcn(int nr_bandP, uint32_t dl_earfcn) { + return (0); +} +int32_t get_uldl_offset(int eutra_bandP) { + return (0); +} + +NR_IF_Module_t * +NR_IF_Module_init(int Mod_id) { + return (NULL); +} + +void exit_function(const char *file, const char *function, const int line, const char *s) { + const char *msg = s == NULL ? "no comment" : s; + printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg); + exit(-1); +} + +// needed for some functions +PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } }; +uint16_t n_rnti = 0x1234; + +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; //,j,l,aa; + 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 transmission_mode = 1, n_tx = 1, n_rx = 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; + 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; + uint8_t Imcs = 9; + + cpuf = get_cpu_freq_GHz(); + + 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 '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; + + case 'l': + nb_symb_sch = atoi(optarg); + break; + + case 'r': + nb_rb = atoi(optarg); + break; + + case 'x': + transmission_mode = atoi(optarg); + break; + + default: + case 'h': + printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]); + printf("-h This message\n"); + printf("-p Use extended prefix mode\n"); + printf("-d Use TDD\n"); + printf("-n Number of frames to simulate\n"); + printf("-s Starting SNR, runs from SNR0 to SNR0 + 5 dB. If n_frames is 1 then just SNR is simulated\n"); + printf("-S Ending SNR, runs from SNR0 to SNR1\n"); + printf("-t Delay spread for multipath channel\n"); + printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); + printf("-x Transmission mode (1,2,6 for the moment)\n"); + printf("-y Number of TX antennas used in eNB\n"); + printf("-z Number of RX antennas used in UE\n"); + printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n"); + printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n"); + printf("-M Multiple SSB positions in burst\n"); + printf("-N Nid_cell\n"); + printf("-R N_RB_DL\n"); + printf("-O oversampling factor (1,2,4,8,16)\n"); + printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n"); + // printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n"); + printf("-f Output filename (.txt format) for Pe/SNR results\n"); + printf("-F Input filename (.txt format) for RX conformance testing\n"); + exit(-1); + break; + } + } + + logInit(); + set_glog(loglvl); + T_stdout = 1; + + if (snr1set == 0) + snr1 = snr0 + 10; + + gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, + 61.44e6, //N_RB2sampling_rate(N_RB_DL), + 40e6, //N_RB2channel_bandwidth(N_RB_DL), + 0, 0, 0); + + if (gNB2UE == NULL) { + msg("Problem generating channel model. Exiting.\n"); + exit(-1); + } + + RC.gNB = (PHY_VARS_gNB ** *) malloc(sizeof(PHY_VARS_gNB **)); + RC.gNB[0] = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); + RC.gNB[0][0] = malloc(sizeof(PHY_VARS_gNB)); + gNB = RC.gNB[0][0]; + //gNB_config = &gNB->gNB_config; + + 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; + 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)); + + //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); + } + + } + } + + 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 int TBS = 8424; + unsigned int available_bits; + uint8_t nb_re_dmrs = 6; + uint16_t length_dmrs = 1; + unsigned char mod_order; + uint8_t Nl = 1; + uint8_t rvidx = 0; + uint8_t UE_id = 1; + + NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id][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("available bits %d TBS %d mod_order %d\n", available_bits, TBS, mod_order); + + /////////// setting rel15_ul parameters /////////// + rel15_ul->number_rbs = nb_rb; + rel15_ul->number_symbols = nb_symb_sch; + rel15_ul->Qm = mod_order; + rel15_ul->mcs = Imcs; + rel15_ul->rv = rvidx; + rel15_ul->n_layers = Nl; + /////////////////////////////////////////////////// + + 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; + test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8); + + for (i = 0; i < TBS / 8; i++) + test_input[i] = (unsigned char) rand(); + + // estimated_output = ulsch_gNB->harq_processes[harq_pid]->b; + + /////////////////////////[adk] preparing UL harq_process parameters///////////////////////// + /////////// + NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch_ue->harq_processes[harq_pid]; + + 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->rvidx = rvidx; + harq_process_ul_ue->TBS = TBS; + harq_process_ul_ue->a = &test_input[0]; + + } + /////////// + //////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef DEBUG_ULSCHSIM + for (i = 0; i < TBS / 8; i++) printf("test_input[i]=%d \n",test_input[i]); +#endif + + /*for (int i=0; i0x%08x\n",crc24c(test_input, 32)); + // generate signal + + /////////////////////////[adk] ULSCH coding///////////////////////// + /////////// + + if (input_fd == NULL) { + nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid); + } + + /////////// + //////////////////////////////////////////////////////////////////// + + + for (SNR = snr0; SNR < snr1; SNR += snr_step) { + n_errors = 0; + n_false_positive = 0; + + for (trial = 0; trial < n_trials; trial++) { + + errors_bit_uncoded = 0; + + for (i = 0; i < available_bits; i++) { + +#ifdef DEBUG_CODER + if ((i&0xf)==0) + printf("\ne %d..%d: ",i,i+15); +#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) + 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 + channel_output_fixed[i] = (short) quantize(sigma / 4.0 / 4.0, + modulated_input[i] + sigma * gaussdouble(0.0, 1.0), + qbits); +#else + 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 + else + channel_output_uncoded[i] = 0; + + if (channel_output_uncoded[i] != ulsch_ue->harq_processes[harq_pid]->f[i]) + errors_bit_uncoded = errors_bit_uncoded + 1; + } + + //if (errors_bit_uncoded>10) + printf("errors bits uncoded %u\n", errors_bit_uncoded); + +#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); + + if (ret > ulsch_gNB->max_ldpc_iterations) + n_errors++; + + //count errors + errors_bit = 0; + + 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] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + + if (estimated_output_bit[i] != test_input_bit[i]) { + errors_bit++; + //printf("estimated bits error occurs @%d ",i); + } + } + + if (errors_bit > 0) { + n_false_positive++; + if (n_trials == 1) + printf("errors_bit %d (trial %d)\n", errors_bit, trial); + } + } + + printf("*****************************************\n"); + printf("SNR %f, BLER %f (false positive %f)\n", SNR, + (float) n_errors / (float) n_trials, + (float) n_false_positive / (float) n_trials); + printf("*****************************************\n"); + + if ((float) n_errors / (float) n_trials < target_error_rate) { + printf("PUSCH test OK\n"); + break; + } + } + + /*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; aaframe_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; inb_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"); + 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, i); + + free_gNB_ulsch(gNB->ulsch[UE_id][i]); + + 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"); + } + + 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); + + if (input_fd) + fclose(input_fd); + + return (n_errors); +} + diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt index 5d718a1911..836af4540a 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/build/CMakeLists.txt @@ -96,3 +96,8 @@ target_link_libraries(pucch_uci_test -Wl,--start-group UTIL SCHED_NR_UE_LIB PHY PHY_COMMON PHY_UE PHY_NR_UE -Wl,--end-group pthread m ${ATLAS_LIBRARIES} ) +add_executable(pucch_uci_generator_test ${OPENAIR1_DIR}/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c ${SRC_UNIT_TESTS} ) +target_link_libraries(pucch_uci_generator_test + -Wl,--start-group UTIL SCHED_NR_UE_LIB PHY PHY_COMMON PHY_UE PHY_NR_UE -Wl,--end-group + pthread m ${ATLAS_LIBRARIES} + ) \ No newline at end of file diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c index 24a86425f3..fa243d1eb0 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c @@ -192,11 +192,10 @@ int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf) { retu void * get_shlibmodule_fptr(char *modname, char *fname) { return(NULL) ; } -void exit_fun(const char* s) -{ +/*void exit_fun (const char *s) { VOID_PARAMETER s; undefined_function(__FUNCTION__); -} +}*/ 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){ diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c index ab99841668..05170e0bc9 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/harq_test.c @@ -54,6 +54,8 @@ int test_harq_uplink(PHY_VARS_NR_UE *phy_vars_ue) { int gNB_id = 0; + int thread_number = 0; + int code_word_idx = 0; int harq_pid = 0; int ndi = 1; uint8_t rnti_type = _C_RNTI_; @@ -61,7 +63,7 @@ int test_harq_uplink(PHY_VARS_NR_UE *phy_vars_ue) printf("\nHARQ Uplink \n"); - config_uplink_harq_process(phy_vars_ue , gNB_id, NR_DEFAULT_DLSCH_HARQ_PROCESSES); + config_uplink_harq_process(phy_vars_ue , gNB_id, thread_number, code_word_idx, NR_DEFAULT_DLSCH_HARQ_PROCESSES); NR_UE_ULSCH_t *ulsch_harq = phy_vars_ue->ulsch[gNB_id]; @@ -91,7 +93,7 @@ int test_harq_uplink(PHY_VARS_NR_UE *phy_vars_ue) } } - release_uplink_harq_process(phy_vars_ue , gNB_id); + release_uplink_harq_process(phy_vars_ue , gNB_id, thread_number, code_word_idx); return 0; } diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c index c33571c6ea..9a4df025c7 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pss_util_test.c @@ -66,7 +66,7 @@ /*************** LOCAL VARIABLES***********************************/ static nfapi_config_request_t config_t; -static nfapi_config_request_t* config =&config_t; +static nfapi_config_request_t *config =&config_t; /*************** FUNCTIONS ****************************************/ @@ -86,8 +86,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_eNB, uint8_t abstract * *********************************************************************/ -void phase_shift_samples(int16_t *samples, int length, int16_t phase_shift_re, int16_t phase_shift_im) -{ +void phase_shift_samples(int16_t *samples, int length, int16_t phase_shift_re, int16_t phase_shift_im) { int16_t sample_re, sample_im; for (int i = 0; i < length; i++) { @@ -112,22 +111,23 @@ void phase_shift_samples(int16_t *samples, int length, int16_t phase_shift_re, i * *********************************************************************/ -void display_data(int pss_sequence_number, int16_t *rxdata, int position) -{ +void display_data(int pss_sequence_number, int16_t *rxdata, int position) { #ifdef DEBUG_TEST_PSS int16_t *pss_sequence[NUMBER_PSS_SEQUENCE] = {primary_synch0_time, primary_synch1_time, primary_synch2_time}; int16_t *pss_sequence_time = pss_sequence[pss_sequence_number]; printf(" pss %6d data \n", pss_sequence_number); + for (int i = 0; i < 4; i++) { if (pss_sequence_number < NUMBER_PSS_SEQUENCE) { printf("[i %6d] : %4d [i %6d] : %8i at address : %p \n", i, pss_sequence_time[2*i], (i + position), rxdata[2*i + (position*2)], &(rxdata[2*i + (position*2)])); printf("[q %6d] : %4d [q %6d] : %8i at address : %p \n", i, pss_sequence_time[2*i+1], (i + position), rxdata[2*i + 1 + (position*2)], &(rxdata[2*i + 1 + (position*2)])); - } - else { + } else { printf("[i %6d] : Undef [i %6d] : %8i at address : %p \n", i, (i + position), rxdata[2*i + (position*2)], &(rxdata[2*i + (position*2)])); printf("[q %6d] : Undef [q %6d] : %8i at address : %p \n", i, (i + position), rxdata[2*i + 1 + (position*2)], &(rxdata[2*i + 1 + (position*2)])); } - }nr_init_frame_parms + } + + nr_init_frame_parms printf(" ... ... \n"); #else (void) pss_sequence_number; @@ -149,11 +149,9 @@ void display_data(int pss_sequence_number, int16_t *rxdata, int position) * *********************************************************************/ -void display_test_configuration_pss(int position, int pss_sequence_number) -{ +void display_test_configuration_pss(int position, int pss_sequence_number) { const char next_test_text[] = "------------------------------------------------\n"; const char test_text_pss[] = "Test nr pss with Nid2 %i at position %i \n"; - printf(next_test_text); printf(test_text_pss, pss_sequence_number, position); } @@ -171,8 +169,7 @@ void display_test_configuration_pss(int position, int pss_sequence_number) * *********************************************************************/ -void display_test_configuration_sss(int sss_sequence_number) -{ +void display_test_configuration_sss(int sss_sequence_number) { const char test_text_sss[] = "Test nr sss with Nid1 %i \n"; printf(test_text_sss, sss_sequence_number); } @@ -191,8 +188,7 @@ void display_test_configuration_sss(int sss_sequence_number) * *********************************************************************/ -void undefined_function(const char *function) -{ +void undefined_function(const char *function) { printf("%s undefined \n", function); printf("Warning: function \"%s\" has been replaced by an empty function for avoiding undefined function error at build \n", function); } @@ -210,34 +206,22 @@ void undefined_function(const char *function) *********************************************************************/ int init_test(unsigned char N_tx, unsigned char N_rx, unsigned char transmission_mode, - unsigned char extended_prefix_flag, uint8_t frame_type, uint16_t Nid_cell, uint8_t N_RB_DL) -{ + unsigned char extended_prefix_flag, uint8_t frame_type, uint16_t Nid_cell, uint8_t N_RB_DL) { (void) transmission_mode; NR_DL_FRAME_PARMS *frame_parms; - int log_level = OAILOG_TRACE; - logInit(); - // enable these lines if you need debug info //set_comp_log(PHY,LOG_DEBUG,LOG_HIGH,1); set_glog(log_level); - #ifndef NR_UNIT_TEST - cpuf = get_cpu_freq_GHz(); - - LOG_I(PHY, "[CONFIG] Test of UE synchronisation \n"); - + //LOG_I(PHY, "[CONFIG] Test of UE synchronisation \n"); set_component_filelog(USIM); // file located in /tmp/testSynchroue.txt - #endif - //randominit(0); //set_taus_seed(0); - printf("Start lte_param_init, frame_type %d, extended_prefix %d\n",frame_type,extended_prefix_flag); - PHY_vars_UE = malloc(sizeof(PHY_VARS_NR_UE)); bzero(PHY_vars_UE, sizeof(PHY_VARS_NR_UE)); @@ -245,7 +229,6 @@ int init_test(unsigned char N_tx, unsigned char N_rx, unsigned char transmission return(-1); frame_parms = &(PHY_vars_UE->frame_parms); - frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz frame_parms->N_RB_UL = N_RB_DL; frame_parms->Ncp = extended_prefix_flag; @@ -257,38 +240,35 @@ int init_test(unsigned char N_tx, unsigned char N_rx, unsigned char transmission frame_parms->nb_antenna_ports_eNB = 1; frame_parms->threequarter_fs = 0; frame_parms->numerology_index = NUMEROLOGY_INDEX_MAX_NR; - - nr_init_frame_parms_ue(frame_parms); - + int mu = 1; + int n_ssb_crb = 0; + int ssb_subcarrier_offset = 0; + nr_init_frame_parms_ue(frame_parms, mu, extended_prefix_flag, N_RB_DL, n_ssb_crb, ssb_subcarrier_offset); PHY_vars_UE->frame_parms.Nid_cell = (3 * N_ID_1_NUMBER) + N_ID_2_NUMBER; /* set to unvalid value */ //phy_init_nr_top(frame_parms); - if (init_nr_ue_signal(PHY_vars_UE, 1, 0) != 0) - { + if (init_nr_ue_signal(PHY_vars_UE, 1, 0) != 0) { LOG_E(PHY,"Error at UE NR initialisation : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return (0); } -/* dummy initialisation of global structure PHY_vars_UE_g */ - + /* dummy initialisation of global structure PHY_vars_UE_g */ unsigned char NB_UE_INST=1; + PHY_vars_UE_g = (PHY_VARS_NR_UE ** *)calloc( NB_UE_INST, sizeof(PHY_VARS_NR_UE **)); - PHY_vars_UE_g = (PHY_VARS_NR_UE***)calloc( NB_UE_INST, sizeof(PHY_VARS_NR_UE**)); + for (int UE_id=0; UE_idnb_antennas_tx = 1; - //(frame_parms[CC_id])->nb_antennas_rx = nb_antennas_rx_ue; - // PHY_vars_UE_g[UE_id][CC_id] = init_lte_UE(frame_parms[CC_id], UE_id,abstraction_flag); - - PHY_vars_UE_g[UE_id][CC_id] = calloc(1, sizeof(PHY_VARS_NR_UE)); - PHY_vars_UE_g[UE_id][CC_id]->Mod_id=UE_id; - PHY_vars_UE_g[UE_id][CC_id]->CC_id=CC_id; - } - } + for (int CC_id=0; CC_idnb_antennas_tx = 1; + //(frame_parms[CC_id])->nb_antennas_rx = nb_antennas_rx_ue; + // PHY_vars_UE_g[UE_id][CC_id] = init_lte_UE(frame_parms[CC_id], UE_id,abstraction_flag); + PHY_vars_UE_g[UE_id][CC_id] = calloc(1, sizeof(PHY_VARS_NR_UE)); + PHY_vars_UE_g[UE_id][CC_id]->Mod_id=UE_id; + PHY_vars_UE_g[UE_id][CC_id]->CC_id=CC_id; + } + } return (0); } @@ -318,73 +298,66 @@ typedef enum { #define FREQUENCY_15_MHZ (15360000L) #define FREQUENCY (FREQUENCY_15_MHZ) /* to generate a frequency with a sampling of 30,72 MHz 5 gives 770 KHz, 20 gives 1,5 MHz, 40 gives 3 MHz */ -void set_random_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int amp) -{ -NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); -int samples_for_frame = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); -int16_t random; -int16_t *data_p; -random_data_format_t data_format = SINUSOIDAL_DATA; - +void set_random_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int amp) { + NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); + int samples_for_frame = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti); + int16_t random; + int16_t *data_p; + random_data_format_t data_format = SINUSOIDAL_DATA; /* reinitialise random for always getting same data */ srand(0); - double n = 0; - for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) { - + for (int aa=0; aaframe_parms.nb_antennas_rx; aa++) { data_p = (int16_t *) &(PHY_vars_UE->common_vars.rxdata[aa][0]); - int frequency_switch = samples_for_frame/LTE_NUMBER_OF_SUBFRAMES_PER_FRAME; int frequency_step = 0; double beat = (2*M_PI*FREQUENCY_15_MHZ)/(SAMPLING_RATE); for (int i=0; i< samples_for_frame; i++) { switch(data_format) { - case ZERO_DATA: - { + case ZERO_DATA: { /* all data are forced to zero */ random = 0; break; } - case SINUSOIDAL_DATA: - { + + case SINUSOIDAL_DATA: { /* sinusoidal signal */ n = cos(beat*i); random = n * (amp * SCALING_SINUSOIDAL_DATA); frequency_step++; + if (frequency_step == frequency_switch) { beat = beat/2; /* frequency is divided by 2 */ //printf("frequency %f at %d\n", (beat/2*M_PI), i); - frequency_step = 0; + frequency_step = 0; } + //printf("%d : cos %d %d \n", i, n, random); break; } - case RANDOM_DATA: - { + + case RANDOM_DATA: { /* random data can take any value between -SHRT_MAX and SHRT_MAX */ /* in this case one can use maxim value for uint16 because there is no saturation */ - #define SCALING_RANDOM_DATA (24) /* 48 is max value without decimation */ - #define RANDOM_MAX_AMP (amp * SCALING_RANDOM_DATA) - +#define SCALING_RANDOM_DATA (24) /* 48 is max value without decimation */ +#define RANDOM_MAX_AMP (amp * SCALING_RANDOM_DATA) random = ((rand() % RANDOM_MAX_AMP) - RANDOM_MAX_AMP/2); break; } - case RANDOM_MAX_DATA: - { + + case RANDOM_MAX_DATA: { /* random data can take only two value (-RANDOM_MAX) or RANDOM_MAX */ /* In this case saturation can occur with value of scaling_value greater than 23 */ - #define SCALING_RANDOM_MAX_DATA (8) - #define RANDOM_VALUE (amp * SCALING_RANDOM_DATA) - +#define SCALING_RANDOM_MAX_DATA (8) +#define RANDOM_VALUE (amp * SCALING_RANDOM_DATA) const int random_number[2] = {-1,+1}; - random = random_number[rand()%2] * RANDOM_VALUE; break; } - default: - { + + default: { printf("Format of data is undefined \n"); assert(0); break; @@ -393,12 +366,13 @@ random_data_format_t data_format = SINUSOIDAL_DATA; data_p[2*i] = random; data_p[2*i+1] = random; - #if 0 + if (i < 10) { - printf("random %d \n", random); + printf("random %d \n", random); printf("data[%d] : %d %d at address %p \n", i, data_p[2*i], data_p[2*i+1], &data_p[2*i]); } + #endif } } @@ -418,23 +392,22 @@ random_data_format_t data_format = SINUSOIDAL_DATA; * *********************************************************************/ -int set_pss_in_rx_buffer_from_external_buffer(PHY_VARS_NR_UE *PHY_vars_UE, short *input_buffer) -{ +int set_pss_in_rx_buffer_from_external_buffer(PHY_VARS_NR_UE *PHY_vars_UE, short *input_buffer) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int samples_for_frame = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe; /* both i and q */ - for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) { + for (int aa=0; aaframe_parms.nb_antennas_rx; aa++) { for (int i = 0; i < samples_for_frame; i++) { - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[2*i] = input_buffer[2*i]; /* real part */ - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1] = input_buffer[2*i+1]; /* imaginary part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i] = input_buffer[2*i]; /* real part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1] = input_buffer[2*i+1]; /* imaginary part */ } } /* check that sequence has been properly copied */ - for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) { + for (int aa=0; aaframe_parms.nb_antennas_rx; aa++) { for (int i=0; icommon_vars.rxdata[aa])[2*i]) - || (input_buffer[2*i+1] != ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1])) { + if ((input_buffer[2*i] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i]) + || (input_buffer[2*i+1] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[2*i+1])) { printf("Sequence pss was not properly copied into received buffer at index %d \n", i); exit(-1); } @@ -466,15 +439,13 @@ int set_pss_in_rx_buffer_from_external_buffer(PHY_VARS_NR_UE *PHY_vars_UE, short * *********************************************************************/ -int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) -{ +int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int samples_for_frame = frame_parms->samples_per_frame; int16_t *pss_sequence_time; if ((position_symbol > samples_for_frame) - || ((position_symbol + frame_parms->ofdm_symbol_size) > samples_for_frame)) - { + || ((position_symbol + frame_parms->ofdm_symbol_size) > samples_for_frame)) { printf("This pss sequence can not be fully written in the received window \n"); return (-1); } @@ -486,18 +457,18 @@ int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int p pss_sequence_time = primary_synchro_time_nr[pss_sequence_number]; - for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) { + for (int aa=0; aaframe_parms.nb_antennas_rx; aa++) { for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)] = pss_sequence_time[2*i]; /* real part */ - ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)] = pss_sequence_time[2*i+1]; /* imaginary part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)] = pss_sequence_time[2*i]; /* real part */ + ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)] = pss_sequence_time[2*i+1]; /* imaginary part */ } } /* check that sequence has been properly copied */ - for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) { + for (int aa=0; aaframe_parms.nb_antennas_rx; aa++) { for (int i=0; i<(frame_parms->ofdm_symbol_size); i++) { - if ((pss_sequence_time[2*i] != ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)]) - || (pss_sequence_time[2*i+1] != ((int16_t*)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)])) { + if ((pss_sequence_time[2*i] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i)]) + || (pss_sequence_time[2*i+1] != ((int16_t *)PHY_vars_UE->common_vars.rxdata[aa])[(position_symbol*2) + (2*i+1)])) { printf("Sequence pss was not properly copied into received buffer at index %d \n", i); exit(-1); } @@ -525,11 +496,9 @@ int set_pss_in_rx_buffer(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int p * *********************************************************************/ -void set_sequence_pss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) -{ +void set_sequence_pss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_sequence_number) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int samples_for_frame = frame_parms->samples_per_frame; - /* initialise received ue data with random */ set_random_rx_buffer(PHY_vars_UE, AMP); @@ -543,6 +512,7 @@ void set_sequence_pss(PHY_VARS_NR_UE *PHY_vars_UE, int position_symbol, int pss_ printf("This position for pss sequence %d is not supported because it exceeds the frame length %d!\n", position_symbol, samples_for_frame); exit(0); } + if (set_pss_in_rx_buffer(PHY_vars_UE, position_symbol, pss_sequence_number) != 0) printf("Warning: pss sequence can not be properly written into received buffer !\n"); } diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c new file mode 100644 index 0000000000..ab3ede4b8f --- /dev/null +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_generator_test.c @@ -0,0 +1,166 @@ +#include "../../unit_tests/src/pss_util_test.h" +#include "PHY/defs_nr_UE.h" +#include "PHY/INIT/init_extern.h" +#include "PHY/phy_extern_nr_ue.h" + +/* +#include "SCHED_NR_UE/defs.h" +#include "SCHED_NR/extern.h" + +#include "SCHED_NR_UE/harq_nr.h" +*/ +#include "SCHED_NR_UE/pucch_uci_ue_nr.h" + +/**************** define **************************************/ + +#define TST_GNB_ID_0 (0) /* first index of gNB */ +#define TST_THREAD_ID (0) + + +int test_pucch_generators(PHY_VARS_NR_UE *ue) { + int gNB_id = TST_GNB_ID_0; + int thread_number = TST_THREAD_ID; + int TB_identifier = 0; + int v_return = 0; + pucch_format_nr_t format = pucch_format2_nr; + uint8_t starting_symbol_index; + uint8_t nb_symbols_total = 4; + uint16_t starting_prb = 0;; /* it can be considered as first hop on case of pucch hopping */ + uint16_t second_hop = 0; /* second part for pucch for hopping */ + uint8_t nb_of_prbs = 1; + + switch (format) { + case pucch_format0_nr: + nb_symbols_total = 2; + nb_of_prbs = 1; + starting_symbol_index = 0; + break; + + case pucch_format1_nr: + nb_symbols_total = 5; + nb_of_prbs = 1; + starting_symbol_index = 0; + break; + + case pucch_format2_nr: + nb_symbols_total = 2; + nb_of_prbs = 16; + starting_symbol_index = 0; + break; + } + + int m_0 = 0; /* format 0 only */ + int m_CS = 0; /* for all format except for format 0 */ + int index_additional_dmrs = I_PUCCH_NO_ADDITIONAL_DMRS; + int index_hopping = I_PUCCH_NO_HOPPING; + int time_domain_occ = 0; + int occ_length = 0; + int occ_Index = 0; + uint64_t pucch_payload = 0; + int tx_amp = 512; + int nr_tti_tx = 0; + int N_UCI = 0; /* size in bits for Uplink Control Information */ + + switch(format) { + case pucch_format0_nr: { + nr_generate_pucch0(ue,ue->common_vars.txdataF, + &ue->frame_parms, + &ue->pucch_config_dedicated_nr[gNB_id], + tx_amp, + nr_tti_tx, + (uint8_t)m_0, + (uint8_t)m_CS, + nb_symbols_total, + starting_symbol_index, + starting_prb); + break; + } + + case pucch_format1_nr: { + nr_generate_pucch1(ue,ue->common_vars.txdataF, + &ue->frame_parms, + &ue->pucch_config_dedicated_nr[gNB_id], + pucch_payload, + tx_amp, + nr_tti_tx, + (uint8_t)m_0, + nb_symbols_total, + starting_symbol_index, + starting_prb, + second_hop, + (uint8_t)time_domain_occ, + (uint8_t)N_UCI); + break; + } + + case pucch_format2_nr: { + nr_generate_pucch2(ue, + ue->pdcch_vars[ue->current_thread_id[nr_tti_tx]][gNB_id]->crnti, + ue->common_vars.txdataF, + &ue->frame_parms, + &ue->pucch_config_dedicated_nr[gNB_id], + pucch_payload, + tx_amp, + nr_tti_tx, + nb_symbols_total, + starting_symbol_index, + nb_of_prbs, + starting_prb, + (uint8_t)N_UCI); + break; + } + + case pucch_format3_nr: + case pucch_format4_nr: { + nr_generate_pucch3_4(ue, + ue->pdcch_vars[ue->current_thread_id[nr_tti_tx]][gNB_id]->crnti, + ue->common_vars.txdataF, + &ue->frame_parms, + format, + &ue->pucch_config_dedicated_nr[gNB_id], + pucch_payload, + tx_amp, + nr_tti_tx, + nb_symbols_total, + starting_symbol_index, + nb_of_prbs, + starting_prb, + second_hop, + (uint8_t)N_UCI, + (uint8_t)occ_length, + (uint8_t)occ_Index); + break; + } + } + + return (v_return); +} + + +int main(int argc, char *argv[]) { + uint8_t transmission_mode = 1; + uint8_t nb_antennas_tx = 1; + uint8_t nb_antennas_rx = 1; + uint8_t frame_type = FDD; + uint8_t N_RB_DL=106; + lte_prefix_type_t extended_prefix_flag = NORMAL; + int Nid_cell[] = {(3*1+3)}; + VOID_PARAMETER argc; + VOID_PARAMETER argv; + printf(" PUCCH TEST \n"); + printf("-----------\n"); + + if (init_test(nb_antennas_tx, nb_antennas_rx, transmission_mode, extended_prefix_flag, frame_type, Nid_cell[0], N_RB_DL) != 0) { + printf("Initialisation problem for test \n"); + exit(-1);; + } + + if (test_pucch_generators(PHY_vars_UE) != 0) { + printf("\nTest PUCCH is fail \n"); + } else { + printf("\nTest PUCCH is pass \n"); + } + + free_context_synchro_nr(); + return(0); +} diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c index e317fbd154..bff3453de0 100644 --- a/openair1/SIMULATION/RF/rf.c +++ b/openair1/SIMULATION/RF/rf.c @@ -107,10 +107,10 @@ void rf_rx(double **r_re, exit(-1); } - if (fabs(f_off) > 10000.0) { +/* if (fabs(f_off) > 10000.0) { printf("rf.c: Illegal f_off %f\n",f_off); exit(-1); - } + }*/ if (fabs(drift) > 1000.0) { printf("rf.c: Illegal drift %f\n",drift); diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 922c949307..1c12f41150 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -361,7 +361,7 @@ typedef struct NRRrcConfigurationReq_s { lte_prefix_type_t UL_BWP_prefix_type[MAX_NUM_CCs]; long UL_timeAlignmentTimerCommon[MAX_NUM_CCs]; long ServingCellConfigCommon_n_TimingAdvanceOffset[MAX_NUM_CCs]; - long ServingCellConfigCommon_ssb_PositionsInBurst_PR[MAX_NUM_CCs]; + uint64_t ServingCellConfigCommon_ssb_PositionsInBurst_PR[MAX_NUM_CCs]; long ServingCellConfigCommon_ssb_periodicityServingCell[MAX_NUM_CCs]; //ServingCellConfigCommon long ServingCellConfigCommon_dmrs_TypeA_Position[MAX_NUM_CCs]; //ServingCellConfigCommon long NIA_SubcarrierSpacing[MAX_NUM_CCs]; //ServingCellConfigCommon Used only for non-initial access diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 82f92b0a4c..6325428743 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -103,7 +103,6 @@ void RCconfig_nr_flexran() *UL_frequencyShift7p5khz, *UL_SCS_SubcarrierSpacing, *UL_BWP_SubcarrierSpacing, *UL_BWP_prefix_type, *UL_timeAlignmentTimerCommon, *ServingCellConfigCommon_n_TimingAdvanceOffset, - *ServingCellConfigCommon_ssb_PositionsInBurst_PR, *NIA_SubcarrierSpacing, *referenceSubcarrierSpacing, *dl_UL_TransmissionPeriodicity, *rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice, *rach_groupBconfigured, *rach_messagePowerOffsetGroupB, @@ -118,7 +117,7 @@ void RCconfig_nr_flexran() *SearchSpace_searchSpaceType, *ue_Specific__dci_Formats, *RateMatchPatternLTE_CRS_subframeAllocation_choice; - uint64_t downlink_frequency; + uint64_t downlink_frequency, ServingCellConfigCommon_ssb_PositionsInBurst_PR; int32_t nr_band, uplink_frequency_offset, N_RB_DL, nb_antenna_ports, MIB_subCarrierSpacingCommon, MIB_ssb_SubcarrierOffset, MIB_dmrs_TypeA_Position, @@ -484,7 +483,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { char* UL_timeAlignmentTimerCommon = 0; char* ServingCellConfigCommon_n_TimingAdvanceOffset = 0; - char* ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0; + uint64_t ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0; int32_t ServingCellConfigCommon_ssb_periodicityServingCell = 0; int32_t ServingCellConfigCommon_dmrs_TypeA_Position = 0; char* NIA_SubcarrierSpacing = 0; @@ -1125,19 +1124,23 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { RC.config_file_name, i, ServingCellConfigCommon_n_TimingAdvanceOffset); } - if (strcmp(ServingCellConfigCommon_ssb_PositionsInBurst_PR,"shortBitmap")==0) { - NRRRC_CONFIGURATION_REQ (msg_p).ServingCellConfigCommon_ssb_PositionsInBurst_PR[j] = NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap; - }else if (strcmp(ServingCellConfigCommon_ssb_PositionsInBurst_PR,"mediumBitmap")==0) { - NRRRC_CONFIGURATION_REQ (msg_p).ServingCellConfigCommon_ssb_PositionsInBurst_PR[j] = NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap; - }else if (strcmp(ServingCellConfigCommon_ssb_PositionsInBurst_PR,"longBitmap")==0) { - NRRRC_CONFIGURATION_REQ (msg_p).ServingCellConfigCommon_ssb_PositionsInBurst_PR[j] = NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap; - }else if (strcmp(ServingCellConfigCommon_ssb_PositionsInBurst_PR,"NOTHING")==0) { - NRRRC_CONFIGURATION_REQ (msg_p).ServingCellConfigCommon_ssb_PositionsInBurst_PR[j] = NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_NOTHING; - }else { - AssertFatal (0,"Failed to parse gNB configuration file %s, gnb %d unknown value \"%s\" for ServingCellConfigCommon_ssb_PositionsInBurst_PR choice !\n", - RC.config_file_name, i, ServingCellConfigCommon_ssb_PositionsInBurst_PR); - } + uint64_t t_freq; + if(nr_band == 41 || (nr_band > 76 && nr_band < 80)) + t_freq = 2400000000; + else + t_freq = 3000000000; + + if (downlink_frequency 15)) + AssertFatal (0,"Failed to parse gNB configuration file %s, gnb %d unvalid value \"%ld\" for ssb_PositionsInBurst at DL frequency %ld !\n", + RC.config_file_name, i, ServingCellConfigCommon_ssb_PositionsInBurst_PR, downlink_frequency); + else { + if(downlink_frequency<6000000000 && (ServingCellConfigCommon_ssb_PositionsInBurst_PR > 255)) + AssertFatal (0,"Failed to parse gNB configuration file %s, gnb %d unvalid value \"%ld\" for ssb_PositionsInBurst at DL frequency %ld !\n", + RC.config_file_name, i, ServingCellConfigCommon_ssb_PositionsInBurst_PR, downlink_frequency); + else + NRRRC_CONFIGURATION_REQ (msg_p).ServingCellConfigCommon_ssb_PositionsInBurst_PR[j] = ServingCellConfigCommon_ssb_PositionsInBurst_PR; + } switch (ServingCellConfigCommon_ssb_periodicityServingCell) { case 5: diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 15a2e97239..6ac5bfc42d 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -640,7 +640,7 @@ typedef enum { {GNB_CONFIG_STRING_UL_BWP_PREFIX_TYPE, NULL, 0, strptr:&UL_BWP_prefix_type, defstrval:"NORMAL", TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_UL_TIMEALIGNMENTTIMERCOMMON, NULL, 0, strptr:&UL_timeAlignmentTimerCommon, defstrval:"infinity", TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON_N_TIMINGADVANCEOFFSET, NULL, 0, strptr:&ServingCellConfigCommon_n_TimingAdvanceOffset, defstrval:"n0", TYPE_STRING, 0}, \ -{GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON_SSB_POSITIONSINBURST_PR, NULL, 0, strptr:&ServingCellConfigCommon_ssb_PositionsInBurst_PR, defstrval:"shortBitmap", TYPE_STRING, 0}, \ +{GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON_SSB_POSITIONSINBURST_PR, NULL, 0, i64ptr:(int64_t *)&ServingCellConfigCommon_ssb_PositionsInBurst_PR, defint64val:0, TYPE_UINT64, 0}, \ {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON_SSB_PERIODICITYSERVINGCELL, NULL, 0, iptr:&ServingCellConfigCommon_ssb_periodicityServingCell, defintval:10, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON_DMRS_TYPEA_POSITION, NULL, 0, iptr:&ServingCellConfigCommon_dmrs_TypeA_Position, defintval:0, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_NIA_SUBCARRIERSPACING, NULL, 0, strptr:&NIA_SubcarrierSpacing, defstrval:"kHz15", TYPE_STRING, 0}, \ diff --git a/openair2/LAYER2/MAC/mac_extern.h b/openair2/LAYER2/MAC/mac_extern.h index ca72882471..825756a095 100644 --- a/openair2/LAYER2/MAC/mac_extern.h +++ b/openair2/LAYER2/MAC/mac_extern.h @@ -58,11 +58,7 @@ extern eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][MAX_MOBILES -#ifndef PHYSIM -#define NB_INST 1 -#else extern unsigned char NB_INST; -#endif extern unsigned char NB_eNB_INST; extern unsigned char NB_UE_INST; extern unsigned char NB_RN_INST; diff --git a/openair2/LAYER2/NR_MAC_UE/mac.h b/openair2/LAYER2/NR_MAC_UE/mac.h index b108bb2f1a..e77a6450da 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac.h +++ b/openair2/LAYER2/NR_MAC_UE/mac.h @@ -43,10 +43,10 @@ /*!\brief UE layer 2 status */ typedef enum { - CONNECTION_OK = 0, - CONNECTION_LOST, - PHY_RESYNCH, - PHY_HO_PRACH + UE_CONNECTION_OK = 0, + UE_CONNECTION_LOST, + UE_PHY_RESYNCH, + UE_PHY_HO_PRACH } NR_UE_L2_STATE_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index f34000bc98..2379233776 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -30,8 +30,8 @@ * \warning */ -#ifndef __LAYER2_MAC_PROTO_H__ -#define __LAYER2_MAC_PROTO_H__ +#ifndef __LAYER2_MAC_UE_PROTO_H__ +#define __LAYER2_MAC_UE_PROTO_H__ #include "mac_defs.h" #include "mac.h" diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 39b6303bcd..7afeced563 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -686,7 +686,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler( mac->scheduled_response.dl_config = dl_config; - return CONNECTION_OK; + return UE_CONNECTION_OK; } ////////////// diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 30917fd543..6954b9507d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -49,110 +49,6 @@ extern RAN_CONTEXT_t RC; extern void mac_top_init_gNB(void); extern uint8_t nfapi_mode; -int32_t **rxdata; -int32_t **txdata; - -typedef struct nr_bandentry_s { - int16_t band; - uint64_t ul_min; - uint64_t ul_max; - uint64_t dl_min; - uint64_t dl_max; - uint64_t N_OFFs_DL; - uint64_t step_size; -} nr_bandentry_t; - -typedef struct band_info_s { - int nbands; - nr_bandentry_t band_info[100]; -} nr_band_info_t; - -static const nr_bandentry_t nr_bandtable[] = { - {1, 1920000, 1980000, 2110000, 2170000, 20, 422000}, - {2, 1850000, 1910000, 1930000, 1990000, 20, 386000}, - {3, 1710000, 1785000, 1805000, 1880000, 20, 361000}, - {5, 824000, 849000, 869000, 894000, 20, 173800}, - {7, 2500000, 2570000, 2620000, 2690000, 20, 524000}, - {8, 880000, 915000, 925000, 960000, 20, 185000}, - {12, 698000, 716000, 728000, 746000, 20, 145800}, - {20, 832000, 862000, 791000, 821000, 20, 158200}, - {25, 1850000, 1915000, 1930000, 1995000, 20, 386000}, - {28, 703000, 758000, 758000, 813000, 20, 151600}, - {34, 2010000, 2025000, 2010000, 2025000, 20, 402000}, - {38, 2570000, 2620000, 2570000, 2630000, 20, 514000}, - {39, 1880000, 1920000, 1880000, 1920000, 20, 376000}, - {40, 2300000, 2400000, 2300000, 2400000, 20, 460000}, - {41, 2496000, 2690000, 2496000, 2690000, 3, 499200}, - {50, 1432000, 1517000, 1432000, 1517000, 20, 286400}, - {51, 1427000, 1432000, 1427000, 1432000, 20, 285400}, - {66, 1710000, 1780000, 2110000, 2200000, 20, 422000}, - {70, 1695000, 1710000, 1995000, 2020000, 20, 399000}, - {71, 663000, 698000, 617000, 652000, 20, 123400}, - {74, 1427000, 1470000, 1475000, 1518000, 20, 295000}, - {75, 000, 000, 1432000, 1517000, 20, 286400}, - {76, 000, 000, 1427000, 1432000, 20, 285400}, - {77, 3300000, 4200000, 3300000, 4200000, 1, 620000}, - {78, 3300000, 3800000, 3300000, 3800000, 1, 620000}, - {79, 4400000, 5000000, 4400000, 5000000, 2, 693334}, - {80, 1710000, 1785000, 000, 000, 20, 342000}, - {81, 860000, 915000, 000, 000, 20, 176000}, - {82, 832000, 862000, 000, 000, 20, 166400}, - {83, 703000, 748000, 000, 000, 20, 140600}, - {84, 1920000, 1980000, 000, 000, 20, 384000}, - {86, 1710000, 1785000, 000, 000, 20, 342000} -}; - - -uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint32_t bw) -{ - - uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000; - int bw_kHz = bw / 1000; - - int i; - - LOG_I(MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n",nr_bandP,(long long unsigned int)dl_CarrierFreq,bw); - AssertFatal(nr_bandP < 86, "nr_band %d > 86\n", nr_bandP); - for (i = 0; i < 30 && nr_bandtable[i].band != nr_bandP; i++); - - AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min, - "Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n", - nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k, - (long long unsigned int)nr_bandtable[i].dl_min); - AssertFatal(dl_CarrierFreq_by_1k <= - (nr_bandtable[i].dl_max - bw_kHz), - "Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n", - nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k, - (long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz)); - - int deltaFglobal; - - if (dl_CarrierFreq < 3e9) deltaFglobal = 5; - else deltaFglobal = 15; - - // This is equation before Table 5.4.2.1-1 in 38101-1-f30 - // F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs) - return (((dl_CarrierFreq_by_1k - nr_bandtable[i].dl_min)/deltaFglobal) + - nr_bandtable[i].N_OFFs_DL); -} - - -uint64_t from_nrarfcn(int nr_bandP, uint32_t dl_nrarfcn) -{ - - int i; - int deltaFglobal; - - if (nr_bandP < 77 || nr_bandP > 79) deltaFglobal = 5; - else deltaFglobal = 15; - - AssertFatal(nr_bandP < 87, "nr_band %d > 86\n", nr_bandP); - for (i = 0; i < 31 && nr_bandtable[i].band != nr_bandP; i++); - AssertFatal(dl_nrarfcn>=nr_bandtable[i].N_OFFs_DL,"dl_nrarfcn %u < N_OFFs_DL %llu\n",dl_nrarfcn, (long long unsigned int)nr_bandtable[i].N_OFFs_DL); - - return 1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal); - -} void config_nr_mib(int Mod_idP, int CC_idP, @@ -184,8 +80,10 @@ void config_nr_mib(int Mod_idP, void config_common(int Mod_idP, int CC_idP, + int cellid, int nr_bandP, - uint64_t dl_CarrierFreqP, + uint64_t ssb_pattern, + uint64_t dl_CarrierFreqP, uint32_t dl_BandwidthP ){ @@ -193,6 +91,9 @@ void config_common(int Mod_idP, int mu = 1; + cfg->sch_config.physical_cell_id.value = cellid; + cfg->sch_config.ssb_scg_position_in_burst.value = ssb_pattern; + // FDD cfg->subframe_config.duplex_mode.value = 1; cfg->subframe_config.duplex_mode.tl.tag = NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG; @@ -232,8 +133,10 @@ void config_common(int Mod_idP, int rrc_mac_config_req_gNB(module_id_t Mod_idP, int CC_idP, + int cellid, int p_gNB, int nr_bandP, + uint64_t ssb_pattern, uint64_t dl_CarrierFreqP, int dl_BandwidthP, NR_BCCH_BCH_Message_t *mib, @@ -258,10 +161,13 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, ); }// END if( mib != NULL ) + if( servingcellconfigcommon != NULL ){ config_common(Mod_idP, CC_idP, + cellid, nr_bandP, + ssb_pattern, dl_CarrierFreqP, dl_BandwidthP ); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 27d4dc36a9..f9d157ace5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -60,6 +60,7 @@ #endif #include "assertions.h" +#include #define ENABLE_MAC_PAYLOAD_DEBUG #define DEBUG_eNB_SCHEDULER 1 @@ -324,6 +325,16 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, nfapi_nr_config_request_t *cfg = &RC.nrmac[module_idP]->config[CC_id]; + nfapi_nr_coreset_t coreset = RC.nrmac[module_idP]->coreset[CC_id][1]; + nfapi_nr_search_space_t search_space = RC.nrmac[module_idP]->search_space[CC_id][1]; + + if (nr_is_dci_opportunity(search_space, + coreset, + frameP, + slotP, + *cfg)) + nr_schedule_uss_dlsch_phytest(module_idP, frameP, slotP); + rnti = UE_RNTI(module_idP, i); CC_id = UE_PCCID(module_idP, i); //int spf = get_spf(cfg); @@ -384,11 +395,12 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } for (int ii=0; iidlsch[ii][0]; - if((dlsch != NULL) && (dlsch->rnti == rnti)){ - LOG_I(MAC, "clean_gNB_dlsch UE %x \n", rnti); - clean_gNB_dlsch(dlsch); - } + NR_gNB_DLSCH_t *dlsch = RC.gNB[module_idP][CC_id]->dlsch[ii][0]; + if((dlsch != NULL) && (dlsch->rnti == rnti)){ + LOG_I(MAC, "clean_eNb_dlsch UE %x \n", rnti); + LOG_E(PHY,"Calling with wrong paramter type\n"); + clean_eNb_dlsch(dlsch); + } } for(int j = 0; j < 10; j++){ @@ -426,9 +438,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // Phytest scheduling/ option not activated because of pending bug - if (slotP==2) - nr_schedule_css_dlsch_phytest(module_idP, frameP, slotP); + /*if (slotP==2) + nr_schedule_css_dlsch_phytest(module_idP, frameP, slotP);*/ + if (slotP==1) + nr_schedule_uss_dlsch_phytest(module_idP, frameP, slotP); /* // Allocate CCEs for good after scheduling is done diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 131e64a93b..5a57bc2846 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -92,14 +92,15 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, nr_configure_css_dci_initial(params_rel15, - scs, scs, nr_FR1, 0, 0, + scs, scs, nr_FR1, 0, 0, 0, + sfn_sf, slotP, slots_per_frame, dl_carrier_bandwidth); params_rel15->first_slot = 0; pdu_rel15->frequency_domain_assignment = get_RIV(dlsch_pdu_rel15->start_prb, dlsch_pdu_rel15->n_prb, cfg->rf_config.dl_carrier_bandwidth.value); - pdu_rel15->time_domain_assignment = get_SLIV(dlsch_pdu_rel15->start_symbol, dlsch_pdu_rel15->nb_symbols); + pdu_rel15->time_domain_assignment = 3; // row index used here instead of SLIV pdu_rel15->vrb_to_prb_mapping = 1; pdu_rel15->mcs = 9; pdu_rel15->tb_scaling = 1; @@ -179,3 +180,145 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, } } + +/*Scheduling of DLSCH with associated DCI in user specific search space + * current version has only a DCI for type 1 PDCCH for C_RNTI*/ +void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP) +{ + uint8_t CC_id; + + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + //NR_COMMON_channels_t *cc = nr_mac->common_channels; + nfapi_nr_dl_config_request_body_t *dl_req; + nfapi_nr_dl_config_request_pdu_t *dl_config_dci_pdu; + nfapi_nr_dl_config_request_pdu_t *dl_config_dlsch_pdu; + nfapi_tx_request_pdu_t *TX_req; + + nfapi_nr_config_request_t *cfg = &nr_mac->config[0]; + uint16_t rnti = 0x1234; + + uint16_t sfn_sf = frameP << 7 | slotP; + int dl_carrier_bandwidth = cfg->rf_config.dl_carrier_bandwidth.value; + + // everything here is hard-coded to 30 kHz + int scs = get_dlscs(cfg); + int slots_per_frame = get_spf(cfg); + for (CC_id=0; CC_idcoreset[CC_id][1]; + nfapi_nr_search_space_t* search_space = &nr_mac->search_space[CC_id][1]; + + dl_req = &nr_mac->DL_req[CC_id].dl_config_request_body; + dl_config_dci_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void*)dl_config_dci_pdu,0,sizeof(nfapi_nr_dl_config_request_pdu_t)); + dl_config_dci_pdu->pdu_type = NFAPI_NR_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_dci_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_nr_dl_config_dci_dl_pdu)); + + dl_config_dlsch_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu+1]; + memset((void*)dl_config_dlsch_pdu,0,sizeof(nfapi_nr_dl_config_request_pdu_t)); + dl_config_dlsch_pdu->pdu_type = NFAPI_NR_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_dlsch_pdu->pdu_size = (uint8_t)(2+sizeof(nfapi_nr_dl_config_dlsch_pdu)); + + nfapi_nr_dl_config_dci_dl_pdu_rel15_t *pdu_rel15 = &dl_config_dci_pdu->dci_dl_pdu.dci_dl_pdu_rel15; + nfapi_nr_dl_config_pdcch_parameters_rel15_t *params_rel15 = &dl_config_dci_pdu->dci_dl_pdu.pdcch_params_rel15; + nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu_rel15 = &dl_config_dlsch_pdu->dlsch_pdu.dlsch_pdu_rel15; + + dlsch_pdu_rel15->start_prb = 0; + dlsch_pdu_rel15->n_prb = 50; + dlsch_pdu_rel15->start_symbol = 2; + dlsch_pdu_rel15->nb_symbols = 9; + dlsch_pdu_rel15->rnti = rnti; + dlsch_pdu_rel15->nb_layers =1; + dlsch_pdu_rel15->nb_codewords = 1; + dlsch_pdu_rel15->mcs_idx = 9; + dlsch_pdu_rel15->ndi = 1; + dlsch_pdu_rel15->redundancy_version = 0; + + nr_configure_dci_from_pdcch_config(params_rel15, + coreset, + search_space, + *cfg, + dl_carrier_bandwidth); + + pdu_rel15->frequency_domain_assignment = get_RIV(dlsch_pdu_rel15->start_prb, dlsch_pdu_rel15->n_prb, cfg->rf_config.dl_carrier_bandwidth.value); + pdu_rel15->time_domain_assignment = 3; // row index used here instead of SLIV; + pdu_rel15->vrb_to_prb_mapping = 1; + pdu_rel15->mcs = 9; + pdu_rel15->tb_scaling = 1; + + pdu_rel15->ra_preamble_index = 25; + pdu_rel15->format_indicator = 1; + pdu_rel15->ndi = 1; + pdu_rel15->rv = 0; + pdu_rel15->harq_pid = 0; + pdu_rel15->dai = 2; + pdu_rel15->tpc = 2; + pdu_rel15->pucch_resource_indicator = 7; + pdu_rel15->pdsch_to_harq_feedback_timing_indicator = 7; + + LOG_I(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d, time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n", + pdu_rel15->frequency_domain_assignment, + pdu_rel15->time_domain_assignment, + pdu_rel15->vrb_to_prb_mapping, + pdu_rel15->mcs, + pdu_rel15->tb_scaling, + pdu_rel15->ndi, + pdu_rel15->rv); + + params_rel15->rnti = rnti; + params_rel15->rnti_type = NFAPI_NR_RNTI_C; + params_rel15->dci_format = NFAPI_NR_DL_DCI_FORMAT_1_0; + + //params_rel15->aggregation_level = 1; + LOG_I(MAC, "DCI params: rnti %d, rnti_type %d, dci_format %d, config type %d\n \ + coreset params: mux_pattern %d, n_rb %d, n_symb %d, rb_offset %d \n \ + ss params : first symb %d, ss type %d\n", + params_rel15->rnti, + params_rel15->rnti_type, + params_rel15->config_type, + params_rel15->dci_format, + params_rel15->mux_pattern, + params_rel15->n_rb, + params_rel15->n_symb, + params_rel15->rb_offset, + params_rel15->first_symbol, + params_rel15->search_space_type); + nr_get_tbs(&dl_config_dlsch_pdu->dlsch_pdu, dl_config_dci_pdu->dci_dl_pdu, *cfg); + LOG_I(MAC, "DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d\n", + dlsch_pdu_rel15->start_prb, + dlsch_pdu_rel15->n_prb, + dlsch_pdu_rel15->start_symbol, + dlsch_pdu_rel15->nb_symbols, + dlsch_pdu_rel15->nb_layers, + dlsch_pdu_rel15->nb_codewords, + dlsch_pdu_rel15->mcs_idx); + + dl_req->number_dci++; + dl_req->number_pdsch_rnti++; + dl_req->number_pdu+=2; + + TX_req = &nr_mac->TX_req[CC_id].tx_request_body.tx_pdu_list[nr_mac->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = 6; + TX_req->pdu_index = nr_mac->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 8; + nr_mac->TX_req[CC_id].tx_request_body.number_of_pdus++; + nr_mac->TX_req[CC_id].sfn_sf = sfn_sf; + nr_mac->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG; + nr_mac->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST; + + TX_req = &nr_mac->TX_req[CC_id].tx_request_body.tx_pdu_list[nr_mac->TX_req[CC_id].tx_request_body.number_of_pdus+1]; + TX_req->pdu_length = dlsch_pdu_rel15->transport_block_size; + TX_req->pdu_index = nr_mac->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 8; + nr_mac->TX_req[CC_id].tx_request_body.number_of_pdus++; + nr_mac->TX_req[CC_id].sfn_sf = sfn_sf; + nr_mac->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG; + nr_mac->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST; + + } +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index ca0f103a43..1f88e2a03c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -21,11 +21,11 @@ /*! \file gNB_scheduler_primitives.c * \brief primitives used by gNB for BCH, RACH, ULSCH, DLSCH scheduling - * \author Navid Nikaein and Raymond Knopp, WEI-TAI CHEN - * \date 2010 - 2014, 2018 - * \email: navid.nikaein@eurecom.fr, kroempa@gmail.com + * \author Raymond Knopp, Guy De Souza + * \date 2018, 2019 + * \email: knopp@eurecom.fr, desouza@eurecom.fr * \version 1.0 - * \company Eurecom, NTUST + * \company Eurecom * @ingroup _mac */ @@ -65,23 +65,64 @@ extern RAN_CONTEXT_t RC; extern int n_active_slices; + // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) -uint8_t nr_coreset_nsymb_pdcch_type_0_b40Mhz[16] = {2,2,2,2,2,3,3,3,3,3,1,1,1,2,2,2}; // below 40Mhz bw -uint8_t nr_coreset_nsymb_pdcch_type_0_a40Mhz[10] = {2,2,3,3,1,1,2,2,3,3}; // above 40Mhz bw +uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_15[15] = {2,2,2,3,3,3,1,1,2,2,3,3,1,2,3}; +uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_30[14] = {2,2,2,2,3,3,3,3,1,1,2,2,3,3}; +uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_15_b40Mhz[9] = {1,1,2,2,3,3,1,2,3}; +uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_15_a40Mhz[9] = {1,2,3,1,1,2,2,3,3}; +uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_30_b40Mhz[16] = {2,2,2,2,2,3,3,3,3,3,1,1,1,2,2,2}; // below 40Mhz bw +uint8_t nr_coreset_nsymb_pdcch_type_0_scs_30_30_a40Mhz[10] = {2,2,3,3,1,1,2,2,3,3}; // above 40Mhz bw +uint8_t nr_coreset_nsymb_pdcch_type_0_scs_120_60[12] = {1,1,2,2,3,3,1,2,1,1,1,1}; + /// LUT for the number of RBs in the coreset indexed by coreset index -uint8_t nr_coreset_rb_offset_pdcch_type_0_b40Mhz[16] = {0,1,2,3,4,0,1,2,3,4,12,14,16,12,14,16}; -uint8_t nr_coreset_rb_offset_pdcch_type_0_a40Mhz[10] = {0,4,0,4,0,28,0,28,0,28}; +uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_15_15[15] = {0,2,4,0,2,4,12,16,12,16,12,16,38,38,38}; +uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_15_30[14] = {5,6,7,8,5,6,7,8,18,20,18,20,18,20}; +uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_15_b40Mhz[9] = {2,6,2,6,2,6,28,28,28}; +uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_15_a40Mhz[9] = {4,4,4,0,56,0,56,0,56}; +uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_30_b40Mhz[16] = {0,1,2,3,4,0,1,2,3,4,12,14,16,12,14,16}; +uint8_t nr_coreset_rb_offset_pdcch_type_0_scs_30_30_a40Mhz[10] = {0,4,0,4,0,28,0,28,0,28}; +int8_t nr_coreset_rb_offset_pdcch_type_0_scs_120_60[12] = {0,8,0,8,0,8,28,28,-1,49,-1,97}; +int8_t nr_coreset_rb_offset_pdcch_type_0_scs_120_120[8] = {0,4,14,14,-1,24,-1,48}; +int8_t nr_coreset_rb_offset_pdcch_type_0_scs_240_120[8] = {0,8,0,8,-1,25,-1,49}; + /// LUT for monitoring occasions param O indexed by ss index (4 LSB rmsi_pdcch_config) + // Note: scaling is used to avoid decimal values for O and M, original values commented uint8_t nr_ss_param_O_type_0_mux1_FR1[16] = {0,0,2,2,5,5,7,7,0,5,0,0,2,2,5,5}; -uint8_t nr_ss_param_O_type_0_mux1_FR2[14] = {0,0,2.5,2.5,5,5,0,2.5,5,7.5,7.5,7.5,0,5}; +uint8_t nr_ss_param_O_type_0_mux1_FR2[14] = {0,0,5,5,5,5,0,5,5,15,15,15,0,5}; //{0,0,2.5,2.5,5,5,0,2.5,5,7.5,7.5,7.5,0,5} +uint8_t nr_ss_scale_O_mux1_FR2[14] = {0,0,1,1,0,0,0,1,0,1,1,1,0,0}; + /// LUT for number of SS sets per slot indexed by ss index uint8_t nr_ss_sets_per_slot_type_0_FR1[16] = {1,2,1,2,1,2,1,2,1,1,1,1,1,1,1,1}; uint8_t nr_ss_sets_per_slot_type_0_FR2[14] = {1,2,1,2,1,2,2,2,2,1,2,2,1,1}; + /// LUT for monitoring occasions param M indexed by ss index -uint8_t nr_ss_param_M_type_0_mux1_FR1[16] = {1,0.5,1,0.5,1,0.5,1,0.5,2,2,1,1,1,1,1,1}; -uint8_t nr_ss_param_M_type_0_mux1_FR2[14] = {1,0.5,1,0.5,1,0.5,0.5,0.5,0.5,1,0.5,0.5,2,2}; +uint8_t nr_ss_param_M_type_0_mux1_FR1[16] = {1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1}; //{1,0.5,1,0.5,1,0.5,1,0.5,2,2,1,1,1,1,1,1} +uint8_t nr_ss_scale_M_mux1_FR1[16] = {0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0}; +uint8_t nr_ss_param_M_type_0_mux1_FR2[14] = {1,1,1,1,1,1,1,1,1,1,1,1,2,2}; //{1,0.5,1,0.5,1,0.5,0.5,0.5,0.5,1,0.5,0.5,2,2} +uint8_t nr_ss_scale_M_mux1_FR2[14] = {0,1,0,1,0,1,1,1,1,0,1,1,0,0}; + /// LUT for SS first symbol index indexed by ss index uint8_t nr_ss_first_symb_idx_type_0_mux1_FR1[8] = {0,0,1,2,1,2,1,2}; + // Mux pattern type 2 +uint8_t nr_ss_first_symb_idx_scs_120_60_mux2[4] = {0,1,6,7}; +uint8_t nr_ss_first_symb_idx_scs_240_120_set1_mux2[6] = {0,1,2,3,0,1}; + // Mux pattern type 3 +uint8_t nr_ss_first_symb_idx_scs_120_120_mux3[4] = {4,8,2,6}; + +/// Search space max values indexed by scs +uint8_t nr_max_number_of_candidates_per_slot[4] = {44, 36, 22, 20}; +uint8_t nr_max_number_of_cces_per_slot[4] = {56, 56, 48, 32}; + +static inline uint8_t get_max_candidates(uint8_t scs) { + AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs); + return (nr_max_number_of_candidates_per_slot[scs]); +} + +static inline uint8_t get_max_cces(uint8_t scs) { + AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs); + return (nr_max_number_of_cces_per_slot[scs]); +} int is_nr_UL_slot(NR_COMMON_channels_t * ccP, int slot){ @@ -94,69 +135,143 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* p nr_frequency_range_e freq_range, uint8_t rmsi_pdcch_config, uint8_t ssb_idx, + uint8_t k_ssb, + uint16_t sfn_ssb, + uint8_t n_ssb, /*slot index overlapping the corresponding SSB index*/ uint16_t nb_slots_per_frame, uint16_t N_RB) { uint8_t O, M; uint8_t ss_idx = rmsi_pdcch_config&0xf; uint8_t cset_idx = (rmsi_pdcch_config>>4)&0xf; - uint8_t mu; + uint8_t mu = scs_common; + uint8_t O_scale=0, M_scale=0; // used to decide if the values of O and M need to be divided by 2 /// Coreset params switch(scs_common) { case kHz15: - mu = 0; + + switch(pdcch_scs) { + case kHz15: + AssertFatal(cset_idx<15,"Coreset index %d reserved for scs kHz15/kHz15\n", cset_idx); + pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1; + pdcch_params->n_rb = (cset_idx < 6)? 24 : (cset_idx < 12)? 48 : 96; + pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_15[cset_idx]; + pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx]; + break; + + case kHz30: + AssertFatal(cset_idx<14,"Coreset index %d reserved for scs kHz15/kHz30\n", cset_idx); + pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1; + pdcch_params->n_rb = (cset_idx < 8)? 24 : 48; + pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_30[cset_idx]; + pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx]; + break; + + default: + AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs); + + } break; case kHz30: - mu = 1; if (N_RB < 106) { // Minimum 40Mhz bandwidth not satisfied switch(pdcch_scs) { case kHz15: - AssertFatal(1==0,"kHz15 not supported yet\n"); - break; + AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx); + pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1; + pdcch_params->n_rb = (cset_idx < 10)? 48 : 96; + pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_b40Mhz[cset_idx]; + pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_b40Mhz[cset_idx]; + break; case kHz30: pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1; - pdcch_params->n_rb = (cset_idx < 10)? 24 : 48; - pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_b40Mhz[cset_idx]; - pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_b40Mhz[cset_idx]; - break; + pdcch_params->n_rb = (cset_idx < 6)? 24 : 48; + pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_b40Mhz[cset_idx]; + pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_30_b40Mhz[cset_idx]; + break; default: AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs); } } - else { - AssertFatal(ss_idx<10 ,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs); + else { // above 40Mhz switch(pdcch_scs) { case kHz15: - AssertFatal(1==0,"15 kHz SCS not supported yet\n"); - break; + AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx); + pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1; + pdcch_params->n_rb = (cset_idx < 3)? 48 : 96; + pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_a40Mhz[cset_idx]; + pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_a40Mhz[cset_idx]; + break; case kHz30: + AssertFatal(cset_idx<10,"Coreset index %d reserved for scs kHz30/kHz30\n", cset_idx); pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1; pdcch_params->n_rb = (cset_idx < 4)? 24 : 48; - pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_b40Mhz[cset_idx]; - pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_b40Mhz[cset_idx]; - break; + pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_a40Mhz[cset_idx]; + pdcch_params->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_30_a40Mhz[cset_idx]; + break; default: AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs); } } - - case kHz60: - mu = 2; break; case kHz120: - mu = 3; + switch(pdcch_scs) { + case kHz60: + AssertFatal(cset_idx<12,"Coreset index %d reserved for scs kHz120/kHz60\n", cset_idx); + pdcch_params->mux_pattern = (cset_idx < 8)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2; + pdcch_params->n_rb = (cset_idx < 6)? 48 : (cset_idx < 8)? 96 : (cset_idx < 10)? 48 : 96; + pdcch_params->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_120_60[cset_idx]; + pdcch_params->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx]>0)?nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx] : + (k_ssb == 0)? -41 : -42; + break; + + case kHz120: + AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz120/kHz120\n", cset_idx); + pdcch_params->mux_pattern = (cset_idx < 4)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3; + pdcch_params->n_rb = (cset_idx < 2)? 24 : (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48; + pdcch_params->n_symb = (cset_idx == 2)? 1 : 2; + pdcch_params->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx] : + (k_ssb == 0)? -20 : -21; + break; + + default: + AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs); + } + break; + + case kHz240: + switch(pdcch_scs) { + case kHz60: + AssertFatal(cset_idx<4,"Coreset index %d reserved for scs kHz240/kHz60\n", cset_idx); + pdcch_params->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1; + pdcch_params->n_rb = 96; + pdcch_params->n_symb = (cset_idx < 2)? 1 : 2; + pdcch_params->rb_offset = (cset_idx&1)? 16 : 0; break; + case kHz120: + AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz240/kHz120\n", cset_idx); + pdcch_params->mux_pattern = (cset_idx < 4)? NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2; + pdcch_params->n_rb = (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48; + pdcch_params->n_symb = ((cset_idx==2)||(cset_idx==3))? 2 : 1; + pdcch_params->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx] : + (k_ssb == 0)? -41 : -42; + break; + + default: + AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs); + } + break; + default: AssertFatal(1==0,"Invalid common subcarrier spacing %d\n", scs_common); @@ -170,27 +285,50 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* p O = nr_ss_param_O_type_0_mux1_FR1[ss_idx]; pdcch_params->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR1[ss_idx]; M = nr_ss_param_M_type_0_mux1_FR1[ss_idx]; - pdcch_params->first_symbol = (ss_idx < 8)? ( (ss_idx&1)? pdcch_params->n_symb : 0 ) : nr_ss_first_symb_idx_type_0_mux1_FR1[ss_idx - 8]; + M_scale = nr_ss_scale_M_mux1_FR1[ss_idx]; + pdcch_params->first_symbol = (ss_idx < 8)? ( (ssb_idx&1)? pdcch_params->n_symb : 0 ) : nr_ss_first_symb_idx_type_0_mux1_FR1[ss_idx - 8]; } else { AssertFatal(ss_idx<14 ,"Invalid search space index for multiplexing type 1 and FR2 %d\n", ss_idx); O = nr_ss_param_O_type_0_mux1_FR2[ss_idx]; + O_scale = nr_ss_scale_O_mux1_FR2[ss_idx]; pdcch_params->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR2[ss_idx]; M = nr_ss_param_M_type_0_mux1_FR2[ss_idx]; + M_scale = nr_ss_scale_M_mux1_FR2[ss_idx]; pdcch_params->first_symbol = (ss_idx < 12)? ( (ss_idx&1)? 7 : 0 ) : 0; } pdcch_params->nb_slots = 2; - pdcch_params->sfn_mod2 = ((uint8_t)(floor( (O*pow(2, mu) + floor(ssb_idx*M)) / nb_slots_per_frame )) & 1)? 1 : 0; - pdcch_params->first_slot = (uint8_t)(O*pow(2, mu) + floor(ssb_idx*M)) % nb_slots_per_frame; + pdcch_params->sfn_mod2 = (CEILIDIV( (((O<>O_scale) + ((ssb_idx*M)>>M_scale)), nb_slots_per_frame ) & 1)? 1 : 0; + pdcch_params->first_slot = (((O<>O_scale) + ((ssb_idx*M)>>M_scale)) % nb_slots_per_frame; - break; + break; case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2: - break; + AssertFatal( ((scs_common==kHz120)&&(pdcch_scs==kHz60)) || ((scs_common==kHz240)&&(pdcch_scs==kHz120)), + "Invalid scs_common/pdcch_scs combination %d/%d for Mux type 2\n", scs_common, pdcch_scs ); + AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs); + + pdcch_params->nb_slots = 1; + + if ((scs_common==kHz120)&&(pdcch_scs==kHz60)) { + pdcch_params->first_symbol = nr_ss_first_symb_idx_scs_120_60_mux2[ssb_idx&3]; + // Missing in pdcch_params sfn_C and n_C here and in else case + } + else { + pdcch_params->first_symbol = ((ssb_idx&7)==4)?12 : ((ssb_idx&7)==4)?13 : nr_ss_first_symb_idx_scs_240_120_set1_mux2[ssb_idx&7]; //??? + } + + break; case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3: - break; + AssertFatal( (scs_common==kHz120)&&(pdcch_scs==kHz120), + "Invalid scs_common/pdcch_scs combination %d/%d for Mux type 3\n", scs_common, pdcch_scs ); + AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs); + + pdcch_params->first_symbol = nr_ss_first_symb_idx_scs_120_120_mux3[ssb_idx&3]; + + break; default: AssertFatal(1==0, "Invalid SSB and coreset multiplexing pattern %d\n", pdcch_params->mux_pattern); @@ -206,11 +344,91 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* p } -void nr_configure_css_dci_from_pdcch_config(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params, +void nr_configure_dci_from_pdcch_config(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params, nfapi_nr_coreset_t* coreset, - nfapi_nr_search_space_t* search_space) { + nfapi_nr_search_space_t* search_space, + nfapi_nr_config_request_t cfg, + uint16_t N_RB) { +/// coreset + //ControlResourceSetId + pdcch_params->config_type = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; + //frequencyDomainResources + uint8_t count=0, start=0, start_set=0; + uint64_t bitmap = coreset->frequency_domain_resources; + for (int i=0; i<45; i++) + if ((bitmap>>(44-i))&1) { + count++; + if (!start_set) { + start = i; + start_set = 1; + } + } + pdcch_params->rb_offset = 6*start; + pdcch_params->n_rb = 6*count; + + //duration + pdcch_params->n_symb = coreset->duration; + + //cce-REG-MappingType + pdcch_params->cr_mapping_type = coreset->cce_reg_mapping_type; + if (pdcch_params->cr_mapping_type == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { + pdcch_params->reg_bundle_size = coreset->reg_bundle_size; + pdcch_params->interleaver_size = coreset->interleaver_size; + } + else { + pdcch_params->reg_bundle_size = 0; + pdcch_params->interleaver_size = 0; + } + + //shift index + pdcch_params->shift_index = coreset->shift_index; + + //precoderGranularity + pdcch_params->precoder_granularity = coreset->precoder_granularity; + + //TCI states + // PDCCH params does not yet include information about TCI and QCL (needed for DCI 1.1 and 0.1) + + //pdcch-DMRS-ScramblingID + pdcch_params->scrambling_id = coreset->dmrs_scrambling_id; + + +/// SearchSpace + + // first symbol + //AssertFatal(pdcch_scs==kHz15, "PDCCH SCS above 15kHz not allowed if a symbol above 2 is monitored"); + for (int i=0; imonitoring_symbols_in_slot>>(15-i))&1) { + pdcch_params->first_symbol=i; + break; + } + + //searchSpaceType + pdcch_params->search_space_type = search_space->search_space_type; + + pdcch_params->n_RB_BWP = N_RB; +} + +int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space, + nfapi_nr_coreset_t coreset, + uint16_t frame, + uint16_t slot, + nfapi_nr_config_request_t cfg) { + + AssertFatal(search_space.coreset_id==coreset.coreset_id, "Invalid association of coreset(%d) and search space(%d)\n", + search_space.search_space_id, coreset.coreset_id); + + uint8_t is_dci_opportunity=0; + uint16_t Ks=search_space.slot_monitoring_periodicity; + uint16_t Os=search_space.slot_monitoring_offset; + uint8_t Ts=search_space.duration; + + if (((frame*get_spf(&cfg) + slot - Os)%Ks)subframe_config.dl_cyclic_prefix_type.value==NFAPI_CP_EXTENDED)?12:14); + +} + diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 7060d80e7a..99452c4c7a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -60,8 +60,10 @@ void config_common(int Mod_idP, int rrc_mac_config_req_gNB(module_id_t Mod_idP, int CC_id, + int cellid, int p_gNB, int nr_bandP, + uint64_t ssb_pattern, uint64_t dl_CarrierFreqP, int dl_BandwidthP, NR_BCCH_BCH_Message_t *mib, @@ -94,13 +96,23 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_config_pdcch_parameters_rel15_t* p nr_frequency_range_e freq_range, uint8_t rmsi_pdcch_config, uint8_t ssb_idx, + uint8_t k_ssb, + uint16_t sfn_ssb, + uint8_t n_ssb, uint16_t nb_slots_per_frame, uint16_t N_RB); +int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space, + nfapi_nr_coreset_t coreset, + uint16_t frame, + uint16_t slot, + nfapi_nr_config_request_t cfg); -void nr_configure_css_dci_from_pdcch_config(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params, +void nr_configure_dci_from_pdcch_config(nfapi_nr_dl_config_pdcch_parameters_rel15_t* pdcch_params, nfapi_nr_coreset_t* coreset, - nfapi_nr_search_space_t* search_space); + nfapi_nr_search_space_t* search_space, + nfapi_nr_config_request_t cfg, + uint16_t N_RB); int get_dlscs(nfapi_nr_config_request_t *cfg); @@ -110,4 +122,12 @@ int get_spf(nfapi_nr_config_request_t *cfg); int to_absslot(nfapi_nr_config_request_t *cfg,int frame,int slot); +int get_symbolsperslot(nfapi_nr_config_request_t *cfg); + +void get_band(uint32_t downlink_frequency, uint8_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type); + +uint64_t from_nrarfcn(int nr_bandP, uint32_t dl_nrarfcn); + +uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint32_t bw); + #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 8387f748a7..7e6705d87f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -44,6 +44,34 @@ extern RAN_CONTEXT_t RC; +void nr_init_coreset(nfapi_nr_coreset_t *coreset) { + + coreset->coreset_id = 1; + coreset->frequency_domain_resources = 0x1E0000000000;//0x1FFFE0000000; // 96 RB starting from CRB0 + coreset->duration = 2; + coreset->cce_reg_mapping_type = NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED; + coreset->reg_bundle_size = 6; + coreset->interleaver_size = 2; + coreset->precoder_granularity = NFAPI_NR_CSET_SAME_AS_REG_BUNDLE; + coreset->tci_present_in_dci = 0; + coreset->dmrs_scrambling_id = 0; +} + +void nr_init_search_space(nfapi_nr_search_space_t *search_space) { + + search_space->search_space_id = 1; + search_space->coreset_id = 1; + search_space->search_space_type = NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC; + search_space->duration = 5; + search_space->slot_monitoring_periodicity = NFAPI_NR_SS_PERIODICITY_SL10; + search_space->slot_monitoring_offset = 1; + search_space->monitoring_symbols_in_slot = 0xC0000000; // first 2 ofdm symbols + search_space->css_formats_0_0_and_1_0 = 1; + search_space->uss_dci_formats = 0; // enum to be defined-- formats 0.0 and 1.0 + for (int i=0; inumber_of_candidates[i] = 4; // TODO +} + void mac_top_init_gNB(void) { module_id_t i,j; @@ -56,24 +84,24 @@ void mac_top_init_gNB(void) if (RC.nb_nr_macrlc_inst > 0) { RC.nrmac = (gNB_MAC_INST **) malloc16(RC.nb_nr_macrlc_inst *sizeof(gNB_MAC_INST *)); - + AssertFatal(RC.nrmac != NULL,"can't ALLOCATE %zu Bytes for %d gNB_MAC_INST with size %zu \n", RC.nb_nr_macrlc_inst * sizeof(gNB_MAC_INST *), RC.nb_nr_macrlc_inst, sizeof(gNB_MAC_INST)); for (i = 0; i < RC.nb_nr_macrlc_inst; i++) { RC.nrmac[i] = (gNB_MAC_INST *) malloc16(sizeof(gNB_MAC_INST)); - + AssertFatal(RC.nrmac != NULL,"can't ALLOCATE %zu Bytes for %d gNB_MAC_INST with size %zu \n", RC.nb_nr_macrlc_inst * sizeof(gNB_MAC_INST *), RC.nb_nr_macrlc_inst, sizeof(gNB_MAC_INST)); LOG_D(MAC,"[MAIN] ALLOCATE %zu Bytes for %d gNB_MAC_INST @ %p\n",sizeof(gNB_MAC_INST), RC.nb_nr_macrlc_inst, RC.mac); - + bzero(RC.nrmac[i], sizeof(gNB_MAC_INST)); - + RC.nrmac[i]->Mod_id = i; - + for (j = 0; j < MAX_NUM_CCs; j++) { RC.nrmac[i]->DL_req[j].dl_config_request_body.dl_config_pdu_list = RC.nrmac[i]->dl_config_pdu_list[j]; @@ -84,7 +112,11 @@ void mac_top_init_gNB(void) RC.nrmac[i]->HI_DCI0_req[j].hi_dci0_request_body.hi_dci0_pdu_list = RC.nrmac[i]->hi_dci0_pdu_list[j]; RC.nrmac[i]->TX_req[j].tx_request_body.tx_pdu_list = RC.nrmac[i]->tx_request_pdu[j]; - RC.nrmac[i]->ul_handle = 0; + RC.nrmac[i]->ul_handle = 0; + + // Init PDCCH structures + nr_init_coreset(&RC.nrmac[i]->coreset[j][1]); + nr_init_search_space(&RC.nrmac[i]->search_space[j][1]); } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_common.c b/openair2/LAYER2/NR_MAC_gNB/nr_mac_common.c new file mode 100644 index 0000000000..f2c2e437cc --- /dev/null +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_common.c @@ -0,0 +1,148 @@ +/* + * 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 nr_mac_common.c + * \brief Common MAC functions for NR UE and gNB + * \author Florian Kaltenberger and Raymond Knopp + * \date 2019 + * \version 0.1 + * \company Eurecom, NTUST + * \email: florian.kalteberger@eurecom.fr, raymond.knopp@eurecom.fr + * @ingroup _mac + + */ + +#include "LAYER2/NR_MAC_gNB/mac_proto.h" + +nr_bandentry_t nr_bandtable[] = { + {1, 1920000, 1980000, 2110000, 2170000, 20, 422000}, + {2, 1850000, 1910000, 1930000, 1990000, 20, 386000}, + {3, 1710000, 1785000, 1805000, 1880000, 20, 361000}, + {5, 824000, 849000, 869000, 894000, 20, 173800}, + {7, 2500000, 2570000, 2620000, 2690000, 20, 524000}, + {8, 880000, 915000, 925000, 960000, 20, 185000}, + {12, 698000, 716000, 728000, 746000, 20, 145800}, + {20, 832000, 862000, 791000, 821000, 20, 158200}, + {25, 1850000, 1915000, 1930000, 1995000, 20, 386000}, + {28, 703000, 758000, 758000, 813000, 20, 151600}, + {34, 2010000, 2025000, 2010000, 2025000, 20, 402000}, + {38, 2570000, 2620000, 2570000, 2630000, 20, 514000}, + {39, 1880000, 1920000, 1880000, 1920000, 20, 376000}, + {40, 2300000, 2400000, 2300000, 2400000, 20, 460000}, + {41, 2496000, 2690000, 2496000, 2690000, 3, 499200}, + {50, 1432000, 1517000, 1432000, 1517000, 20, 286400}, + {51, 1427000, 1432000, 1427000, 1432000, 20, 285400}, + {66, 1710000, 1780000, 2110000, 2200000, 20, 422000}, + {70, 1695000, 1710000, 1995000, 2020000, 20, 399000}, + {71, 663000, 698000, 617000, 652000, 20, 123400}, + {74, 1427000, 1470000, 1475000, 1518000, 20, 295000}, + {75, 000, 000, 1432000, 1517000, 20, 286400}, + {76, 000, 000, 1427000, 1432000, 20, 285400}, + {77, 3300000, 4200000, 3300000, 4200000, 1, 620000}, + {78, 3300000, 3800000, 3300000, 3800000, 1, 620000}, + {79, 4400000, 5000000, 4400000, 5000000, 2, 693334}, + {80, 1710000, 1785000, 000, 000, 20, 342000}, + {81, 860000, 915000, 000, 000, 20, 176000}, + {82, 832000, 862000, 000, 000, 20, 166400}, + {83, 703000, 748000, 000, 000, 20, 140600}, + {84, 1920000, 1980000, 000, 000, 20, 384000}, + {86, 1710000, 1785000, 000, 000, 20, 342000} +}; + +void get_band(uint32_t downlink_frequency, uint8_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type) { + + int ind; + int64_t dl_freq_khz = downlink_frequency/1000; + for ( ind=0; + ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]); + ind++) { + + *current_band = nr_bandtable[ind].band; + LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", ind, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min); + + if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) { + *current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000; + if (*current_offset == 0) + *current_type = TDD; + else + *current_type = FDD; + + LOG_I( PHY, "DL frequency %"PRIu32": band %d, frame_type %d, UL frequency %"PRIu32"\n", + downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset); + break; + } + } + + AssertFatal(ind != (sizeof(nr_bandtable) / sizeof(nr_bandtable[0])), + "Can't find EUTRA band for frequency %d\n", downlink_frequency); + +} + +uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint32_t bw) +{ + + uint64_t dl_CarrierFreq_by_1k = dl_CarrierFreq / 1000; + int bw_kHz = bw / 1000; + + int i; + + LOG_I(MAC,"Searching for nr band %d DL Carrier frequency %llu bw %u\n",nr_bandP,(long long unsigned int)dl_CarrierFreq,bw); + AssertFatal(nr_bandP < 86, "nr_band %d > 86\n", nr_bandP); + for (i = 0; i < 30 && nr_bandtable[i].band != nr_bandP; i++); + + AssertFatal(dl_CarrierFreq_by_1k >= nr_bandtable[i].dl_min, + "Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n", + nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k, + (long long unsigned int)nr_bandtable[i].dl_min); + AssertFatal(dl_CarrierFreq_by_1k <= + (nr_bandtable[i].dl_max - bw_kHz), + "Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n", + nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k, + (long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz)); + + int deltaFglobal; + + if (dl_CarrierFreq < 3e9) deltaFglobal = 5; + else deltaFglobal = 15; + + // This is equation before Table 5.4.2.1-1 in 38101-1-f30 + // F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs) + return (((dl_CarrierFreq_by_1k - nr_bandtable[i].dl_min)/deltaFglobal) + + nr_bandtable[i].N_OFFs_DL); +} + + +uint64_t from_nrarfcn(int nr_bandP, uint32_t dl_nrarfcn) +{ + + int i; + int deltaFglobal; + + if (nr_bandP < 77 || nr_bandP > 79) deltaFglobal = 5; + else deltaFglobal = 15; + + AssertFatal(nr_bandP < 87, "nr_band %d > 86\n", nr_bandP); + for (i = 0; i < 31 && nr_bandtable[i].band != nr_bandP; i++); + AssertFatal(dl_nrarfcn>=nr_bandtable[i].N_OFFs_DL,"dl_nrarfcn %u < N_OFFs_DL %llu\n",dl_nrarfcn, (long long unsigned int)nr_bandtable[i].N_OFFs_DL); + + return 1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal); + +} diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3af2a4a7c9..6cd15fd32b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -138,6 +138,10 @@ typedef struct gNB_MAC_INST_s { nfapi_tx_request_pdu_t tx_request_pdu[NFAPI_CC_MAX][MAX_NUM_TX_REQUEST_PDU]; /// NFAPI DL PDU structure nfapi_tx_request_t TX_req[NFAPI_CC_MAX]; + /// NFAPI coreset structure + nfapi_nr_coreset_t coreset[NFAPI_CC_MAX][NFAPI_NR_MAX_NB_CORESETS]; + /// NFAPI search space structure + nfapi_nr_search_space_t search_space[NFAPI_CC_MAX][NFAPI_NR_MAX_NB_SEARCH_SPACES]; UE_list_t UE_list; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 1ea888eeb9..e391cc67b9 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -74,7 +74,7 @@ int8_t handle_dlsch (module_id_t module_id, int cc_id, uint8_t gNB_index, fapi_n return nr_ue_process_dlsch( module_id, cc_id, gNB_index, - &dci_ind, + dci_ind, pduP, pdu_len); @@ -102,13 +102,13 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ 0, 0); // TODO check tx/rx frame/slot is need for NR version switch(ret){ - case CONNECTION_OK: + case UE_CONNECTION_OK: break; - case CONNECTION_LOST: + case UE_CONNECTION_LOST: break; - case PHY_RESYNCH: + case UE_PHY_RESYNCH: break; - case PHY_HO_PRACH: + case UE_PHY_HO_PRACH: break; default: break; @@ -268,11 +268,11 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { // Type0 PDCCH search space dl_config->number_pdus = 1; dl_config->dl_config_list[0].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 0xaaaa; // to be set + dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 0x1234; // to be set uint64_t mask = 0x0; - uint16_t num_rbs=48; - uint16_t rb_offset=47; + uint16_t num_rbs=24; + uint16_t rb_offset=0; uint16_t cell_id=0; uint16_t num_symbols=2; for(int i=0; i<(num_rbs/6); ++i){ // 38.331 Each bit corresponds a group of 6 RBs @@ -283,16 +283,16 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.rb_offset = rb_offset; // additional parameter other than coreset dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.duration = num_symbols; - dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_mapping_type =CCE_REG_MAPPING_TYPE_INTERLEAVED; - dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_reg_bundle_size = 6; // L 38.211 7.3.2.2 - dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_interleaver_size = 2; // R 38.211 7.3.2.2 + dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_mapping_type =CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; + dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_reg_bundle_size = 0; // L 38.211 7.3.2.2 + dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_interleaver_size = 0; // R 38.211 7.3.2.2 dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.cce_reg_interleaved_shift_index = cell_id; dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.precoder_granularity = PRECODER_GRANULARITY_SAME_AS_REG_BUNDLE; dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.pdcch_dmrs_scrambling_id = cell_id; uint32_t number_of_search_space_per_slot=1; uint32_t first_symbol_index=0; - uint32_t search_space_duration=1; // element of search space + uint32_t search_space_duration=0; // element of search space uint32_t coreset_duration; // element of coreset coreset_duration = num_symbols * number_of_search_space_per_slot; @@ -308,4 +308,5 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.N_RB_BWP = 106; + return 0; } diff --git a/openair2/RRC/LTE/rrc_extern.h b/openair2/RRC/LTE/rrc_extern.h index 59200fb9cc..68c805dffe 100644 --- a/openair2/RRC/LTE/rrc_extern.h +++ b/openair2/RRC/LTE/rrc_extern.h @@ -44,17 +44,11 @@ extern LogicalChannelConfig_t SRB1_logicalChannelConfig_defaultValue; extern LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue; -#ifndef PHY_EMUL -#ifndef PHYSIM -//#define NB_INST 1 -#else extern unsigned char NB_INST; -#endif extern unsigned char NB_eNB_INST; extern unsigned char NB_UE_INST; extern unsigned short NODE_ID[1]; extern void* bigphys_malloc(int); -#endif //CONSTANTS diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index df45ae5e05..1b3e367ec7 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -747,15 +747,21 @@ void do_SERVINGCELLCONFIGCOMMON(uint8_t Mod_id, //ssb_PositionsInBurst (*servingcellconfigcommon)->ssb_PositionsInBurst->present = configuration->ServingCellConfigCommon_ssb_PositionsInBurst_PR[CC_id]; - if((*servingcellconfigcommon)->ssb_PositionsInBurst->present == NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap){ + uint64_t t_freq; + if(configuration->nr_band[CC_id] == 41 || (configuration->nr_band[CC_id] > 76 && configuration->nr_band[CC_id] < 80)) + t_freq = 2400000000; + else + t_freq = 3000000000; + + if(configuration->downlink_frequency[CC_id]ssb_PositionsInBurst->choice.shortBitmap.size = 1; (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.shortBitmap.bits_unused = 4; - (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.shortBitmap.buf[0] = 0x0f; - }else if((*servingcellconfigcommon)->ssb_PositionsInBurst->present == NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap){ + (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.shortBitmap.buf[0] = configuration->ServingCellConfigCommon_ssb_PositionsInBurst_PR[CC_id]; + }else if(configuration->downlink_frequency[CC_id]<6000000000){ (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.mediumBitmap.size = 1; (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; - (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = 0xff; - }else if((*servingcellconfigcommon)->ssb_PositionsInBurst->present == NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap){ + (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = configuration->ServingCellConfigCommon_ssb_PositionsInBurst_PR[CC_id]; + }else { (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.longBitmap.size = 8; (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.longBitmap.bits_unused = 0; (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.longBitmap.buf[0] = 0xff; @@ -768,6 +774,7 @@ void do_SERVINGCELLCONFIGCOMMON(uint8_t Mod_id, (*servingcellconfigcommon)->ssb_PositionsInBurst->choice.longBitmap.buf[7] = 0xff; } + //ssb_periodicityServingCell *(*servingcellconfigcommon)->ssb_periodicityServingCell = configuration->ServingCellConfigCommon_ssb_periodicityServingCell[CC_id]; //dmrs_TypeA_Position diff --git a/openair2/RRC/NR/nr_rrc_extern.h b/openair2/RRC/NR/nr_rrc_extern.h index 7509dfc727..a9af422f02 100644 --- a/openair2/RRC/NR/nr_rrc_extern.h +++ b/openair2/RRC/NR/nr_rrc_extern.h @@ -43,17 +43,11 @@ extern LogicalChannelConfig_t SRB1_logicalChannelConfig_defaultValue; extern LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue; -#ifndef PHY_EMUL -#ifndef PHYSIM -//#define NB_INST 1 -#else extern unsigned char NB_INST; -#endif extern unsigned char NB_eNB_INST; extern unsigned char NB_UE_INST; extern unsigned short NODE_ID[1]; extern void* bigphys_malloc(int); -#endif //CONSTANTS diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 52ac623b5e..af5ec8df82 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -235,7 +235,7 @@ static void init_NR_SI(const protocol_ctxt_t* const ctxt_pP, RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].Ncp_UL = configuration->UL_prefix_type[CC_id]; RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].dl_CarrierFreq = configuration->downlink_frequency[CC_id]; RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].ul_CarrierFreq = configuration->downlink_frequency[CC_id]+ configuration->uplink_frequency_offset[CC_id]; - + ///MIB RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_MIB = 0; RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].MIB = (uint8_t*) malloc16(4); @@ -260,11 +260,13 @@ static void init_NR_SI(const protocol_ctxt_t* const ctxt_pP, LOG_I(NR_RRC,"Done init_NR_SI\n"); - + rrc_mac_config_req_gNB(ctxt_pP->module_id, CC_id, + RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].physCellId, RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].p_gNB, configuration->nr_band[CC_id], + configuration->ServingCellConfigCommon_ssb_PositionsInBurst_PR[CC_id], RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].dl_CarrierFreq, configuration->N_RB_DL[CC_id], (NR_BCCH_BCH_Message_t *)&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].mib, diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 8b4279dc31..7efc4e8bed 100755 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -322,25 +322,24 @@ int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message( (const void *)bufferP, buffer_len ); - if(bcch_message->message.choice.mib->systemFrameNumber.buf != 0){ - if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { - printf("NR_CellGroupConfig decode error\n"); - for (i=0; imessage.choice.mib; - //memcpy( (void *)mib, - // (void *)&bcch_message->message.choice.mib, - // sizeof(NR_MIB_t) ); - - nr_rrc_mac_config_req_ue( 0, 0, 0, mib, NULL, NULL, NULL); + if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { + printf("NR_BCCH_BCH decode error\n"); + for (i=0; imessage.choice.mib; + //memcpy( (void *)mib, + // (void *)&bcch_message->message.choice.mib, + // sizeof(NR_MIB_t) ); + + nr_rrc_mac_config_req_ue( 0, 0, 0, mib, NULL, NULL, NULL); } return 0; diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index cf62304ec8..bcfa08c7eb 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -34,40 +34,42 @@ #include #include #include +#include #include "common_lib.h" #include "common/utils/load_module_shlib.h" +#include int set_device(openair0_device *device) { switch (device->type) { case EXMIMO_DEV: - printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case USRP_B200_DEV: - printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; -case USRP_X300_DEV: - printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + case USRP_X300_DEV: + LOG_I(HW,"[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case BLADERF_DEV: - printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case LMSSDR_DEV: - printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case NONE_DEV: - printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_W(HW,"[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case ADRV9371_ZC706_DEV: - printf("[%s] has loaded ADRV9371_ZC706 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded ADRV9371_ZC706 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; case UEDv2_DEV: - printf("[%s] has loaded UEDv2 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded UEDv2 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); break; default: - printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_E(HW,"[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return -1; } return 0; @@ -78,15 +80,15 @@ int set_transport(openair0_device *device) { switch (device->transp_type) { case ETHERNET_TP: - printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_I(HW,"[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return 0; break; case NONE_TP: - printf("[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_W(HW,"[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return 0; break; default: - printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); + LOG_E(HW,"[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU")); return -1; break; } @@ -100,6 +102,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 libname=OAI_RF_LIBNAME; shlib_fdesc[0].fname="device_init"; } else { @@ -108,7 +113,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param } ret=load_module_shlib(libname,shlib_fdesc,1,NULL); if (ret < 0) { - fprintf(stderr,"Library %s couldn't be loaded\n",libname); + LOG_E(HW,"Library %s couldn't be loaded\n",libname); } else { ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg); } @@ -124,7 +129,7 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf if ( rc >= 0) { if ( set_device(device) < 0) { - fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); + LOG_E(HW,"Unsupported radio head\n"); return -1; } } @@ -136,7 +141,7 @@ int openair0_transport_load(openair0_device *device, openair0_config_t *openair0 rc=load_lib(device, openair0_cfg, eth_params, RAU_REMOTE_RADIO_HEAD); if ( rc >= 0) { if ( set_transport(device) < 0) { - fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); + LOG_E(HW,"Unsupported transport protocol\n"); return -1; } } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 685a628b26..d14b2457c9 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -424,7 +424,7 @@ extern "C" * \returns 0 in success */ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg); - +#define gettid() syscall(__NR_gettid) /*@}*/ #ifdef __cplusplus diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index ffdec958a9..58a8697f79 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -597,10 +597,10 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp for (int i=0; irx_stream->recv(buff_ptrs, nsamps, s->rx_md); + samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md,1.0); } else { // receive a single channel (e.g. from connector RF A) - samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md); + samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md,1.0); } } diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md new file mode 100644 index 0000000000..89964decd5 --- /dev/null +++ b/targets/ARCH/rfsimulator/README.md @@ -0,0 +1,68 @@ +#General +This is a RF simulator that allows to test OAI without a RF board. +It replaces a actual RF board driver. + +As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound) + +#build + +## From build_oai +You can build it the same way, and together with actual RF driver + +Example: +```bash +./build_oai --ue-nas-use-tun --UE --eNB -w SIMU +``` +It is also possible to build actual RF and use choose on each run: +```bash +./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator +``` +Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem) +We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver. + +## Add the rfsimulator after initial build +After any regular build, you can compile the driver +```bash +cd /build +make rfsimulator +``` +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 + +## 4G case +For the UE, it should be set to the IP address of the eNB +example: +```bash +sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 +``` +Except this, the UE and the eNB can be used as it the RF is real + +If you reach 'RA not active' on UE, be careful to generate a valid SIM +```bash +$OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o . +``` +## 5G case +After regular build, add the simulation driver +(don't use ./build_oai -w SIMU until we merge 4G and 5G branches) +```bash +cd ran_build/build +make rfsimulator +``` +### Launch gNB in one window +```bash +sudo RFSIMULATOR=enb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD +``` +### Launch UE in another window +```bash +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 + +#Caveacts +Still issues in power control: txgain, rxgain are not used + +no S1 mode is currently broken, so we were not able to test the simulator in noS1 mode diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c new file mode 100644 index 0000000000..a17327b03e --- /dev/null +++ b/targets/ARCH/rfsimulator/simulator.c @@ -0,0 +1,475 @@ +/* + Author: Laurent THOMAS, Open Cells for Nokia + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "common_lib.h" +#include +#include "openair1/PHY/defs_UE.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 MAGICeNB 0xA5A5A5A5A5A5A5A5 +#define MAGICUE 0x5A5A5A5A5A5A5A5A + +typedef struct { + uint64_t magic; + uint32_t size; + uint32_t nbAnt; + uint64_t timestamp; +} transferHeader; + +typedef struct buffer_s { + int conn_sock; + bool alreadyRead; + uint64_t lastReceivedTS; + bool headerMode; + transferHeader th; + char *transferPtr; + uint64_t remainToTransfer; + char *circularBufEnd; + sample_t *circularBuf; +} buffer_t; + +typedef struct { + int listen_sock, epollfd; + uint64_t nextTimestamp; + uint64_t typeStamp; + uint64_t initialAhead; + char *ip; + buffer_t buf[FD_SETSIZE]; +} rfsimulator_state_t; + +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->headerMode=true; + ptr->transferPtr=(char *)&ptr->th; + ptr->remainToTransfer=sizeof(transferHeader); + int sendbuff=1000*1000*10; + AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, ""); + struct epoll_event ev= {0}; + ev.events = EPOLLIN | EPOLLRDHUP; + ev.data.fd = sock; + AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, ""); +} + +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); + memset(&bridge->buf[sock], 0, sizeof(buffer_t)); + bridge->buf[sock].conn_sock=-1; +} + +void socketError(rfsimulator_state_t *bridge, int sock) { + if (bridge->buf[sock].conn_sock!=-1) { + LOG_W(HW,"Lost socket \n"); + removeCirBuf(bridge, sock); + + if (bridge->typeStamp==MAGICUE) + exit(1); + } +} + + +#define helpTxt "\ +\x1b[31m\ +rfsimulator: error: you have to run one UE and one eNB\n\ +For this, export RFSIMULATOR=enb (eNB case) or \n\ + RFSIMULATOR= (UE case)\n\ +\x1b[m" + +enum blocking_t { + notBlocking, + blocking +}; + +void setblocking(int sock, enum blocking_t active) { + int opts; + AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,""); + + if (active==blocking) + opts = opts & ~O_NONBLOCK; + else + opts = opts | O_NONBLOCK; + + AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, ""); +} + +static bool flushInput(rfsimulator_state_t *t); + +void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) { + char *buf = _buf; + int l; + setblocking(fd, notBlocking); + + while (count) { + l = write(fd, buf, count); + + if (l <= 0) { + if (errno==EINTR) + continue; + + if(errno==EAGAIN) { + flushInput(t); + continue; + } else + return; + } + + count -= l; + buf += l; + } +} + +int server_start(openair0_device *device) { + rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; + t->typeStamp=MAGICeNB; + AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); + int enable = 1; + AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: + htons(PORT), +sin_addr: + { s_addr: INADDR_ANY } + }; + bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr)); + AssertFatal(listen(t->listen_sock, 5) == 0, ""); + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.fd = t->listen_sock; + AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, ""); + return 0; +} + +int start_ue(openair0_device *device) { + rfsimulator_state_t *t = device->priv; + t->typeStamp=MAGICUE; + int sock; + AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: + htons(PORT), +sin_addr: + { s_addr: INADDR_ANY } + }; + addr.sin_addr.s_addr = inet_addr(t->ip); + bool connected=false; + + while(!connected) { + LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, PORT); + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + LOG_I(HW,"rfsimulator: connection established\n"); + connected=true; + } + + perror("rfsimulator"); + sleep(1); + } + + setblocking(sock, notBlocking); + allocCirBuf(t, sock); + t->buf[sock].alreadyRead=true; // UE will start blocking on read + return 0; +} + +int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { + rfsimulator_state_t *t = device->priv; + + for (int i=0; ibuf[i]; + + if (ptr->conn_sock >= 0 ) { + transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp}; + fullwrite(ptr->conn_sock,&header, sizeof(header), t); + sample_t tmpSamples[nsamps][nbAnt]; + + for(int a=0; aconn_sock >= 0 ) + fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); + } + } + + 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) ); + return nsamps; +} + +static bool flushInput(rfsimulator_state_t *t) { + // Process all incoming events on sockets + // store the data in lists + struct epoll_event events[FD_SETSIZE]= {0}; + int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 200); + + if ( nfds==-1 ) { + if ( errno==EINTR || errno==EAGAIN ) + return false; + else + AssertFatal(false,"error in epoll_wait\n"); + } + + for (int nbEv = 0; nbEv < nfds; ++nbEv) { + int fd=events[nbEv].data.fd; + + if (events[nbEv].events & EPOLLIN && fd == t->listen_sock) { + int conn_sock; + AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, ""); + setblocking(conn_sock, notBlocking); + allocCirBuf(t, conn_sock); + LOG_I(HW,"A ue connected\n"); + } else { + if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) { + socketError(t,fd); + continue; + } + + buffer_t *b=&t->buf[fd]; + + if ( b->circularBuf == NULL ) { + LOG_E(HW, "received data on not connected socket %d\n", events[nbEv].data.fd); + continue; + } + + int blockSz; + + if ( b->headerMode) + blockSz=b->remainToTransfer; + else + blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ? + b->remainToTransfer : + b->circularBufEnd - 1 - b->transferPtr ; + + int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); + + if ( sz < 0 ) { + if ( errno != EAGAIN ) { + LOG_E(HW,"socket failed %s\n", strerror(errno)); + abort(); + } + } else if ( sz == 0 ) + continue; + + AssertFatal((b->remainToTransfer-=sz) >= 0, ""); + b->transferPtr+=sz; + + if (b->transferPtr==b->circularBufEnd - 1) + b->transferPtr=(char *)b->circularBuf; + + // check the header and start block transfer + if ( b->headerMode==true && b->remainToTransfer==0) { + AssertFatal( (t->typeStamp == MAGICUE && b->th.magic==MAGICeNB) || + (t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "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; + + LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); + } + + b->lastReceivedTS=b->th.timestamp; + b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; + b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); + } + + if ( b->headerMode==false ) { + b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt); + + if ( b->remainToTransfer==0) { + LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS); + + // First block in UE, resync with the eNB current TS + if ( t->nextTimestamp == 0 ) + t->nextTimestamp=b->lastReceivedTS-b->th.size; + + b->headerMode=true; + b->transferPtr=(char *)&b->th; + b->remainToTransfer=sizeof(transferHeader); + b->th.magic=-1; + } + } + } + } + + return nfds>0; +} + +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); + } + + 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 + // check if a UE is connected + int first_sock; + + for (first_sock=0; first_sockbuf[first_sock].circularBuf != NULL ) + break; + + if ( first_sock == FD_SETSIZE ) { + // no connected device (we are eNB, no UE is connected) + if (!flushInput(t)) { + for (int x=0; x < nbAnt; x++) + memset(samplesVoid[x],0,sampleToByte(nsamps,1)); + + t->nextTimestamp+=nsamps; + LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); + *ptimestamp = t->nextTimestamp-nsamps; + return nsamps; + } + } else { + bool have_to_wait; + + do { + have_to_wait=false; + + for ( int sock=0; sockbuf[sock].circularBuf && + t->buf[sock].alreadyRead && //>= t->initialAhead && + (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { + have_to_wait=true; + break; + } + + if (have_to_wait) + /*printf("Waiting on socket, current last ts: %ld, expected at least : %ld\n", + ptr->lastReceivedTS, + t->nextTimestamp+nsamps); + */ + flushInput(t); + } while (have_to_wait); + } + + // Clear the output buffer + for (int a=0; abuf[sock]; + + if ( ptr->circularBuf && ptr->alreadyRead ) { + for (int a=0; acircularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1; + } + } + } + + *ptimestamp = t->nextTimestamp; // return the time of the first sample + t->nextTimestamp+=nsamps; + LOG_D(HW,"Rx to upper layer: %d from %ld to %ld, energy in first antenna %d\n", + nsamps, + *ptimestamp, t->nextTimestamp, + signal_energy(samplesVoid[0], nsamps)); + return nsamps; +} + + +int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) { + abort(); + return 0; +} +int rfsimulator_reply(openair0_device *device, void *msg, ssize_t msg_len) { + abort(); + return 0; +} +int rfsimulator_get_stats(openair0_device *device) { + return 0; +} +int rfsimulator_reset_stats(openair0_device *device) { + return 0; +} +void rfsimulator_end(openair0_device *device) {} +int rfsimulator_stop(openair0_device *device) { + return 0; +} +int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { + return 0; +} +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); + rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); + + if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) { + LOG_E(HW,helpTxt); + exit(1); + } + + rfsimulator->typeStamp = strncasecmp(rfsimulator->ip,"enb",3) == 0 ? + MAGICeNB: + MAGICUE; + LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == MAGICeNB ? "eNB" : "UE"); + device->trx_start_func = rfsimulator->typeStamp == MAGICeNB ? + server_start : + start_ue; + device->trx_get_stats_func = rfsimulator_get_stats; + device->trx_reset_stats_func = rfsimulator_reset_stats; + device->trx_end_func = rfsimulator_end; + device->trx_stop_func = rfsimulator_stop; + device->trx_set_freq_func = rfsimulator_set_freq; + device->trx_set_gains_func = rfsimulator_set_gains; + device->trx_write_func = rfsimulator_write; + device->trx_read_func = rfsimulator_read; + /* let's pretend to be a b2x0 */ + device->type = USRP_B200_DEV; + device->openair0_cfg=&openair0_cfg[0]; + device->priv = rfsimulator; + + for (int i=0; ibuf[i].conn_sock=-1; + + AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,""); + rfsimulator->initialAhead=openair0_cfg[0].sample_rate/1000; // One sub frame + return 0; +} diff --git a/targets/COMMON/openairinterface5g_limits.h b/targets/COMMON/openairinterface5g_limits.h index d44f0c5601..9645acf4dd 100644 --- a/targets/COMMON/openairinterface5g_limits.h +++ b/targets/COMMON/openairinterface5g_limits.h @@ -1,11 +1,12 @@ #ifndef OPENAIRINTERFACE5G_LIMITS_H_ #define OPENAIRINTERFACE5G_LIMITS_H_ -#if defined(CBMIMO1) || defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) +#if 1 /*defined(CBMIMO1) || defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)*/ # define NUMBER_OF_eNB_MAX 1 # define NUMBER_OF_gNB_MAX 1 # define NUMBER_OF_RU_MAX 2 # define NUMBER_OF_NR_RU_MAX 2 +# ifndef PHYSIM # ifndef UE_EXPANSION # define NUMBER_OF_UE_MAX 16 # define NUMBER_OF_NR_UE_MAX 16 @@ -17,6 +18,12 @@ # define NUMBER_OF_CONNECTED_eNB_MAX 1 # define NUMBER_OF_CONNECTED_gNB_MAX 1 # endif +# else +# define NUMBER_OF_UE_MAX 1 +# define NUMBER_OF_NR_UE_MAX 1 +# define NUMBER_OF_CONNECTED_eNB_MAX 1 +# define NUMBER_OF_CONNECTED_gNB_MAX 1 +# endif #else # define NUMBER_OF_eNB_MAX 7 # define NUMBER_OF_gNB_MAX 7 diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf index 258d6c5f03..5fd4b465b3 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf @@ -26,10 +26,10 @@ gNBs = node_function = "3GPP_gNODEB"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; - frame_type = "FDD"; + frame_type = "TDD"; DL_prefix_type = "NORMAL"; UL_prefix_type = "NORMAL"; - eutra_band = 22; + eutra_band = 78; downlink_frequency = 3510000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; @@ -70,7 +70,7 @@ gNBs = UL_BWP_prefix_type = "NORMAL"; UL_timeAlignmentTimerCommon = "infinity"; ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = "shortBitmap"; + ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; ServingCellConfigCommon_ssb_periodicityServingCell = 10; ServingCellConfigCommon_dmrs_TypeA_Position = 2; NIA_SubcarrierSpacing = "kHz15"; 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 3aaf0c5506..f22abf3112 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 @@ -26,10 +26,10 @@ gNBs = node_function = "3GPP_gNODEB"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; - frame_type = "FDD"; + frame_type = "TDD"; DL_prefix_type = "NORMAL"; UL_prefix_type = "NORMAL"; - eutra_band = 22; + eutra_band = 78; downlink_frequency = 3510000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; @@ -70,7 +70,7 @@ gNBs = UL_BWP_prefix_type = "NORMAL"; UL_timeAlignmentTimerCommon = "infinity"; ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = "shortBitmap"; + ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; ServingCellConfigCommon_ssb_periodicityServingCell = 10; ServingCellConfigCommon_dmrs_TypeA_Position = 2; NIA_SubcarrierSpacing = "kHz15"; @@ -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"; + 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"; } ); 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 d62b06aaa5..be98106d1e 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 @@ -26,10 +26,10 @@ gNBs = node_function = "3GPP_gNODEB"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; - frame_type = "FDD"; + frame_type = "TDD"; DL_prefix_type = "NORMAL"; UL_prefix_type = "NORMAL"; - eutra_band = 22; + eutra_band = 78; downlink_frequency = 3510000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; @@ -70,7 +70,7 @@ gNBs = UL_BWP_prefix_type = "NORMAL"; UL_timeAlignmentTimerCommon = "infinity"; ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = "shortBitmap"; + ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; ServingCellConfigCommon_ssb_periodicityServingCell = 10; ServingCellConfigCommon_dmrs_TypeA_Position = 2; NIA_SubcarrierSpacing = "kHz15"; 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 a604feabec..dbd937d61a 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 @@ -26,10 +26,10 @@ gNBs = node_function = "3GPP_gNODEB"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; - frame_type = "FDD"; + frame_type = "TDD"; DL_prefix_type = "NORMAL"; UL_prefix_type = "NORMAL"; - eutra_band = 22; + eutra_band = 78; downlink_frequency = 3510000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; @@ -70,7 +70,7 @@ gNBs = UL_BWP_prefix_type = "NORMAL"; UL_timeAlignmentTimerCommon = "infinity"; ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = "shortBitmap"; + ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; ServingCellConfigCommon_ssb_periodicityServingCell = 10; ServingCellConfigCommon_dmrs_TypeA_Position = 2; NIA_SubcarrierSpacing = "kHz15"; diff --git a/targets/RT/USER/nr-ru.c b/targets/RT/USER/nr-ru.c index af3916604e..c0598b9144 100644 --- a/targets/RT/USER/nr-ru.c +++ b/targets/RT/USER/nr-ru.c @@ -1333,7 +1333,7 @@ static void* ru_thread_tx( void* param ) { { for (i=0; inb_tx; i++) { - sprintf(filename,"tx%ddataF_frame%d_sf%d.m", i, print_frame, proc->tti_tx); + sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); if(proc->tti_tx == 9) { @@ -1554,7 +1554,7 @@ static void* ru_thread( void* param ) { { for (i=0; inb_tx; i++) { - sprintf(filename,"tx%ddataF_frame%d_sf%d.m", i, print_frame, proc->tti_tx); + sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); if(proc->tti_tx == 9) { diff --git a/targets/RT/USER/nr-softmodem.c b/targets/RT/USER/nr-softmodem.c index 3bc9bf49d9..5561258694 100644 --- a/targets/RT/USER/nr-softmodem.c +++ b/targets/RT/USER/nr-softmodem.c @@ -429,9 +429,12 @@ static void *scope_thread(void *arg) { for(UE_id=0; UE_idframe_parms), frame_parms, sizeof(NR_DL_FRAME_PARMS)); - } - else ue = PHY_vars_UE_g[UE_id][0]; + } else ue = PHY_vars_UE_g[UE_id][0]; ue->Mod_id = UE_id; ue->mac_enabled = 1; @@ -227,97 +176,99 @@ PHY_VARS_NR_UE* init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms, init_nr_ue_signal(ue,1,abstraction_flag); // intialize transport init_nr_ue_transport(ue,abstraction_flag); - return(ue); } -void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name) { - +void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char *name) { #ifdef DEADLINE_SCHEDULER - if (sched_runtime!=0) { - struct sched_attr attr= {0}; - attr.size = sizeof(attr); - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = sched_runtime; - attr.sched_deadline = sched_deadline; - attr.sched_period = 0; - AssertFatal(sched_setattr(0, &attr, 0) == 0, - "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno)); - LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n", - name, (unsigned long)gettid(), sched_getcpu()); - } + + if (sched_runtime!=0) { + struct sched_attr attr= {0}; + attr.size = sizeof(attr); + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = sched_runtime; + attr.sched_deadline = sched_deadline; + attr.sched_period = 0; + AssertFatal(sched_setattr(0, &attr, 0) == 0, + "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno)); + LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n", + name, (unsigned long)gettid(), sched_getcpu()); + } #else - if (CPU_COUNT(cpuset) > 0) - AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), ""); - struct sched_param sp; - sp.sched_priority = sched_fifo; - AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0, - "Can't set thread priority, Are you root?\n"); - /* Check the actual affinity mask assigned to the thread */ - cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE); - if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) { - char txt[512]={0}; - for (int j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, cset)) - sprintf(txt+strlen(txt), " %d ", j); - printf("CPU Affinity of thread %s is %s\n", name, txt); - } - CPU_FREE(cset); + + if (CPU_COUNT(cpuset) > 0) + AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), ""); + + struct sched_param sp; + sp.sched_priority = sched_fifo; + AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0, + "Can't set thread priority, Are you root?\n"); + /* Check the actual affinity mask assigned to the thread */ + cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE); + + if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) { + char txt[512]= {0}; + + for (int j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, cset)) + sprintf(txt+strlen(txt), " %d ", j); + + printf("CPU Affinity of thread %s is %s\n", name, txt); + } + + CPU_FREE(cset); #endif + // Lock memory from swapping. This is a process wide call (not constraint to this thread). + mlockall(MCL_CURRENT | MCL_FUTURE); + pthread_setname_np( pthread_self(), name ); + // LTS: this sync stuff should be wrong + printf("waiting for sync (%s)\n",name); + pthread_mutex_lock(&sync_mutex); + printf("Locked sync_mutex, waiting (%s)\n",name); - // Lock memory from swapping. This is a process wide call (not constraint to this thread). - mlockall(MCL_CURRENT | MCL_FUTURE); - pthread_setname_np( pthread_self(), name ); + while (sync_var<0) + pthread_cond_wait(&sync_cond, &sync_mutex); - // LTS: this sync stuff should be wrong - printf("waiting for sync (%s)\n",name); - pthread_mutex_lock(&sync_mutex); - printf("Locked sync_mutex, waiting (%s)\n",name); - while (sync_var<0) - pthread_cond_wait(&sync_cond, &sync_mutex); - pthread_mutex_unlock(&sync_mutex); - printf("started %s as PID: %ld\n",name, gettid()); + pthread_mutex_unlock(&sync_mutex); + printf("started %s as PID: %ld\n",name, gettid()); } -void init_UE(int nb_inst) -{ - int inst; - NR_UE_MAC_INST_t *mac_inst; - for (inst=0; inst < nb_inst; inst++) { - // UE->rfdevice.type = NONE_DEV; - //PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; - LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]); - PHY_vars_UE_g[inst][0] = init_nr_ue_vars(NULL,inst,0); - PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; +void init_UE(int nb_inst) { + int inst; + NR_UE_MAC_INST_t *mac_inst; - AssertFatal((UE->if_inst = nr_ue_if_module_init(inst)) != NULL, "can not initial IF module\n"); - nr_l3_init_ue(); - nr_l2_init_ue(); - - mac_inst = get_mac_inst(0); - mac_inst->if_module = UE->if_inst; - UE->if_inst->scheduled_response = nr_ue_scheduled_response; - UE->if_inst->phy_config_request = nr_ue_phy_config_request; - - LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]); - //init_UE_threads(inst); - //UE = PHY_vars_UE_g[inst][0]; - - - AssertFatal(0 == pthread_create(&UE->proc.pthread_ue, - &UE->proc.attr_ue, - UE_thread, - (void*)UE), ""); - } + for (inst=0; inst < nb_inst; inst++) { + // UE->rfdevice.type = NONE_DEV; + //PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; + LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]); + PHY_vars_UE_g[inst][0] = init_nr_ue_vars(NULL,inst,0); + PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; + AssertFatal((UE->if_inst = nr_ue_if_module_init(inst)) != NULL, "can not initial IF module\n"); + nr_l3_init_ue(); + nr_l2_init_ue(); + mac_inst = get_mac_inst(0); + mac_inst->if_module = UE->if_inst; + UE->if_inst->scheduled_response = nr_ue_scheduled_response; + UE->if_inst->phy_config_request = nr_ue_phy_config_request; + LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]); + //init_UE_threads(inst); + //UE = PHY_vars_UE_g[inst][0]; + AssertFatal(0 == pthread_create(&UE->proc.pthread_ue, + &UE->proc.attr_ue, + UE_thread, + (void *)UE), ""); + } printf("UE threads created by %ld\n", gettid()); #if 0 #if defined(ENABLE_USE_MME) extern volatile int start_UE; + while (start_UE == 0) { sleep(1); } + #endif #endif } @@ -329,292 +280,337 @@ void init_UE(int nb_inst) * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ static void *UE_thread_synch(void *arg) { - static int __thread UE_thread_synch_retval; - int i, hw_slot_offset; - PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE*) arg; - int current_band = 0; - int current_offset = 0; - sync_mode_t sync_mode = pbch; - int CC_id = UE->CC_id; - int freq_offset=0; - char threadname[128]; - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - if ( threads.sync != -1 ) - CPU_SET(threads.sync, &cpuset); - // this thread priority must be lower that the main acquisition thread - sprintf(threadname, "sync UE %d", UE->Mod_id); - init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname); + static int __thread UE_thread_synch_retval; + int i, hw_slot_offset; + PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; + int current_band = 0; + int current_offset = 0; + lte_frame_type_t current_type; + sync_mode_t sync_mode = pbch; + int CC_id = UE->CC_id; + int freq_offset=0; + char threadname[128]; + cpu_set_t cpuset; + CPU_ZERO(&cpuset); - UE->is_synchronized = 0; + if ( threads.sync != -1 ) + CPU_SET(threads.sync, &cpuset); - if (UE->UE_scan == 0) { - int ind; - for ( ind=0; - ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]); - ind++) { - current_band = eutra_bands[ind].band; - LOG_D(PHY, "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min); - if ( eutra_bands[ind].dl_min <= downlink_frequency[0][0] && eutra_bands[ind].dl_max >= downlink_frequency[0][0] ) { - for (i=0; i<4; i++) - uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min; - break; - } - } - AssertFatal( ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]), "Can't find EUTRA band for frequency"); + // this thread priority must be lower that the main acquisition thread + sprintf(threadname, "sync UE %d", UE->Mod_id); + init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname); + UE->is_synchronized = 0; - LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", - downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0], - oai_exit, openair0_cfg[0].rx_num_channels); + printf("UE_scan %d\n",UE->UE_scan); - for (i=0; irf_map.card].rx_num_channels; i++) { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = - downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - if (uplink_frequency_offset[CC_id][i] != 0) // - openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD; - else //FDD - openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD; - } - sync_mode = pbch; + if (UE->UE_scan == 0) { - } else { - current_band=0; - for (i=0; irf_map.card].rx_num_channels; i++) { - downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = - bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = - downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; - } + get_band(downlink_frequency[CC_id][0], &UE->frame_parms.eutra_band, &uplink_frequency_offset[CC_id][0], &UE->frame_parms.frame_type); + + LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", + downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0], + oai_exit, openair0_cfg[0].rx_num_channels); + + for (i=0; irf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + + if (uplink_frequency_offset[CC_id][i] != 0) // + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD; + else //FDD + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD; } - // AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); + sync_mode = pbch; + } else { + current_band=0; + LOG_E(PHY,"Fixme!\n"); + /* + for (i=0; irf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = + bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + } + */ + } - while (oai_exit==0) { - AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); - while (UE->proc.instance_cnt_synch < 0) - // the thread waits here most of the time - pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch ); - AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + // AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); - switch (sync_mode) { - case pss: - LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); - //lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); - current_offset += 20000000; // increase by 20 MHz + while (oai_exit==0) { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); - if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) { - current_band++; - current_offset=0; - } + while (UE->proc.instance_cnt_synch < 0) + // the thread waits here most of the time + pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch ); - if (current_band==bands_to_scan.nbands) { - current_band=0; - oai_exit=1; - } + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - for (i=0; irf_map.card].rx_num_channels; i++) { - downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; + switch (sync_mode) { + /* + case pss: + LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + //lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + current_offset += 20000000; // increase by 20 MHz - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; - if (UE->UE_scan_carrier) { - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - } - - } - - break; - - case pbch: - -#if DISABLE_LOG_X - printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); -#else - LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); -#endif - if (nr_initial_sync( UE, UE->mode ) == 0) { - - //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (10*UE->frame_parms.samples_per_subframe), 1, 1); - - hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe; - printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", - hw_slot_offset, - freq_offset, - UE->rx_total_gain_dB, - downlink_frequency[0][0]+freq_offset, - downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset, - UE->UE_scan_carrier ); - - - // rerun with new cell parameters and frequency-offset - for (i=0; irf_map.card].rx_num_channels; i++) { - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - if (UE->UE_scan_carrier == 1) { - if (freq_offset >= 0) - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset); - else - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset); - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; - downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; - freq_offset=0; - } - } - - // reconfigure for potentially different bandwidth - switch(UE->frame_parms.N_RB_DL) { - case 6: - openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; - openair0_cfg[UE->rf_map.card].rx_bw =.96e6; - openair0_cfg[UE->rf_map.card].tx_bw =.96e6; - // openair0_cfg[0].rx_gain[0] -= 12; - break; - case 25: - openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; - openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; - openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; - // openair0_cfg[0].rx_gain[0] -= 6; - break; - case 50: - openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; - openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; - openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; - // openair0_cfg[0].rx_gain[0] -= 3; - break; - case 100: - openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; - openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; - openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; - // openair0_cfg[0].rx_gain[0] -= 0; - break; - } - - if (UE->mode != loop_through_memory) { - UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); - //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); - //UE->rfdevice.trx_stop_func(&UE->rfdevice); - // sleep(1); - //nr_init_frame_parms_ue(&UE->frame_parms); - /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { - LOG_E(HW,"Could not start the device\n"); - oai_exit=1; - }*/ - } - - if (UE->UE_scan_carrier == 1) { - - UE->UE_scan_carrier = 0; - } else { - AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); - UE->is_synchronized = 1; - AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - - if( UE->mode == rx_dump_frame ) { - FILE *fd; - if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) { // this guarantees SIB1 is present - if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { - fwrite((void*)&UE->common_vars.rxdata[0][0], - sizeof(int32_t), - 10*UE->frame_parms.samples_per_subframe, - fd); - LOG_I(PHY,"Dummping Frame ... bye bye \n"); - fclose(fd); - exit(0); - } else { - LOG_E(PHY,"Cannot open file for writing\n"); - exit(0); - } - } else { - AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); - UE->is_synchronized = 0; - AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - - } - } - } - } else { - // initial sync failed - // calculate new offset and try again - - if (UE->UE_scan_carrier == 1) { - if (freq_offset >= 0) - freq_offset += 100; - freq_offset *= -1; - - if (abs(freq_offset) > 7500) { - LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" ); - FILE *fd; - if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) { - fwrite((void*)&UE->common_vars.rxdata[0][0], - sizeof(int32_t), - 10*UE->frame_parms.samples_per_subframe, - fd); - LOG_I(PHY,"Dummping Frame ... bye bye \n"); - fclose(fd); - exit(0); - } - //mac_xface->macphy_exit("No cell synchronization found, abandoning"); new mac - return &UE_thread_synch_retval; // not reached - } - } - -#if DISABLE_LOG_X - printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", - freq_offset, - UE->rx_total_gain_dB, - downlink_frequency[0][0]+freq_offset, - downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); -#else - LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", - freq_offset, - UE->rx_total_gain_dB, - downlink_frequency[0][0]+freq_offset, - downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); -#endif - - for (i=0; irf_map.card].rx_num_channels; i++) { - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset; - openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset; - openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - if (UE->UE_scan_carrier==1) - openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; - } - if (UE->mode != loop_through_memory) - UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); - }// initial_sync=0 - break; - case si: - default: - break; + if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) { + current_band++; + current_offset=0; } -#if 0 //defined XFORMS - if (do_forms) { - extern FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX]; - - phy_scope_UE(form_ue[0], - PHY_vars_UE_g[0][0], - 0,0,7); - } + if (current_band==bands_to_scan.nbands) { + current_band=0; + oai_exit=1; + } + + for (i=0; irf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + + if (UE->UE_scan_carrier) { + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } + } + + break; + */ + case pbch: +#if DISABLE_LOG_X + printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); +#else + LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); #endif - AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); - // indicate readiness - UE->proc.instance_cnt_synch--; - AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + if (nr_initial_sync( UE, UE->mode ) == 0) { + //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (10*UE->frame_parms.samples_per_slot), 1, 1); + freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync + hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_slot; + printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", + hw_slot_offset, + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset, + UE->UE_scan_carrier ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 ); - } // while !oai_exit + // rerun with new cell parameters and frequency-offset + for (i=0; irf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - return &UE_thread_synch_retval; + if (freq_offset >= 0) + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); + else + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset); + + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; + downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; + } + + // reconfigure for potentially different bandwidth + switch(UE->frame_parms.N_RB_DL) { + case 6: + openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; + openair0_cfg[UE->rf_map.card].rx_bw =.96e6; + openair0_cfg[UE->rf_map.card].tx_bw =.96e6; + // openair0_cfg[0].rx_gain[0] -= 12; + break; + + case 25: + openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; + openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; + openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; + // openair0_cfg[0].rx_gain[0] -= 6; + break; + + case 50: + openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; + openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; + openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; + // openair0_cfg[0].rx_gain[0] -= 3; + break; + + case 100: + openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; + openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; + openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; + // openair0_cfg[0].rx_gain[0] -= 0; + break; + } + + if (UE->mode != loop_through_memory) { + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); + //UE->rfdevice.trx_stop_func(&UE->rfdevice); + // sleep(1); + //nr_init_frame_parms_ue(&UE->frame_parms); + /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { + LOG_E(HW,"Could not start the device\n"); + oai_exit=1; + }*/ + } + + if (UE->UE_scan_carrier == 1) { + UE->UE_scan_carrier = 0; + } else { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + UE->is_synchronized = 1; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + + if( UE->mode == rx_dump_frame ) { + FILE *fd; + + if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) { // this guarantees SIB1 is present + if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) { + fwrite((void *)&UE->common_vars.rxdata[0][0], + sizeof(int32_t), + 10*UE->frame_parms.samples_per_subframe, + fd); + LOG_I(PHY,"Dummping Frame ... bye bye \n"); + fclose(fd); + exit(0); + } else { + LOG_E(PHY,"Cannot open file for writing\n"); + exit(0); + } + } else { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + UE->is_synchronized = 0; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + } + } + } + } else { + // initial sync failed + // calculate new offset and try again + if (UE->UE_scan_carrier == 1) { + if (freq_offset >= 0) + freq_offset += 100; + + freq_offset *= -1; + + if (abs(freq_offset) > 7500) { + LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" ); + FILE *fd; + + if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) { + fwrite((void *)&UE->common_vars.rxdata[0][0], + sizeof(int32_t), + 10*UE->frame_parms.samples_per_subframe, + fd); + LOG_I(PHY,"Dummping Frame ... bye bye \n"); + fclose(fd); + exit(0); + } + + //mac_xface->macphy_exit("No cell synchronization found, abandoning"); new mac + return &UE_thread_synch_retval; // not reached + } + } + +#if DISABLE_LOG_X + printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); +#else + LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); +#endif + + for (i=0; irf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + + if (UE->UE_scan_carrier==1) + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } + + if (UE->mode != loop_through_memory) + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + }// initial_sync=0 + + break; + + case si: + default: + break; + } + +#if 0 //defined XFORMS + + if (do_forms) { + extern FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX]; + phy_scope_UE(form_ue[0], + PHY_vars_UE_g[0][0], + 0,0,1); + } + +#endif + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + // indicate readiness + UE->proc.instance_cnt_synch--; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 ); + } // while !oai_exit + + return &UE_thread_synch_retval; +} + +void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { + // 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.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); + printf("Processing slot %d\n",proc->nr_tti_rx); +#ifdef UE_SLOT_PARALLELISATION + phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); +#else + phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode); + // printf(">>> nr_ue_pdcch_procedures ended\n"); +#endif + } + + if (UE->mac_enabled==1) { + // trigger L2 to run ue_scheduler thru IF module + // [TODO] mapping right after NR initial sync + if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) { + UE->ul_indication.module_id = 0; + UE->ul_indication.gNB_index = 0; + UE->ul_indication.cc_id = 0; + UE->ul_indication.frame = proc->frame_rx; + UE->ul_indication.slot = proc->nr_tti_rx; + UE->if_inst->ul_indication(&UE->ul_indication); + } + } } /*! @@ -626,146 +622,153 @@ static void *UE_thread_synch(void *arg) { */ static void *UE_thread_rxn_txnp4(void *arg) { - static __thread int UE_thread_rxtx_retval; - struct nr_rxtx_thread_data *rtd = arg; - UE_nr_rxtx_proc_t *proc = rtd->proc; - PHY_VARS_NR_UE *UE = rtd->UE; - int ret; + struct nr_rxtx_thread_data *rtd = arg; + UE_nr_rxtx_proc_t *proc = rtd->proc; + PHY_VARS_NR_UE *UE = rtd->UE; + //proc->counter_decoder = 0; + proc->instance_cnt_rxtx=-1; + proc->subframe_rx=proc->sub_frame_start; + proc->dci_err_cnt=0; + char threadname[256]; + sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + char timing_proc_name[256]; + sprintf(timing_proc_name,"Delay to process sub-frame proc %d",proc->sub_frame_start); - //proc->counter_decoder = 0; - proc->instance_cnt_rxtx=-1; - proc->subframe_rx=proc->sub_frame_start; + if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 ) + CPU_SET(threads.one, &cpuset); - proc->dci_err_cnt=0; - char threadname[256]; - sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start); - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - char timing_proc_name[256]; - sprintf(timing_proc_name,"Delay to process sub-frame proc %d",proc->sub_frame_start); + if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 ) + CPU_SET(threads.two, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 ) - CPU_SET(threads.one, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 ) - CPU_SET(threads.two, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 ) - CPU_SET(threads.three, &cpuset); - //CPU_SET(threads.three, &cpuset); - init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, - threadname); + if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 ) + CPU_SET(threads.three, &cpuset); - while (!oai_exit) { - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); - exit_fun("nothing to add"); - } - while (proc->instance_cnt_rxtx < 0) { - // most of the time, the thread is waiting here - pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); - } - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" ); - exit_fun("nothing to add"); - } + //CPU_SET(threads.three, &cpuset); + init_thread(900000,1000000, FIFO_PRIORITY-1, &cpuset, + threadname); -// initRefTimes(t2); -// initRefTimes(t3); -// pickTime(current); -// updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)"); + while (!oai_exit) { + AssertFatal( 0 == pthread_mutex_lock(&proc->mutex_rxtx), "[SCHED][UE] error locking mutex for UE RXTX\n" ); - - - // 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; - nr_ue_scheduled_response(&UE_mac->scheduled_response); - -#ifdef UE_SLOT_PARALLELISATION - phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); -#else - phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode); - // printf(">>> nr_ue_pdcch_procedures ended\n"); - -#endif - } - -#if UE_TIMING_TRACE - start_meas(&UE->generic_stat); -#endif - //printf(">>> mac init\n"); - - if (UE->mac_enabled==1) { - - // trigger L2 to run ue_scheduler thru IF module - // [TODO] mapping right after NR initial sync - if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL){ - UE->ul_indication.module_id = 0; - UE->ul_indication.gNB_index = 0; - UE->ul_indication.cc_id = 0; - UE->ul_indication.frame = proc->frame_rx; - UE->ul_indication.slot = proc->nr_tti_rx; - - UE->if_inst->ul_indication(&UE->ul_indication); - } - } - -#if UE_TIMING_TRACE - stop_meas(&UE->generic_stat); -#endif - //printf(">>> mac ended\n"); - - // Prepare the future Tx data -#if 0 -#ifndef NO_RAT_NR - if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_UPLINK_SLOT) -#else - if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || - (UE->frame_parms.frame_type == FDD) ) -#endif - if (UE->mode != loop_through_memory) - phy_procedures_nrUE_TX(UE,proc,0,0,UE->mode,no_relay); - //phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay); -#endif -#if 0 - if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) && - (UE->frame_parms.frame_type == TDD)) - if (UE->mode != loop_through_memory) - //phy_procedures_UE_S_TX(UE,0,0,no_relay); - updateTimes(current, &t3, 10000, timing_proc_name); -#endif - - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" ); - exit_fun("noting to add"); - } - proc->instance_cnt_rxtx--; -#if BASIC_SIMULATOR - if (pthread_cond_signal(&proc->cond_rxtx) != 0) abort(); -#endif - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" ); - exit_fun("noting to add"); - } + while (proc->instance_cnt_rxtx < 0) { + // most of the time, the thread is waiting here + pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); } -// thread finished - free(arg); - return &UE_thread_rxtx_retval; + AssertFatal ( 0== pthread_mutex_unlock(&proc->mutex_rxtx), "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" ); + processSubframeRX(UE, proc); + //printf(">>> mac ended\n"); + // Prepare the future Tx data +#if 0 +#ifndef NO_RAT_NR + + if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_UPLINK_SLOT) +#else + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || + (UE->frame_parms.frame_type == FDD) ) +#endif + if (UE->mode != loop_through_memory) + phy_procedures_nrUE_TX(UE,proc,0,0,UE->mode,no_relay); + + //phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay); +#endif +#if 0 + + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) && + (UE->frame_parms.frame_type == TDD)) + if (UE->mode != loop_through_memory) + //phy_procedures_UE_S_TX(UE,0,0,no_relay); + updateTimes(current, &t3, 10000, timing_proc_name); + +#endif + AssertFatal( 0 == pthread_mutex_lock(&proc->mutex_rxtx), "[SCHED][UE] error locking mutex for UE RXTX\n" ); + proc->instance_cnt_rxtx--; +#if BASIC_SIMULATOR + + if (pthread_cond_signal(&proc->cond_rxtx) != 0) abort(); + +#endif + AssertFatal (0 == pthread_mutex_unlock(&proc->mutex_rxtx), "[SCHED][UE] error unlocking mutex for UE RXTX\n" ); + } + + // thread finished + free(arg); + return NULL; +} + +void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + void *rxp[NB_ANTENNAS_RX]; + + for(int x=0; x<10; x++) { + for (int i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe; + + AssertFatal( UE->frame_parms.samples_per_subframe == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + rxp, + UE->frame_parms.samples_per_subframe, + UE->frame_parms.nb_antennas_rx), "readFrame error"); + } + +} + +void trashFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + void *dummy_rx[UE->frame_parms.nb_antennas_rx]; + + for (int i=0; iframe_parms.nb_antennas_rx; i++) + dummy_rx[i]=malloc16(UE->frame_parms.samples_per_subframe*4); + + for (int sf=0; sfframe_parms.samples_per_subframe == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + dummy_rx, + UE->frame_parms.samples_per_subframe, + UE->frame_parms.nb_antennas_rx), "trashFrame error"); + //usleep(500); // this sleep improves in the case of simulated RF and doesn't harm with true radio + } + + for (int i=0; iframe_parms.nb_antennas_rx; i++) + free(dummy_rx[i]); +} + +void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + if (UE->no_timing_correction==0) { + LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + + for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { + int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; + AssertFatal(unitTransfer == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx),"syncInFrame error"); + } + } +} + +int computeSamplesShift(PHY_VARS_NR_UE *UE) { + if ( getenv("RFSIMULATOR") != 0) { + LOG_E(PHY,"SET rx_offset %d \n",UE->rx_offset); + //UE->rx_offset_diff=0; + return 0; + } + + // compute TO compensation that should be applied for this frame + if ( UE->rx_offset < 5*UE->frame_parms.samples_per_slot && + UE->rx_offset > 0 ) + return -1 ; + + if ( UE->rx_offset > 5*UE->frame_parms.samples_per_slot && + UE->rx_offset < 10*UE->frame_parms.samples_per_slot ) + return 1; + + return 0; } /*! @@ -779,356 +782,266 @@ static void *UE_thread_rxn_txnp4(void *arg) { */ void *UE_thread(void *arg) { + PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; + // int tx_enabled = 0; + openair0_timestamp timestamp; + void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX]; + int start_rx_stream = 0; + int i; + char threadname[128]; + int th_id; + const uint16_t table_sf_slot[20] = {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9}; - PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; - // int tx_enabled = 0; - int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_subframe] __attribute__((aligned(32))); - openair0_timestamp timestamp; - void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX]; - int start_rx_stream = 0; - int i; - char threadname[128]; - int th_id; - UE->proc.proc_rxtx[0].counter_decoder = 0; - UE->proc.proc_rxtx[1].counter_decoder = 0; - UE->proc.proc_rxtx[2].counter_decoder = 0; + for (int i=0; i< RX_NB_TH_MAX; i++ ) + UE->proc.proc_rxtx[i].counter_decoder = 0; - static uint8_t thread_idx = 0; + static uint8_t thread_idx = 0; + cpu_set_t cpuset; + CPU_ZERO(&cpuset); - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - if ( threads.main != -1 ) - CPU_SET(threads.main, &cpuset); - sprintf(threadname, "Main UE %d", UE->Mod_id); - init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,threadname); - - if ((oaisim_flag == 0) && (UE->mode !=loop_through_memory)) - AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); - UE->rfdevice.host_type = RAU_HOST; + if ( threads.main != -1 ) + CPU_SET(threads.main, &cpuset); - init_UE_threads(UE); + sprintf(threadname, "Main UE %d", UE->Mod_id); + init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,threadname); + if ((oaisim_flag == 0) && (UE->mode !=loop_through_memory)) + AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); + + UE->rfdevice.host_type = RAU_HOST; + init_UE_threads(UE); #ifdef NAS_UE - //MessageDef *message_p; - //message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); - //itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p); + //MessageDef *message_p; + //message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE); + //itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p); #endif + int nb_slot_frame = 10*UE->frame_parms.slots_per_subframe; + int slot_nr=-1; - int subframe_nr=-1; - //int cumulated_shift=0; - if ((oaisim_flag == 0) && (UE->mode != loop_through_memory)) - AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); - while (!oai_exit) { - AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); - int instance_cnt_synch = UE->proc.instance_cnt_synch; - int is_synchronized = UE->is_synchronized; - AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + //int cumulated_shift=0; + if ((oaisim_flag == 0) && (UE->mode != loop_through_memory)) + AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); - if (is_synchronized == 0) { + while (!oai_exit) { + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); + int instance_cnt_synch = UE->proc.instance_cnt_synch; + int is_synchronized = UE->is_synchronized; + AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + + if (is_synchronized == 0) { #if BASIC_SIMULATOR - while (!((instance_cnt_synch = UE->proc.instance_cnt_synch) < 0)) { - printf("ue sync not ready\n"); - usleep(500*1000); - } + + while (!((instance_cnt_synch = UE->proc.instance_cnt_synch) < 0)) { + printf("ue sync not ready\n"); + usleep(500*1000); + } + #endif - if (instance_cnt_synch < 0) { // we can invoke the synch - // grab 10 ms of signal and wakeup synch thread - for (int i=0; iframe_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&UE->common_vars.rxdata[i][0]; + if (UE->mode != loop_through_memory) { + if (instance_cnt_synch < 0) { // we can invoke the synch + // grab 10 ms of signal and wakeup synch thread + readFrame(UE, ×tamp); + AssertFatal( 0 == pthread_mutex_lock(&UE->proc.mutex_synch), ""); + AssertFatal( 0 == ++UE->proc.instance_cnt_synch, "[SCHED][UE] UE sync thread busy!!\n" ); + AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), ""); + AssertFatal( 0 == pthread_mutex_unlock(&UE->proc.mutex_synch), ""); + } else { + // grab 10 ms of signal into dummy buffer to wait result of sync detection + trashFrame(UE, ×tamp); + } + } - if (UE->mode != loop_through_memory) - AssertFatal( UE->frame_parms.samples_per_subframe*10== - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_subframe*10, - UE->frame_parms.nb_antennas_rx), "error reading samples"); + continue; + } - AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); - instance_cnt_synch = ++UE->proc.instance_cnt_synch; - if (instance_cnt_synch == 0) { - AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), ""); - } else { - LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" ); - exit_fun("nothing to add"); - } - AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - } else { -#if OAISIM - (void)dummy_rx; /* avoid gcc warnings */ - usleep(500); -#else - // grab 10 ms of signal into dummy buffer - if (UE->mode != loop_through_memory) { - for (int i=0; iframe_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&dummy_rx[i][0]; - for (int sf=0; sfframe_parms.samples_per_subframe== - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_subframe, - UE->frame_parms.nb_antennas_rx), "error reading samples"); - } -#endif - } + if (start_rx_stream==0) { + start_rx_stream=1; - } // UE->is_synchronized==0 - else { - if (start_rx_stream==0) { - start_rx_stream=1; - if (UE->mode != loop_through_memory) { - if (UE->no_timing_correction==0) { - LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - AssertFatal(UE->rx_offset == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void**)UE->common_vars.rxdata, - UE->rx_offset, - UE->frame_parms.nb_antennas_rx),""); - } - UE->rx_offset=0; - UE->time_sync_cell=0; - UE->proc.proc_rxtx[0].frame_rx++; - //UE->proc.proc_rxtx[1].frame_rx++; - for (th_id=1; th_id < RX_NB_TH; th_id++) { - UE->proc.proc_rxtx[th_id].frame_rx = UE->proc.proc_rxtx[0].frame_rx; - } - - //printf("first stream frame rx %d\n",UE->proc.proc_rxtx[0].frame_rx); + if (UE->mode != loop_through_memory) { + syncInFrame(UE, ×tamp); + UE->rx_offset=0; + UE->time_sync_cell=0; + UE->proc.proc_rxtx[0].frame_rx++; - // read in first symbol - AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void**)UE->common_vars.rxdata, - UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, - UE->frame_parms.nb_antennas_rx),""); - //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0), 1, 1); - //nr_slot_fep(UE,0, 0, 0, 1, 1, NR_PDCCH_EST); - } //UE->mode != loop_through_memory - else - rt_sleep_ns(1000*1000); + //UE->proc.proc_rxtx[1].frame_rx++; + for (th_id=1; th_id < RX_NB_TH; th_id++) { + UE->proc.proc_rxtx[th_id].frame_rx = UE->proc.proc_rxtx[0].frame_rx; + } - } else { - thread_idx++; - if(thread_idx>=RX_NB_TH) - thread_idx = 0; + //printf("first stream frame rx %d\n",UE->proc.proc_rxtx[0].frame_rx); + // read in first symbol + AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void **)UE->common_vars.rxdata, + UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx),"first symbol read error"); + //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0), 1, 1); + //nr_slot_fep(UE,0, 0, 0, 1, NR_PDCCH_EST); + } //UE->mode != loop_through_memory + else + rt_sleep_ns(1000*1000); - subframe_nr++; - subframe_nr %= NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - UE_nr_rxtx_proc_t *proc = &UE->proc.proc_rxtx[thread_idx]; - // update thread index for received subframe - UE->current_thread_id[subframe_nr] = thread_idx; + continue; + } + thread_idx++; + thread_idx%=RX_NB_TH; + //printf("slot_nr %d nb slot frame %d\n",slot_nr, nb_slot_frame); + slot_nr++; + slot_nr %= nb_slot_frame; + UE_nr_rxtx_proc_t *proc = &UE->proc.proc_rxtx[thread_idx]; + // update thread index for received subframe + UE->current_thread_id[slot_nr] = thread_idx; #if BASIC_SIMULATOR - { - int t; - for (t = 0; t < RX_NB_TH; t++) { - UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[t]; - pthread_mutex_lock(&proc->mutex_rxtx); - while (proc->instance_cnt_rxtx >= 0) pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); - pthread_mutex_unlock(&proc->mutex_rxtx); - } - } + + for (int t = 0; t < RX_NB_TH; t++) { + UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[t]; + pthread_mutex_lock(&proc->mutex_rxtx); + + while (proc->instance_cnt_rxtx >= 0) pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); + + pthread_mutex_unlock(&proc->mutex_rxtx); + } + #endif + LOG_D(PHY,"Process slot %d thread Idx %d \n", slot_nr, UE->current_thread_id[slot_nr]); + proc->nr_tti_rx=slot_nr; + proc->subframe_rx=table_sf_slot[slot_nr]; + proc->frame_tx = proc->frame_rx; + proc->nr_tti_tx= slot_nr + DURATION_RX_TO_TX; - LOG_D(PHY,"Process subframe %d thread Idx %d \n", subframe_nr, UE->current_thread_id[subframe_nr]); + if (proc->nr_tti_tx > nb_slot_frame) { + proc->frame_tx = (proc->frame_tx + 1)%MAX_FRAME_NUMBER; + proc->nr_tti_tx %= nb_slot_frame; + } + if(slot_nr == 0) { + UE->proc.proc_rxtx[0].frame_rx++; - if (UE->mode != loop_through_memory) { - for (i=0; iframe_parms.nb_antennas_rx; i++) - rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+ - UE->frame_parms.nb_prefix_samples0+ - subframe_nr*UE->frame_parms.samples_per_subframe]; - for (i=0; iframe_parms.nb_antennas_tx; i++) - txp[i] = (void*)&UE->common_vars.txdata[i][((subframe_nr+2)%NR_NUMBER_OF_SUBFRAMES_PER_FRAME)*UE->frame_parms.samples_per_subframe]; + //UE->proc.proc_rxtx[1].frame_rx++; + for (th_id=1; th_id < RX_NB_TH; th_id++) { + UE->proc.proc_rxtx[th_id].frame_rx = UE->proc.proc_rxtx[0].frame_rx; + } + } - int readBlockSize, writeBlockSize; - if (subframe_nr<(NR_NUMBER_OF_SUBFRAMES_PER_FRAME - 1)) { - readBlockSize=UE->frame_parms.samples_per_subframe; - writeBlockSize=UE->frame_parms.samples_per_subframe; - } else { - // set TO compensation to zero - UE->rx_offset_diff = 0; - // compute TO compensation that should be applied for this frame - if ( UE->rx_offset < 5*UE->frame_parms.samples_per_subframe && - UE->rx_offset > 0 ) - UE->rx_offset_diff = -1 ; - if ( UE->rx_offset > 5*UE->frame_parms.samples_per_subframe && - UE->rx_offset < 10*UE->frame_parms.samples_per_subframe ) - UE->rx_offset_diff = 1; + if (UE->mode != loop_through_memory) { + for (i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+ + UE->frame_parms.nb_prefix_samples0+ + slot_nr*UE->frame_parms.samples_per_slot]; - LOG_D(PHY,"AbsSubframe %d.%d TTI SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,subframe_nr,UE->rx_offset_diff,UE->rx_offset); - readBlockSize=UE->frame_parms.samples_per_subframe - - UE->frame_parms.ofdm_symbol_size - - UE->frame_parms.nb_prefix_samples0 - - UE->rx_offset_diff; - writeBlockSize=UE->frame_parms.samples_per_subframe - - UE->rx_offset_diff; - } + for (i=0; iframe_parms.nb_antennas_tx; i++) + txp[i] = (void *)&UE->common_vars.txdata[i][((slot_nr+2)%NR_NUMBER_OF_SUBFRAMES_PER_FRAME)*UE->frame_parms.samples_per_slot]; - AssertFatal(readBlockSize == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - readBlockSize, - UE->frame_parms.nb_antennas_rx),""); - AssertFatal( writeBlockSize == - UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+ - (2*UE->frame_parms.samples_per_subframe) - - UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - - openair0_cfg[0].tx_sample_advance, - txp, - writeBlockSize, - UE->frame_parms.nb_antennas_tx, - 1),""); - - if( subframe_nr==(NR_NUMBER_OF_SUBFRAMES_PER_FRAME-1)) { - // read in first symbol of next frame and adjust for timing drift - int first_symbols=writeBlockSize-readBlockSize; - if ( first_symbols > 0 ) - AssertFatal(first_symbols == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void**)UE->common_vars.rxdata, - first_symbols, - UE->frame_parms.nb_antennas_rx),""); - if ( first_symbols <0 ) - LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols); - } + int readBlockSize, writeBlockSize; - pickTime(gotIQs); - // operate on thread sf mod 2 - AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,""); - if(subframe_nr == 0) { - UE->proc.proc_rxtx[0].frame_rx++; - //UE->proc.proc_rxtx[1].frame_rx++; - for (th_id=1; th_id < RX_NB_TH; th_id++) { - UE->proc.proc_rxtx[th_id].frame_rx = UE->proc.proc_rxtx[0].frame_rx; - } + if (slot_nr<(nb_slot_frame - 1)) { + readBlockSize=UE->frame_parms.samples_per_slot; + writeBlockSize=UE->frame_parms.samples_per_slot; + } else { + UE->rx_offset_diff = computeSamplesShift(UE); + readBlockSize=UE->frame_parms.samples_per_slot - + UE->frame_parms.ofdm_symbol_size - + UE->frame_parms.nb_prefix_samples0 - + UE->rx_offset_diff; + writeBlockSize=UE->frame_parms.samples_per_slot - + UE->rx_offset_diff; + } + + AssertFatal(readBlockSize == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + readBlockSize, + UE->frame_parms.nb_antennas_rx),"read error"); + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+ + (2*UE->frame_parms.samples_per_slot) - + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - + openair0_cfg[0].tx_sample_advance, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + 1),"write error"); + + if( slot_nr==(nb_slot_frame-1)) { + // read in first symbol of next frame and adjust for timing drift + int first_symbols=writeBlockSize-readBlockSize; + + if ( first_symbols > 0 ) + AssertFatal(first_symbols == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void **)UE->common_vars.rxdata, + first_symbols, + UE->frame_parms.nb_antennas_rx),"first symbols read error"); + else + LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols); + } + + pickTime(gotIQs); + // operate on thread sf mod 2 + AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,""); #ifdef SAIF_ENABLED - if (!(proc->frame_rx%4000)) - { - printf("frame_rx=%d rx_thread_busy=%ld - rate %8.3f\n", - proc->frame_rx, g_ue_rx_thread_busy, - (float)g_ue_rx_thread_busy/(proc->frame_rx*10+1)*100.0); - fflush(stdout); - } + + if (!(proc->frame_rx%4000)) { + printf("frame_rx=%d rx_thread_busy=%ld - rate %8.3f\n", + proc->frame_rx, g_ue_rx_thread_busy, + (float)g_ue_rx_thread_busy/(proc->frame_rx*10+1)*100.0); + fflush(stdout); + } + #endif - } - //UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs); - //UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs); - for (th_id=0; th_id < RX_NB_TH; th_id++) { - UE->proc.proc_rxtx[th_id].gotIQs=readTime(gotIQs); - } - proc->nr_tti_rx=subframe_nr; - proc->subframe_rx=subframe_nr; - - proc->frame_tx = proc->frame_rx; - proc->nr_tti_tx= subframe_nr + DURATION_RX_TO_TX; - if (proc->nr_tti_tx > NR_NUMBER_OF_SUBFRAMES_PER_FRAME) { - proc->frame_tx = (proc->frame_tx + 1)%MAX_FRAME_NUMBER; - proc->nr_tti_tx %= NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - } - proc->subframe_tx=proc->nr_tti_rx; - proc->timestamp_tx = timestamp+ - (DURATION_RX_TO_TX*UE->frame_parms.samples_per_subframe)- - UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; + //UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs); + //UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs); + for (th_id=0; th_id < RX_NB_TH; th_id++) { + UE->proc.proc_rxtx[th_id].gotIQs=readTime(gotIQs); + } - proc->instance_cnt_rxtx++; - LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx); - if (proc->instance_cnt_rxtx == 0) { - if (pthread_cond_signal(&proc->cond_rxtx) != 0) { - LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id); - exit_fun("nothing to add"); - } - } else { + proc->subframe_tx=proc->nr_tti_rx; + proc->timestamp_tx = timestamp+ + (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot)- + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; + proc->instance_cnt_rxtx++; + LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx); + + if (proc->instance_cnt_rxtx != 0) { #ifdef SAIF_ENABLED - g_ue_rx_thread_busy++; + g_ue_rx_thread_busy++; #endif - LOG_E( PHY, "[SCHED][UE %d] !! UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx); - if (proc->instance_cnt_rxtx > 4) - { - char exit_fun_string[256]; - sprintf(exit_fun_string,"[SCHED][UE %d] !!! UE instance_cnt_rxtx > 2 (IC %d) (Proc %d)!!", - UE->Mod_id, proc->instance_cnt_rxtx, - UE->current_thread_id[subframe_nr]); - printf("%s\n",exit_fun_string); - fflush(stdout); - sleep(1); - exit_fun(exit_fun_string); - } - } - AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,""); - AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,""); -// initRefTimes(t1); -// initStaticTime(lastTime); -// updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)"); -// pickStaticTime(lastTime); - } //UE->mode != loop_through_memory - else { - proc->nr_tti_rx=subframe_nr; - proc->subframe_rx=subframe_nr; - if(subframe_nr == 0) { - for (th_id=0; th_id < RX_NB_TH; th_id++) { - UE->proc.proc_rxtx[th_id].frame_rx++; - } - } - proc->frame_tx = proc->frame_rx; - proc->nr_tti_tx= subframe_nr + DURATION_RX_TO_TX; - if (proc->nr_tti_tx > NR_NUMBER_OF_SUBFRAMES_PER_FRAME) { - proc->frame_tx = (proc->frame_tx + 1)%MAX_FRAME_NUMBER; - proc->nr_tti_tx %= NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - } - proc->subframe_tx=proc->nr_tti_tx; + if ( getenv("RFSIMULATOR") != NULL ) { + do { + AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) == 0, ""); + usleep(100); + AssertFatal (pthread_mutex_lock(&proc->mutex_rxtx) == 0, ""); + } while ( proc->instance_cnt_rxtx >= 0); + } else + LOG_E( PHY, "[SCHED][UE %d] !! UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx); - 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 + AssertFatal( proc->instance_cnt_rxtx <= 4, "[SCHED][UE %d] !!! UE instance_cnt_rxtx > 2 (IC %d) (Proc %d)!!", + UE->Mod_id, proc->instance_cnt_rxtx, + UE->current_thread_id[slot_nr]); + } - NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); - UE_mac->scheduled_response.dl_config = &UE->dcireq.dl_config_req; - nr_ue_scheduled_response(&UE_mac->scheduled_response); + AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0,""); + AssertFatal (pthread_mutex_unlock(&proc->mutex_rxtx) ==0,""); + // initRefTimes(t1); + // initStaticTime(lastTime); + // updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)"); + // pickStaticTime(lastTime); + } //UE->mode != loop_through_memory + else { + processSubframeRX(UE,proc); + getchar(); + } // else loop_through_memory + } // while !oai_exit - - printf("Processing subframe %d\n",proc->subframe_rx); - phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode); - } - - if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL){ - UE->ul_indication.module_id = 0; - UE->ul_indication.gNB_index = 0; - UE->ul_indication.cc_id = 0; - UE->ul_indication.frame = proc->frame_rx; - UE->ul_indication.slot = proc->nr_tti_rx; - - UE->if_inst->ul_indication(&UE->ul_indication); - } - - getchar(); - } // else loop_through_memory - } // start_rx_stream==1 - } // UE->is_synchronized==1 - - } // while !oai_exit - return NULL; + return NULL; } /*! @@ -1144,84 +1057,79 @@ void *UE_thread(void *arg) { * and the locking between them. */ void init_UE_threads(PHY_VARS_NR_UE *UE) { - struct nr_rxtx_thread_data *rtd; + struct nr_rxtx_thread_data *rtd; + pthread_attr_init (&UE->proc.attr_ue); + pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN); + pthread_mutex_init(&UE->proc.mutex_synch,NULL); + pthread_cond_init(&UE->proc.cond_synch,NULL); + UE->proc.instance_cnt_synch = -1; - pthread_attr_init (&UE->proc.attr_ue); - pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN); + // the threads are not yet active, therefore access is allowed without locking + for (int i=0; iproc.mutex_synch,NULL); - pthread_cond_init(&UE->proc.cond_synch,NULL); - UE->proc.instance_cnt_synch = -1; - - // the threads are not yet active, therefore access is allowed without locking - int nb_threads=RX_NB_TH; - for (int i=0; iUE = UE; - rtd->proc = &UE->proc.proc_rxtx[i]; - - pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL); - pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL); - UE->proc.proc_rxtx[i].sub_frame_start=i; - UE->proc.proc_rxtx[i].sub_frame_step=nb_threads; - printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i); - pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd); + if (rtd == NULL) abort(); + rtd->UE = UE; + rtd->proc = &UE->proc.proc_rxtx[i]; + pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL); + UE->proc.proc_rxtx[i].sub_frame_start=i; + UE->proc.proc_rxtx[i].sub_frame_step=RX_NB_TH; + printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,RX_NB_TH, i); + pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd); #ifdef UE_DLSCH_PARALLELISATION - pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_dlsch_td,NULL); - pthread_cond_init(&UE->proc.proc_rxtx[i].cond_dlsch_td,NULL); - pthread_create(&UE->proc.proc_rxtx[i].pthread_dlsch_td,NULL,nr_dlsch_decoding_2thread0, rtd); - //thread 2 - pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_dlsch_td1,NULL); - pthread_cond_init(&UE->proc.proc_rxtx[i].cond_dlsch_td1,NULL); - pthread_create(&UE->proc.proc_rxtx[i].pthread_dlsch_td1,NULL,nr_dlsch_decoding_2thread1, rtd); + pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_dlsch_td,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[i].cond_dlsch_td,NULL); + pthread_create(&UE->proc.proc_rxtx[i].pthread_dlsch_td,NULL,nr_dlsch_decoding_2thread0, rtd); + //thread 2 + pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_dlsch_td1,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[i].cond_dlsch_td1,NULL); + pthread_create(&UE->proc.proc_rxtx[i].pthread_dlsch_td1,NULL,nr_dlsch_decoding_2thread1, rtd); #endif - #ifdef UE_SLOT_PARALLELISATION - //pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL); - //pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL); - //pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd); - - pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL); - pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL); - pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd); + //pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL); + //pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL); + //pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd); + pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL); + pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL); + pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd); #endif + } - } - pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE); + pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void *)UE); } #ifdef OPENAIR2 -/* -void fill_ue_band_info(void) { + /* + void fill_ue_band_info(void) { - UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability; - int i,j; + UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability; + int i,j; - bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count; + bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count; - for (i=0; irf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) { - memcpy(&bands_to_scan.band_info[i], - &eutra_bands[j], - sizeof(eutra_band_t)); + for (j=0; jrf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) { + memcpy(&bands_to_scan.band_info[i], + &eutra_bands[j], + sizeof(eutra_band_t)); - printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n", - bands_to_scan.band_info[i].band, - UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA, - bands_to_scan.band_info[i].dl_min, - bands_to_scan.band_info[i].dl_max, - bands_to_scan.band_info[i].ul_min, - bands_to_scan.band_info[i].ul_max, - (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD"); - break; - } - } -}*/ + printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n", + bands_to_scan.band_info[i].band, + UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA, + bands_to_scan.band_info[i].dl_min, + bands_to_scan.band_info[i].dl_max, + bands_to_scan.band_info[i].ul_min, + bands_to_scan.band_info[i].ul_max, + (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD"); + break; + } + } + }*/ #endif /* diff --git a/targets/RT/USER/nr-uesoftmodem.c b/targets/RT/USER/nr-uesoftmodem.c index 81f46d31b3..226010a1db 100644 --- a/targets/RT/USER/nr-uesoftmodem.c +++ b/targets/RT/USER/nr-uesoftmodem.c @@ -130,6 +130,7 @@ static char *itti_dump_file = NULL; int UE_scan = 0; int UE_scan_carrier = 0; +int UE_fo_compensation = 0; runmode_t mode = normal_txrx; FILE *input_fd=NULL; @@ -660,7 +661,7 @@ void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { config[CC_id]->rf_config.dl_carrier_bandwidth.value = 106; config[CC_id]->rf_config.ul_carrier_bandwidth.value = 106; config[CC_id]->sch_config.physical_cell_id.value = 0; - + frame_parms[CC_id]->eutra_band = 78; frame_parms[CC_id]->frame_type = FDD; frame_parms[CC_id]->tdd_config = 3; //frame_parms[CC_id]->tdd_config_S = 0; @@ -931,14 +932,14 @@ int main( int argc, char **argv ) { 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); - //init_ul_hopping(frame_parms[CC_id]); - //phy_init_nr_top(frame_parms[CC_id]); - } + 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); - for (CC_id=0; CC_idprach_config_common.prach_ConfigInfo.prach_ConfigIndex, frame_parms->frame_type); - // N_ZC = (prach_fmt <4)?839:139; + //init_ul_hopping(frame_parms[CC_id]); + //phy_init_nr_top(frame_parms[CC_id]); + + //init prach for openair1 test + // prach_fmt = get_prach_fmt(frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, frame_parms->frame_type); + // N_ZC = (prach_fmt <4)?839:139; } NB_UE_INST=1; @@ -978,29 +979,23 @@ int main( int argc, char **argv ) { UE[CC_id]->UE_scan = UE_scan; UE[CC_id]->UE_scan_carrier = UE_scan_carrier; + UE[CC_id]->UE_fo_compensation = UE_fo_compensation; UE[CC_id]->mode = mode; printf("UE[%d]->mode = %d\n",CC_id,mode); for (uint8_t i=0; ipdcch_vars[i][0]->agregationLevel = agregation_Level; //UE[CC_id]->pdcch_vars[i][0]->dciFormat = dci_Format; - } /*compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common, UE[CC_id]->frame_parms.frame_type, UE[CC_id]->X_u);*/ if (UE[CC_id]->mac_enabled == 1) - { - UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234; - UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234; - } + UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1234; else - { - UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235; - UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235; - } - + UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1235; + } UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; diff --git a/targets/RT/USER/nr-uesoftmodem.h b/targets/RT/USER/nr-uesoftmodem.h index 816e753086..7f96480b2b 100644 --- a/targets/RT/USER/nr-uesoftmodem.h +++ b/targets/RT/USER/nr-uesoftmodem.h @@ -55,6 +55,7 @@ #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" @@ -135,6 +136,7 @@ {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \ {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \ {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \ +{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&UE_fo_compensation, defintval:0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ {"r" , CONFIG_HLP_PRB, 0, iptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \