diff --git a/.gitignore b/.gitignore index 8f8ff1f454..ff947966a2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,9 @@ targets/bin/ # vscode .vscode + +# Tags for vim/global +GPATH +GRTAGS +GTAGS +tags diff --git a/NOTICE.md b/NOTICE.md index 96b5d4c552..39dd33795d 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -21,3 +21,7 @@ The Regents of the University of California: BSD 3-Clause Licence. Niels Provos : BSD 2-Clause Licence. +## Credits for source code openair3/GTPV1-U/nw-gtpv1u: ## + +Amit Chawre : BSD 2-Clause Licence. + diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index 8dfa5c4ec4..7e9e3800db 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -30,7 +30,6 @@ def sendSocialMediaMessage(pipeChannel, pipeColor, pipeMessage) { } } -def doRedHatBuild = false def doFlexranCtrlTest = false // Location of the executor node @@ -66,7 +65,8 @@ pipeline { "Test-IF4p5-TDD-Band38-Multi-RRU", "Test-eNB-OAI-UE-FDD-Band7", "Test-Mono-FDD-Band13-X2-HO", - "Test-TDD-Band78-gNB-NR-UE" + "Test-TDD-Band78-gNB-NR-UE", + "Test-OCP-FDD-Band7" ]) ansiColor('xterm') } @@ -84,21 +84,6 @@ pipeline { echo "Platform is ${env.TESTPLATFORM_OWNER}" } - if (params.RedHatRemoteServer == null) { - allParametersPresent = false - } - if (params.RedHatRemoteCredentials == null) { - allParametersPresent = false - } - if (params.RedHatWorkingPath == null) { - allParametersPresent = false - } - if (allParametersPresent) { - echo "Performing Red Hat Build" - doRedHatBuild = true - } else { - doRedHatBuild = false - } if (params.FlexRanRtcGitLabRepository_Credentials != null) { doFlexranCtrlTest = true } @@ -278,7 +263,7 @@ pipeline { steps { gitlabCommitStatus(name: "Build eNB-USRP") { timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" + sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" } } } @@ -310,28 +295,6 @@ pipeline { } } } - stage ("Build eNB-USRP on Red Hat") { - when { - expression {doRedHatBuild} - } - steps { - gitlabCommitStatus(name: "Build eNB-USRP-RHE") { - script { - try { - withCredentials([ - [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.RedHatRemoteCredentials}", usernameVariable: 'RH_Username', passwordVariable: 'RH_Password'] - ]) { - timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/buildOnRH.sh --workspace $WORKSPACE --job-name ${JOB_NAME} --build-id ${BUILD_ID} --remote-host ${params.RedHatRemoteServer} --remote-path ${params.RedHatWorkingPath} --remote-user-name ${RH_Username} --remote-password ${RH_Password}" - } - } - } catch (Exception e) { - echo "Red Hat build failed but we could keep running pipeline if all ubuntu-based build passed" - } - } - } - } - } } post { failure { @@ -683,6 +646,25 @@ pipeline { } } } + stage ("Test OAI OCP-eNB - FDD - Band 7 - B210") { + steps { + script { + triggerSlaveJob ('OCPeNB-FDD-Band7-B210', 'Test-OCP-FDD-Band7') + } + } + post { + always { + script { + finalizeSlaveJob('OCPeNB-FDD-Band7-B210') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } } post { always { diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py new file mode 100644 index 0000000000..84b3a84514 --- /dev/null +++ b/ci-scripts/args_parse.py @@ -0,0 +1,229 @@ + +# * 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 +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import Libs +#----------------------------------------------------------- +import sys # arg +import re # reg +import yaml +import constants as CONST + +#----------------------------------------------------------- +# Parsing Command Line Arguements +#----------------------------------------------------------- + + +def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): + + + py_param_file_present = False + py_params={} + + while len(argvs) > 1: + myArgv = argvs.pop(1) # 0th is this file's name + + #--help + if re.match('^\-\-help$', myArgv, re.IGNORECASE): + HELP.GenericHelp(CONST.Version) + sys.exit(0) + + #--apply= as parameters file, to replace inline parameters + elif re.match('^\-\-Apply=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-Apply=(.+)$', myArgv, re.IGNORECASE) + py_params_file = matchReg.group(1) + with open(py_params_file,'r') as file: + # The FullLoader parameter handles the conversion from YAML + # scalar values to Python dictionary format + py_params = yaml.load(file,Loader=yaml.FullLoader) + py_param_file_present = True #to be removed once validated + #AssignParams(py_params) #to be uncommented once validated + + #consider inline parameters + elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) + mode = matchReg.group(1) + elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ranRepository = matchReg.group(1) + RAN.ranRepository=matchReg.group(1) + HTML.ranRepository=matchReg.group(1) + ldpc.ranRepository=matchReg.group(1) + elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) + doMerge = matchReg.group(1) + ldpc.ranAllowMerge=matchReg.group(1) + if ((doMerge == 'true') or (doMerge == 'True')): + CiTestObj.ranAllowMerge = True + RAN.ranAllowMerge=True + HTML.ranAllowMerge=True + elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ranBranch = matchReg.group(1) + RAN.ranBranch=matchReg.group(1) + HTML.ranBranch=matchReg.group(1) + ldpc.ranBranch=matchReg.group(1) + elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) + CiTestObj.ranCommitID = matchReg.group(1) + RAN.ranCommitID=matchReg.group(1) + HTML.ranCommitID=matchReg.group(1) + ldpc.ranCommitID=matchReg.group(1) + elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) + CiTestObj.ranTargetBranch = matchReg.group(1) + RAN.ranTargetBranch=matchReg.group(1) + HTML.ranTargetBranch=matchReg.group(1) + ldpc.ranTargetBranch=matchReg.group(1) + elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBIPAddress=matchReg.group(1) + ldpc.eNBIpAddr=matchReg.group(1) + elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1IPAddress=matchReg.group(1) + elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2IPAddress=matchReg.group(1) + elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBUserName=matchReg.group(1) + ldpc.eNBUserName=matchReg.group(1) + elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1UserName=matchReg.group(1) + elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2UserName=matchReg.group(1) + elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBPassword=matchReg.group(1) + ldpc.eNBPassWord=matchReg.group(1) + elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1Password=matchReg.group(1) + elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2Password=matchReg.group(1) + elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBSourceCodePath=matchReg.group(1) + ldpc.eNBSourceCodePath=matchReg.group(1) + elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1SourceCodePath=matchReg.group(1) + elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2SourceCodePath=matchReg.group(1) + elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) + EPC.IPAddress=matchReg.group(1) + elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) + EPC.UserName=matchReg.group(1) + elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) + EPC.Password=matchReg.group(1) + elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + EPC.SourceCodePath=matchReg.group(1) + elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) + if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-Docker', matchReg.group(1), re.IGNORECASE): + EPC.Type=matchReg.group(1) + else: + sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS or OAI-Rel14-Docker)') + elif re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE) + EPC.ContainerPrefix=matchReg.group(1) + elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ADBIPAddress = matchReg.group(1) + elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ADBUserName = matchReg.group(1) + elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) + if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): + if re.match('distributed', matchReg.group(1), re.IGNORECASE): + CiTestObj.ADBCentralized = False + else: + CiTestObj.ADBCentralized = True + else: + sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') + elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ADBPassword = matchReg.group(1) + elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.testXMLfiles.append(matchReg.group(1)) + HTML.testXMLfiles.append(matchReg.group(1)) + HTML.nbTestXMLfiles=HTML.nbTestXMLfiles+1 + elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEIPAddress = matchReg.group(1) + elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEUserName = matchReg.group(1) + elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEPassword = matchReg.group(1) + elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UESourceCodePath = matchReg.group(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')): + CiTestObj.finalStatus = True + else: + HELP.GenericHelp(CONST.Version) + sys.exit('Invalid Parameter: ' + myArgv) + + return py_param_file_present, py_params, mode diff --git a/ci-scripts/checkCodingFormattingRules.sh b/ci-scripts/checkCodingFormattingRules.sh index fb159d4da0..d47b90a9dd 100755 --- a/ci-scripts/checkCodingFormattingRules.sh +++ b/ci-scripts/checkCodingFormattingRules.sh @@ -77,7 +77,7 @@ then IS_NFAPI=`echo $FILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FILE` IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FILE` - IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h|openair3/GTPV1-U/nw-gtpv1u|openair2/UTIL/OPT/ws_"` if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] then if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] @@ -194,12 +194,12 @@ do IS_NFAPI=`echo $FULLFILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FULLFILE` IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FULLFILE` - IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + IS_EXCEPTION=`echo $FULLFILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h|openair3/GTPV1-U/nw-gtpv1u|openair2/UTIL/OPT/ws_"` if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] then if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] then - echo $FILE >> ./files-w-suspect-banner.txt + echo $FULLFILE >> ./files-w-suspect-banner.txt fi fi fi diff --git a/ci-scripts/cls_cots_ue.py b/ci-scripts/cls_cots_ue.py new file mode 100644 index 0000000000..59c2713b47 --- /dev/null +++ b/ci-scripts/cls_cots_ue.py @@ -0,0 +1,138 @@ +# * 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 +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#to use isfile +import os +import sys +#to use logging.info() +import logging +#to create a SSH object locally in the methods +import sshconnection +#time.sleep +import time +#to load cots_ue dictionary +import yaml + +class CotsUe: + def __init__(self,ADBIPAddr,ADBUserName,ADBPassWord): + self.cots_id = '' #cots id from yaml oppo, s10 etc... + self.ADBIPAddr = ADBIPAddr + self.ADBUserName = ADBUserName + self.ADBPassWord = ADBPassWord + self.cots_run_mode = '' #on of off to toggle airplane mode on/off + self.__cots_cde_dict_file = 'cots_ue_ctl.yaml' + self.__SetAirplaneRetry = 3 + + +#-----------------$ +#PUBLIC Methods$ +#-----------------$ + + def Check_Airplane(self): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.ADBIPAddr, self.ADBUserName, self.ADBPassWord) + status=mySSH.cde_check_value('adb shell settings get global airplane_mode_on ', ['0','1'],5) + mySSH.close() + return status + + #simply check if the device id exists in the dictionary + #returns true if it exists, false otherwise + def Check_Exists(self,target_id): + #load cots commands dictionary + if (os.path.isfile(self.__cots_cde_dict_file)): + yaml_file=self.__cots_cde_dict_file + elif (os.path.isfile('ci-scripts/'+self.__cots_cde_dict_file)): + yaml_file='ci-scripts/'+self.__cots_cde_dict_file + else: + logging.error("COTS UE dictionary yaml file cannot be found") + sys.exit("COTS UE dictionary yaml file cannot be found") + + #load cots commands dictionary + with open(yaml_file,'r') as file: + cots_ue_ctl = yaml.load(file,Loader=yaml.FullLoader) + #check if ue id is in the dictionary + if target_id in cots_ue_ctl: + return True + else: + return False + + def Set_Airplane(self, target_id, target_state_str): + #loading cots commands dictionary + + if (os.path.isfile(self.__cots_cde_dict_file)): + yaml_file=self.__cots_cde_dict_file + elif (os.path.isfile('ci-scripts/'+self.__cots_cde_dict_file)): + yaml_file='ci-scripts/'+self.__cots_cde_dict_file + else: + logging.error("COTS UE dictionary yaml file cannot be found") + sys.exit("COTS UE dictionary yaml file cannot be found") + + #load cots commands dictionary + with open(yaml_file,'r') as file: + cots_ue_ctl = yaml.load(file,Loader=yaml.FullLoader) + #check if ue id is in the dictionary + if target_id in cots_ue_ctl: + mySSH = sshconnection.SSHConnection() + mySSH.open(self.ADBIPAddr, self.ADBUserName, self.ADBPassWord) + logging.info(str(self.ADBIPAddr)+' '+str(self.ADBUserName)+' '+str(self.ADBPassWord)) + mySSH.command('adb start-server','\$',5) + mySSH.command('adb devices','\$',5) + logging.info("Toggling COTS UE Airplane mode to : "+target_state_str) + #get current state + current_state = self.Check_Airplane() + if target_state_str.lower()=="on": + target_state=1 + else: + target_state=0 + if current_state != target_state: + #toggle state + retry = 0 + while (current_state!=target_state) and (retry < self.__SetAirplaneRetry): + #loop over the command list from dictionary for the selected ue, to switch to required state + for i in range (0,len(cots_ue_ctl[target_id])): + mySSH.command(cots_ue_ctl[target_id][i], '\$', 5) + time.sleep(1) + current_state = self.Check_Airplane() + retry+=1 + #could not toggle despite the retry + if current_state != target_state: + logging.error("ATTENTION : Could not toggle to : "+target_state_str) + logging.error("Current state is : "+ str(current_state)) + else: + logging.info("Airplane mode is already "+ target_state_str) + mySSH.command('adb kill-server','\$',5) + mySSH.close() + #ue id is NOT in the dictionary + else: + logging.error("COTS UE Id from XML could not be found in UE YAML dictionary " + self.__cots_cde_dict_file) + sys.exit("COTS UE Id from XML could not be found in UE YAML dictionary " + self.__cots_cde_dict_file) + + + + diff --git a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf index db1c5eae2a..d834b23e30 100644 --- a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf @@ -105,6 +105,7 @@ eNBs = ue_TimersAndConstants_n310 = 20; ue_TimersAndConstants_n311 = 1; ue_TransmissionMode = 1; + mbms_dedicated_serving_cell = "DISABLE" //Parameters for SIB18 rxPool_sc_CP_Len = "normal"; diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf index de58950df4..a9ccb9f783 100644 --- a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf @@ -105,6 +105,8 @@ eNBs = ue_TimersAndConstants_n310 = 20; ue_TimersAndConstants_n311 = 1; ue_TransmissionMode = 1; + mbms_dedicated_serving_cell = "DISABLE" + //Parameters for SIB18 rxPool_sc_CP_Len = "normal"; @@ -247,7 +249,6 @@ MCEs = ( ); - NETWORK_INTERFACES : { MCE_INTERFACE_NAME_FOR_M2_ENB = "lo"; @@ -271,12 +272,12 @@ MCEs = ( mcch_update_time = 10; mbms_area_config_list = ( { - common_sf_allocation_period = 2; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6) + common_sf_allocation_period = 1; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6) mbms_area_id = 0; pmch_config_list = ( { - allocated_sf_end=64; - data_mcs=10; + allocated_sf_end=40; + data_mcs=20; mch_scheduling_period = 0; #rf8(0) mbms_session_list = ( { @@ -288,7 +289,7 @@ MCEs = ( mnc_length = 2; } service_id=0; - lcid=5; #this must be properly defined lcid:8+service:0 -> rab_id:5 + lcid=5; #this must be properly defined lcid:8+service:0 -> rab_id:5 //with new RLC set lcid either 4 or 5 } ); } @@ -296,10 +297,10 @@ MCEs = ( mbms_sf_config_list = ( { - radioframe_allocation_period=1; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5) + radioframe_allocation_period=0; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5) radioframe_alloocation_offset=0; num_frame="oneFrame"; - subframe_allocation=57; #xx100000 + subframe_allocation=59; #xx111011 #57; #xx111001 //num_frame="fourFrame"; //subframe_allocation=14548987; # } diff --git a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf new file mode 100755 index 0000000000..5b2c90a714 --- /dev/null +++ b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf @@ -0,0 +1,284 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + ////////// Identification parameters: + eNB_ID = 0xe01; + cell_type = "CELL_MACRO_ENB"; + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( + { mcc = 222; mnc = 01; mnc_length = 2; } + ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + nb_antenna_ports = 1; + ue_TransmissionMode = 1; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + prach_root = 0; + tx_gain = 90; + rx_gain = 115; + pbch_repetition = "FALSE"; + + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; +/* + srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =; +*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* + rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + enable_measurement_reports = "yes"; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="high"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="debug"; + rlc_log_verbosity ="high"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="high"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +THREAD_STRUCT = ( + { + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + worker_config = "ENABLE"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 118; + eNB_instances = [0]; + clock_src = "external"; + } +); + +log_config : + { + global_log_level ="info"; + global_log_verbosity ="high"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="high"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="high"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf index d92804ae44..36e93ba14e 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf @@ -71,6 +71,12 @@ gNBs = initialDLBWPmappingType_2 = 0; #this is SS=1,L=12 initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 + initialDLBWPstartSymbolAndLength_3 = 57; + #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 78; @@ -105,8 +111,8 @@ gNBs = #1,2,4,8,10,20,40,80 ra_ResponseWindow = 4; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR -#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen - ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; #oneHalf (0..15) 4,8,12,16,...60,64 ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; #ra_ContentionResolutionTimer @@ -114,8 +120,8 @@ gNBs = ra_ContentionResolutionTimer = 7; rsrp_ThresholdSSB = 19; #prach-RootSequenceIndex_PR -#0 = 839, 1 = 139 - prach_RootSequenceIndex_PR = 1; +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; prach_RootSequenceIndex = 1; # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex # @@ -135,7 +141,11 @@ gNBs = # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; - + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -235,8 +245,10 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; } diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf new file mode 100755 index 0000000000..92af74c300 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -0,0 +1,291 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf new file mode 100644 index 0000000000..e3adedbf4a --- /dev/null +++ b/ci-scripts/conf_files/lte-fdd-fembms-basic-sim.conf @@ -0,0 +1,426 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "3GPP_eNODEB"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -27; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + mbms_dedicated_serving_cell = "ENABLE" + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "no"; + + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + + ////////// MCE parameters: + target_mce_m2_ip_address = ( { ipv4 = "127.0.0.7"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///M2 + enable_enb_m2 = "yes"; + + + mbms_configuration_data_list = ( + { + mbsfn_sync_area = 0x0001; + mbms_service_area_list=( + { + mbms_service_area=0x0001; + } + ); + } + + ); + + + + NETWORK_INTERFACES : + { + + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + + ENB_IPV4_ADDRESS_FOR_M2C = "127.0.0.2/24"; + ENB_PORT_FOR_M2C = 36443; # Spec 36443 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 200; + puCch10xSnr = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +MCEs = ( + { + MCE_ID = 0xe00; + + MCE_name = "MCE-Vicomtech-LTEBox"; + + //M2 + enable_mce_m2 = "yes"; + + //M3 + enable_mce_m3 = "yes"; + + target_mme_m3_ip_address = ( { ipv4 = "127.0.0.18"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + + NETWORK_INTERFACES : + { + MCE_INTERFACE_NAME_FOR_M2_ENB = "lo"; + MCE_IPV4_ADDRESS_FOR_M2C = "127.0.0.7/24"; + MCE_PORT_FOR_M2C = 36443; # Spec 36443 + + MCE_INTERFACE_NAME_FOR_M3_MME = "lo"; + MCE_IPV4_ADDRESS_FOR_M3C = "127.0.0.3/24"; + MCE_PORT_FOR_M3C = 36444; # Spec 36444 + }; + + plnm: + { + mcc = 208; + mnc = 93; + mnc_length = 2; + }; + + mbms_sched_info : + { + mcch_update_time = 10; + mbms_area_config_list = ( + { + common_sf_allocation_period = 1; #rf4(0) rf8(1) rf16(2) rf32(3) rf64(4) rf128(5) rf256(6) + mbms_area_id = 0; + pmch_config_list = ( + { + allocated_sf_end=512; + data_mcs=15; + mch_scheduling_period = 0; #rf8(0) rf16(1) rf32(2) rf64(3) rf128(4) rf256(5) rf512(6) rf1024(7) + mbms_session_list = ( + { + #plnm + service_id ->tmgi + plnm: + { + mcc = 208; + mnc = 93; + mnc_length = 2; + } + service_id=0; #keep this allways as 0 (workaround for TUN if) + lcid=5; #this must be properly defined lcid:6+service:0 -> rab_id:5 //with new RLC set lcid either 4 or 5 + } + ); + } + ); + + mbms_sf_config_list = ( + { + radioframe_allocation_period=0; #n1(0) n2(1) n4(2) n8(3) n16(4) n32(5) + radioframe_alloocation_offset=0; + num_frame="oneFrame"; + subframe_allocation=57; #xx111001 + //num_frame="fourFrame"; + //subframe_allocation=14548987; # + } + ); + + } + ); + }; + + + mcch_config_per_mbsfn_area = ( + { + mbsfn_area = 0; + pdcch_length = 1; #s1(0), s2(1) + repetition_period = 0; #rf32(0), rf64(1), rf128(2), rf256(3) + offset = 0; + modification_period = 0; #rf512(0; rf1024(1) + subframe_allocation_info = 32; #BITSTRING (6bits -> one frame) xx100000 + mcs = 0; #n2(0), n7(1), n13(2), n19(3) + } + ); + + #); #end mbms_scheduling_info + + } +); + +MMEs = ( + { + MME_ID = 0xe00; + + MME_name = "MME-MBMS-Vicomtech-LTEBox"; + + //M3 + enable_mme_m3 = "yes"; + NETWORK_INTERFACES : + { + MME_INTERFACE_NAME_FOR_M3_MCE = "lo"; + MME_IPV4_ADDRESS_FOR_M3C = "127.0.0.18/24"; + MME_PORT_FOR_M3C = 36444; # Spec 36444 + + }; + } +); + + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 125; + eNB_instances = [0]; + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "ens3"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + +//rfsimulator : +//{ + //options = ("chanmod"); + //modelname = "AWGN"; +//}; + diff --git a/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf b/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf index 53261ec32d..3d5a859156 100644 --- a/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf +++ b/ci-scripts/conf_files/lte-fdd-mbms-basic-sim.conf @@ -102,6 +102,7 @@ eNBs = ue_TimersAndConstants_n310 = 20; ue_TimersAndConstants_n311 = 1; ue_TransmissionMode = 1; + mbms_dedicated_serving_cell = "DISABLE" //Parameters for SIB18 rxPool_sc_CP_Len = "normal"; @@ -295,8 +296,8 @@ MCEs = ( pmch_config_list = ( { allocated_sf_end=32; - data_mcs=14; - mch_scheduling_period = 0; #rf8(0) + data_mcs=15; + mch_scheduling_period = 0; #rf8(0) rf16(1) rf32(2) rf64(3) rf128(4) rf256(5) rf512(6) rf1024(7) mbms_session_list = ( { #plnm + service_id ->tmgi @@ -337,7 +338,7 @@ MCEs = ( offset = 0; modification_period = 0; #rf512(0; rf1024(1) subframe_allocation_info = 32; #BITSTRING (6bits -> one frame) xx100000 - mcs = 1; #n2(0), n7(1), n13(2), n19(3) + mcs = 0; #n2(0), n7(1), n13(2), n19(3) } ); @@ -416,3 +417,10 @@ NETWORK_CONTROLLER : rrc_log_level ="info"; rrc_log_verbosity ="medium"; }; + +//rfsimulator : +//{ + //options = ("chanmod"); + //modelname = "AWGN"; +//}; + diff --git a/ci-scripts/cots_ue_ctl.yaml b/ci-scripts/cots_ue_ctl.yaml new file mode 100644 index 0000000000..c22fca246b --- /dev/null +++ b/ci-scripts/cots_ue_ctl.yaml @@ -0,0 +1,20 @@ +9d690a12: #oppo + - adb shell input keyevent KEYCODE_POWER + - adb shell input swipe 300 700 300 0 + - adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS + - adb shell input keyevent 20 + - adb shell input tap 968 324 +002: #s10 + - adb shell input keyevent KEYCODE_POWER + - adb shell input swipe 200 900 200 300 + - adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS + - adb shell input tap 968 324 +003: #s20 + - adb shell input keyevent KEYCODE_POWER + - adb shell input swipe 200 900 200 300 + - adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS + - adb shell input tap 968 324 +004: #xperia + - tbd + - tbd + - tbd diff --git a/ci-scripts/cppcheck_suppressions.list b/ci-scripts/cppcheck_suppressions.list index 727fd22e74..4b9fb97427 100644 --- a/ci-scripts/cppcheck_suppressions.list +++ b/ci-scripts/cppcheck_suppressions.list @@ -83,6 +83,10 @@ nullPointer:common/utils/T/tracer/multi.c:265 // the tests arrayIndexOutOfBounds:openair2/LAYER2/rlc_v2/tests/test.c:401 // +//----------------------------------------------------------------------------- +// cppcheck does not understand the different lengths of arrays +arrayIndexOutOfBounds:openair1/SIMULATION/TOOLS/random_channel.c:705 +arrayIndexOutOfBounds:openair1/SIMULATION/TOOLS/random_channel.c:706 //***************************************************************************** // // True problems we don't know how to fix, Suppression is commented out, diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 09d500f203..25bbbba091 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -66,38 +66,6 @@ class EPCManagement(): self.MmeIPAddress = '' self.containerPrefix = 'prod' -#----------------------------------------------------------- -# Setter and Getters on Public Members -#----------------------------------------------------------- - - def SetIPAddress(self, ipaddress): - self.IPAddress = ipaddress - def GetIPAddress(self): - return self.IPAddress - def SetUserName(self, username): - self.UserName = username - def GetUserName(self): - return self.UserName - def SetPassword(self, password): - self.Password = password - def GetPassword(self): - return self.Password - def SetSourceCodePath(self, sourcecodepath): - self.SourceCodePath = sourcecodepath - def GetSourceCodePath(self): - return self.SourceCodePath - def SetType(self, kind): - self.Type = kind - def GetType(self): - return self.Type - def SetHtmlObj(self, obj): - self.htmlObj = obj - def SetTestCase_id(self, idx): - self.testCase_id = idx - def GetMmeIPAddress(self): - return self.MmeIPAddress - def SetContainerPrefix(self, prefix): - self.containerPrefix = prefix #----------------------------------------------------------- # EPC management functions diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 8fa99fa61b..8f2d38cced 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -82,73 +82,14 @@ class HTMLManagement(): #----------------------------------------------------------- # Setters and Getters #----------------------------------------------------------- - def SethtmlUEFailureMsg(self,huefa): - self.htmlUEFailureMsg = huefa - def GethtmlUEFailureMsg(self): - return self.htmlUEFailureMsg - def SetHmleNBFailureMsg(self, msg): - self.htmleNBFailureMsg = msg - - def Setdesc(self, dsc): - self.desc = dsc - - def SetstartTime(self, sttime): - self.startTime = sttime - - def SettestCase_id(self, tcid): - self.testCase_id = tcid - def GettestCase_id(self): - return self.testCase_id - - def SetranRepository(self, repository): - self.ranRepository = repository - def SetranAllowMerge(self, merge): - self.ranAllowMerge = merge - def SetranBranch(self, branch): - self.ranBranch = branch - def SetranCommitID(self, commitid): - self.ranCommitID = commitid - def SetranTargetBranch(self, tbranch): - self.ranTargetBranch = tbranch - + def SethtmlUEConnected(self, nbUEs): if nbUEs > 0: self.htmlUEConnected = nbUEs else: self.htmlUEConnected = 1 - def SethtmlNb_Smartphones(self, nbUEs): - self.htmlNb_Smartphones = nbUEs - def SethtmlNb_CATM_Modules(self, nbUEs): - self.htmlNb_CATM_Modules = nbUEs + - def SetnbTestXMLfiles(self, nb): - self.nbTestXMLfiles = nb - def GetnbTestXMLfiles(self): - return self.nbTestXMLfiles - - def SettestXMLfiles(self, xmlFile): - self.testXMLfiles.append(xmlFile) - def SethtmlTabRefs(self, tabRef): - self.htmlTabRefs.append(tabRef) - def SethtmlTabNames(self, tabName): - self.htmlTabNames.append(tabName) - def SethtmlTabIcons(self, tabIcon): - self.htmlTabIcons.append(tabIcon) - - def SetOsVersion(self, version, idx): - self.OsVersion[idx] = version - def SetKernelVersion(self, version, idx): - self.KernelVersion[idx] = version - def SetUhdVersion(self, version, idx): - self.UhdVersion[idx] = version - def SetUsrpBoard(self, version, idx): - self.UsrpBoard[idx] = version - def SetCpuNb(self, nb, idx): - self.CpuNb[idx] = nb - def SetCpuModel(self, model, idx): - self.CpuModel[idx] = model - def SetCpuMHz(self, freq, idx): - self.CpuMHz[idx] = freq #----------------------------------------------------------- # HTML structure creation functions diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 63358eca38..86fd9d84df 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -1,4 +1,4 @@ - +#/* # * 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. @@ -28,15 +28,30 @@ # pexpect #--------------------------------------------------------------------- -import constants as CONST #----------------------------------------------------------- -# Import +# Import Components +#----------------------------------------------------------- + +import helpreadme as HELP +import constants as CONST + +import cls_physim #class PhySim for physical simulators build and test +import cls_cots_ue #class CotsUe for Airplane mode control + +import sshconnection +import epc +import ran +import html + + +#----------------------------------------------------------- +# Import Libs #----------------------------------------------------------- import sys # arg import re # reg -import pexpect # pexpect +import pexpect # pexpect import time # sleep import os import subprocess @@ -51,8 +66,9 @@ logging.basicConfig( ) + #----------------------------------------------------------- -# Class Declaration +# OaiCiTest Class Definition #----------------------------------------------------------- class OaiCiTest(): @@ -97,12 +113,13 @@ class OaiCiTest(): self.UEIPAddress = '' self.UEUserName = '' self.UEPassword = '' - self.UE_instance = '' + self.UE_instance = 0 self.UESourceCodePath = '' self.UELogFile = '' self.Build_OAI_UE_args = '' self.Initialize_OAI_UE_args = '' self.clean_repository = True + self.air_interface='' self.expectedNbOfConnectedUEs = 0 def BuildOAIUE(self): @@ -112,10 +129,10 @@ class OaiCiTest(): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) result = re.search('--nrUE', self.Build_OAI_UE_args) if result is not None: - RAN.Setair_interface('nr') + self.air_interface='nr-uesoftmodem' ue_prefix = 'NR ' else: - RAN.Setair_interface('lte') + self.air_interface='lte-uesoftmodem' ue_prefix = '' result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) if result is not None: @@ -155,7 +172,7 @@ class OaiCiTest(): mismatch = True if not mismatch: SSH.close() - HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK) return SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -181,7 +198,7 @@ class OaiCiTest(): SSH.command('ls ran_build/build', '\$', 3) SSH.command('ls ran_build/build', '\$', 3) buildStatus = True - result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) + result = re.search(self.air_interface, SSH.getBefore()) if result is None: buildStatus = False SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) @@ -209,33 +226,33 @@ class OaiCiTest(): sys.exit(1) def CheckFlexranCtrlInstallation(self): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': return - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: - RAN.SetflexranCtrlInstalled(True) + RAN.flexranCtrlInstalled=True logging.debug('Flexran Controller is installed') SSH.close() def InitializeFlexranCtrl(self): - if RAN.GetflexranCtrlInstalled() == False: + if RAN.flexranCtrlInstalled == False: return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f log/*.log', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) result = re.search('rt_controller -c ', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') - RAN.SetflexranCtrlStarted(True) + RAN.flexranCtrlStarted=True SSH.close() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) @@ -268,21 +285,29 @@ class OaiCiTest(): SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) SSH.close() return - # enable data service - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - # The following commands are deprecated since we no longer work on Android 7+ - # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) - # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) - # a dedicated script has to be installed inside the UE - # airplane mode on means call /data/local/tmp/off - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + #RH quick add-on to integrate cots control defined by yaml + #if device_id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id, 'ON') else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - #airplane mode off means call /data/local/tmp/on - logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') - SSH.close() + # enable data service + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + + # The following commands are deprecated since we no longer work on Android 7+ + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) + # a dedicated script has to be installed inside the UE + # airplane mode on means call /data/local/tmp/off + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + #airplane mode off means call /data/local/tmp/on + logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -306,14 +331,14 @@ class OaiCiTest(): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', pStatus) HTML.CreateHtmlTabFooter(False) sys.exit(1) UE_prefix = '' @@ -335,7 +360,7 @@ class OaiCiTest(): # Initialize_OAI_UE_args usually start with -C and followed by the location in repository SSH.command('source oaienv', '\$', 5) SSH.command('cd cmake_targets/ran_build/build', '\$', 5) - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) # We may have to regenerate the .u* files if result is None: @@ -351,13 +376,13 @@ class OaiCiTest(): SSH.command('if [ -e rbconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) SSH.command('if [ -e reconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm reconfig.raw; fi', '\$', 5) # Copy the RAW files from gNB running directory (maybe on another machine) - copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/rbconfig.raw', '.') + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/rbconfig.raw', '.') if (copyin_res == 0): SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './rbconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') - copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/reconfig.raw', '.') + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/reconfig.raw', '.') if (copyin_res == 0): SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './reconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') - SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./'+ self.air_interface +' ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) self.UELogFile = 'ue_' + self.testCase_id + '.log' @@ -370,9 +395,7 @@ class OaiCiTest(): while (doOutterLoop): SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/ran_build/build', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - #use nohup instead of daemon - #SSH.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) + SSH.command('echo $USER; nohup sudo -E ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) time.sleep(6) SSH.command('cd ../..', '\$', 5) doLoop = True @@ -388,7 +411,7 @@ class OaiCiTest(): doLoop = False continue SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': result = re.search('Starting sync detection', SSH.getBefore()) else: result = re.search('got sync', SSH.getBefore()) @@ -413,7 +436,7 @@ class OaiCiTest(): # That is the case for LTE # In NR case, it's a positive message that will show if synchronization occurs doLoop = True - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': loopCounter = 10 else: # We are now checking if sync w/ eNB DOES NOT OCCUR @@ -422,7 +445,7 @@ class OaiCiTest(): while (doLoop): loopCounter = loopCounter - 1 if (loopCounter == 0): - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': # Here we do have great chances that UE did NOT cell-sync w/ gNB doLoop = False fullSyncStatus = False @@ -441,7 +464,7 @@ class OaiCiTest(): fullSyncStatus = True continue SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Frequency"', '\$', 4) - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': # Positive messaging --> result = re.search('Measured Carrier Frequency', SSH.getBefore()) if result is not None: @@ -470,12 +493,12 @@ class OaiCiTest(): if fullSyncStatus and gotSyncStatus: doInterfaceCheck = False - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: doInterfaceCheck = True # For the moment, only in explicit noS1 without kernel module (ie w/ tunnel interface) - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': result = re.search('--noS1 --nokrnmod 1', str(self.Initialize_OAI_UE_args)) if result is not None: doInterfaceCheck = True @@ -491,7 +514,7 @@ class OaiCiTest(): logging.debug(SSH.getBefore()) logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') tunnelInterfaceStatus = False - if RAN.GeteNBmbmsEnable(0): + if RAN.eNBmbmsEnables[0]: SSH.command('ifconfig oaitun_uem1', '\$', 4) result = re.search('inet addr', SSH.getBefore()) if result is not None: @@ -507,7 +530,7 @@ class OaiCiTest(): SSH.close() if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') if (self.ADBIPAddress != 'none'): self.UEDevices = [] @@ -515,15 +538,15 @@ class OaiCiTest(): self.UEDevicesStatus = [] self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) else: - if RAN.Getair_interface() == 'lte': - if RAN.GeteNBmbmsEnable(0): - HTML.SethtmlUEFailureMsg('oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured') + if self.air_interface == 'lte-uesoftmodem': + if RAN.eNBmbmsEnables[0]: + HTML.htmlUEFailureMsg='oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' else: - HTML.SethtmlUEFailureMsg('oaitun_ue1 interface is either NOT mounted or NOT configured') - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + HTML.htmlUEFailureMsg='oaitun_ue1 interface is either NOT mounted or NOT configured' + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') else: - HTML.SethtmlUEFailureMsg('nr-uesoftmodem did NOT synced') - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + HTML.htmlUEFailureMsg='nr-uesoftmodem did NOT synced' + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') logging.error('\033[91mInitialize OAI UE Failed! \033[0m') self.AutoTerminateUEandeNB() @@ -675,7 +698,7 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() def PingCatM(self): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -688,10 +711,10 @@ class OaiCiTest(): try: statusQueue = SimpleQueue() lock = Lock() - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) - if re.match('OAI', EPC.GetType(), re.IGNORECASE): + if re.match('OAI', EPC.Type, re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) HTML.CreateHtmlTabFooter(False) @@ -775,7 +798,13 @@ class OaiCiTest(): try: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - if device_id == '84B7N16418004022': + #RH quick add on to integrate cots control defined by yaml + #if device Id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode OFF (ie Radio ON) + COTS_UE.Set_Airplane(device_id, 'OFF') + elif device_id == '84B7N16418004022': SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) else: SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) @@ -812,7 +841,13 @@ class OaiCiTest(): if count == 15 or count == 30: logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') if self.ADBCentralized: - if device_id == '84B7N16418004022': + #RH quick add on to intgrate cots control defined by yaml + #if device id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id, 'ON') + elif device_id == '84B7N16418004022': SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) @@ -820,7 +855,13 @@ class OaiCiTest(): SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) time.sleep(0.5) if self.ADBCentralized: - if device_id == '84B7N16418004022': + #RH quick add on to integrate cots control defined by yaml + #if device id exists in yaml dictionary, we execute the new procedre defined incots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode OFF (ie Radio ON) + COTS_UE.Set_Airplane(device_id, 'OFF') + elif device_id == '84B7N16418004022': SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) else: SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) @@ -891,7 +932,7 @@ class OaiCiTest(): self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED cnt += 1 HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) @@ -903,7 +944,13 @@ class OaiCiTest(): try: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - if device_id == '84B7N16418004022': + #RH quick add on to integrate cots control defined by yaml + #if device id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id,'ON') + elif device_id == '84B7N16418004022': SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) @@ -937,7 +984,7 @@ class OaiCiTest(): for job in multi_jobs: job.join() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) @@ -1071,7 +1118,6 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: SSH.command('adb devices', '\$', 15) - #self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) SSH.close() else: @@ -1203,8 +1249,8 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) SSH.command('cd /opt/flexran_rtc', '\$', 5) SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) @@ -1316,13 +1362,13 @@ class OaiCiTest(): # Launch ping on the EPC side (true for ltebox and old open-air-cn) # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): launchFromEpc = False ping_time = re.findall("-c (\d+)",str(self.ping_args)) if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) else: @@ -1331,9 +1377,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) ping_status = ret.returncode - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cat ' + EPC.SourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' @@ -1413,7 +1459,7 @@ class OaiCiTest(): return ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) if ping_from_eNB is not None: - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') else: @@ -1422,8 +1468,8 @@ class OaiCiTest(): sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: - SSH.open(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword()) - SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets/', '\$', 5) + SSH.open(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword) + SSH.command('cd ' + RAN.eNBSourceCodePath + '/cmake_targets/', '\$', 5) else: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) @@ -1487,20 +1533,20 @@ class OaiCiTest(): # copying on the EPC server for logCollection if ping_from_eNB is not None: - copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') else: copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '.log', EPC.SourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) def Ping(self): - result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) + result = re.search('noS1', str(RAN.Initialize_eNB_args)) if result is not None: self.PingNoS1() return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -1586,7 +1632,7 @@ class OaiCiTest(): return result def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - SSH.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('awk -f /tmp/tcp_iperf_stats.awk ' + EPC.SourceCodePath + '/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)', SSH.getBefore()) if result is not None: avgbitrate = result.group('average') @@ -1844,7 +1890,7 @@ class OaiCiTest(): # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): launchFromEpc = False cmd = 'hostname -I' ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') @@ -1852,13 +1898,13 @@ class OaiCiTest(): EPC_Iperf_UE_IPAddress = ret.stdout.strip() port = 5001 + idx if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if udpIperf: - SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) + SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) else: - SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) + SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) SSH.close() else: if self.ueIperfVersion == self.dummyIperfVersion: @@ -1881,7 +1927,7 @@ class OaiCiTest(): SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) else: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath+ '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -1915,27 +1961,27 @@ class OaiCiTest(): # Kill iperf server on EPC side if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('killall --signal SIGKILL iperf', EPC.GetUserName(), 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('killall --signal SIGKILL iperf', EPC.UserName, 5) SSH.close() else: cmd = 'killall --signal SIGKILL iperf' logging.debug(cmd) subprocess.run(cmd, shell=True) time.sleep(1) - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') # in case of failure, retrieve server log if (clientStatus == -1) or (clientStatus == -2): if launchFromEpc: time.sleep(1) if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath+ '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI-UE if (device_id == 'OAI-UE'): SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: @@ -1949,8 +1995,8 @@ class OaiCiTest(): if (device_id != 'OAI-UE'): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + EPC.GetSourceCodePath() + '/scripts ; fi', '\$', 5) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('if [ ! -d ' + EPC.SourceCodePath + '/scripts ]; then mkdir -p ' + EPC.SourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) @@ -2009,7 +2055,7 @@ class OaiCiTest(): SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) else: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) if self.ADBCentralized: if (useIperf3): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) @@ -2031,11 +2077,11 @@ class OaiCiTest(): # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): launchFromEpc = False if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2070,9 +2116,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) iperf_status = ret.returncode - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cat ' + EPC.SourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if iperf_status < 0: if launchFromEpc: SSH.close() @@ -2109,7 +2155,7 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') else: - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.SourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') # fromdos has to be called on the python executor not on ADB server cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' subprocess.run(cmd, shell=True) @@ -2119,15 +2165,15 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): if not launchFromEpc: - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') else: SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) def IperfNoS1(self): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -2139,9 +2185,9 @@ class OaiCiTest(): return server_on_enb = re.search('-R', str(self.iperf_args)) if server_on_enb is not None: - iServerIPAddr = RAN.GeteNBIPAddress() - iServerUser = RAN.GeteNBUserName() - iServerPasswd = RAN.GeteNBPassword() + iServerIPAddr = RAN.eNBIPAddress + iServerUser = RAN.eNBUserName + iServerPasswd = RAN.eNBPassword iClientIPAddr = self.UEIPAddress iClientUser = self.UEUserName iClientPasswd = self.UEPassword @@ -2149,9 +2195,9 @@ class OaiCiTest(): iServerIPAddr = self.UEIPAddress iServerUser = self.UEUserName iServerPasswd = self.UEPassword - iClientIPAddr = RAN.GeteNBIPAddress() - iClientUser = RAN.GeteNBUserName() - iClientPasswd = RAN.GeteNBPassword() + iClientIPAddr = RAN.eNBIPAddress + iClientUser = RAN.eNBUserName + iClientPasswd = RAN.eNBPassword if self.iperf_options != 'sink': # Starting the iperf server SSH.open(iServerIPAddr, iServerUser, iServerPasswd) @@ -2206,10 +2252,10 @@ class OaiCiTest(): if (clientStatus == -1): copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/scripts') copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/scripts') iperf_noperf = False if status_queue.empty(): iperf_status = False @@ -2236,11 +2282,11 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() def Iperf(self): - result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) + result = re.search('noS1', str(RAN.Initialize_eNB_args)) if result is not None: self.IperfNoS1() return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -2317,7 +2363,7 @@ class OaiCiTest(): status_queue = SimpleQueue() # in noS1 config, no need to check status from EPC # in gNB also currently no need to check - result = re.search('noS1|band78', str(RAN.GetInitialize_eNB_args())) + result = re.search('noS1|band78', str(RAN.Initialize_eNB_args)) if result is None: p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) p.daemon = True @@ -2356,14 +2402,14 @@ class OaiCiTest(): if (status < 0): result = status if result == CONST.ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(RAN.GeteNBLogFile(0))) + fileCheck = re.search('enb_', str(RAN.eNBLogFiles[0])) if fileCheck is not None: - SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFile(0), '.') - logStatus = RAN.AnalyzeLogFile_eNB(RAN.GeteNBLogFile[0]) + SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/' + RAN.eNBLogFiles[0], '.') + logStatus = RAN.AnalyzeLogFile_eNB(RAN.eNBLogFiles[0]) if logStatus < 0: result = logStatus - RAN.SeteNBLogFile('', 0) - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): + RAN.eNBLogFiles[0]='' + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: self.TerminateFlexranCtrl() return result @@ -2398,8 +2444,8 @@ class OaiCiTest(): def CheckOAIUEProcess(self, status_queue): try: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + RAN.Getair_interface() + '-uesoftmodem | grep -v grep', '\$', 5) - result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) + SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + ' | grep -v grep', '\$', 5) + result = re.search(self.air_interface, SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') status_queue.put(CONST.OAI_UE_PROCESS_FAILED) @@ -2436,7 +2482,7 @@ class OaiCiTest(): nrFoundDCI = 0 nrCRCOK = 0 mbms_messages = 0 - HTML.SethtmlUEFailureMsg('') + HTML.htmlUEFailureMsg='' global_status = CONST.ALL_PROCESSES_OK for line in ue_log_file.readlines(): result = re.search('nr_synchro_time', str(line)) @@ -2498,7 +2544,7 @@ class OaiCiTest(): result = re.search('No cell synchronization found, abandoning', str(line)) if result is not None: no_cell_sync_found = True - if RAN.GeteNBmbmsEnable(0): + if RAN.eNBmbmsEnables[0]: result = re.search('TRIED TO PUSH MBMS DATA', str(line)) if result is not None: mbms_messages += 1 @@ -2506,22 +2552,22 @@ class OaiCiTest(): if result is not None and (not mib_found): try: mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " nidcell = " + result.group('nidcell') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_duration = " + result.group('phich_duration') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_resource = " + result.group('phich_resource') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " tx_ant = " + result.group('tx_ant') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mib_found = True except Exception as e: @@ -2530,7 +2576,7 @@ class OaiCiTest(): if result is not None and (not frequency_found): try: mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') frequency_found = True except Exception as e: @@ -2539,7 +2585,7 @@ class OaiCiTest(): if result is not None and (not plmn_found): try: mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') plmn_found = True except Exception as e: @@ -2548,7 +2594,7 @@ class OaiCiTest(): if result is not None: try: mibMsg = "The operator is: " + result.group('operator') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "Operator name not found" + '\033[0m') @@ -2556,7 +2602,7 @@ class OaiCiTest(): if result is not None: try: mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + ' -> ') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + ' -> ' logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') @@ -2566,7 +2612,7 @@ class OaiCiTest(): freq = result.group('carrier_frequency') new_freq = re.sub('/[0-9]+','',freq) float_freq = float(new_freq) / 1000000 - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' logging.debug('\033[94m' + " DL Carrier Frequency is: " + str(freq) + '\033[0m') except Exception as e: logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') @@ -2574,7 +2620,7 @@ class OaiCiTest(): if result is not None: try: prb = result.group('allowed_bandwidth') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + ' -- PRB: ' + prb + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + ' -- PRB: ' + prb + '\n' logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') except Exception as e: logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') @@ -2582,57 +2628,57 @@ class OaiCiTest(): if rrcConnectionRecfgComplete > 0: statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' logging.debug('\033[94m' + statMsg + '\033[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if nrUEFlag: if nrDecodeMib > 0: statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if nrFoundDCI > 0: statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if nrCRCOK > 0: statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if not frequency_found: statMsg = 'NR-UE could NOT synch!' logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if uciStatMsgCount > 0: statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if pdcpDataReqFailedCount > 0: statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if badDciCount > 0: statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1(A)" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if f1aRetransmissionCount > 0: statMsg = 'UE showed ' + str(f1aRetransmissionCount) + ' "Format1A Retransmission but TBS are different" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if fatalErrorCount > 0: statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if macBsrTimerExpiredCount > 0: statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') - if RAN.GeteNBmbmsEnable(0): + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if RAN.eNBmbmsEnables[0]: if mbms_messages > 0: statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') else: statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)' logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m') - global_status = OAI_UE_PROCESS_NO_MBMS_MSGS - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + global_status = CONST.OAI_UE_PROCESS_NO_MBMS_MSGS + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if foundSegFault: logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') if not nrUEFlag: @@ -2642,7 +2688,7 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE showed an assertion!\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE showed an assertion!\n' if not nrUEFlag: if not mib_found or not frequency_found: global_status = CONST.OAI_UE_PROCESS_ASSERTION @@ -2651,31 +2697,31 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE faced real time issues!\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE faced real time issues!\n' if nrUEFlag: if not frequency_found: global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC else: if no_cell_sync_found and not mib_found: logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE could not synchronize!\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE could not synchronize!\n' global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return global_status def TerminateFlexranCtrl(self): - if RAN.GetflexranCtrlInstalled() == False or RAN.GetflexranCtrlStarted() == False: + if RAN.flexranCtrlInstalled == False or RAN.flexranCtrlStarted == False: return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('echo ' + EPC.Password + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) time.sleep(1) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) time.sleep(1) SSH.close() - RAN.SetflexranCtrlStarted(False) + RAN.flexranCtrlStarted=False HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): @@ -2683,7 +2729,13 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # back in airplane mode on (ie radio off) if self.ADBCentralized: - if device_id == '84B7N16418004022': + #RH quick add on to intgrate cots control defined by yaml + #if device Id exists in yaml dictionary, we execute the new procedure defined in cots_ue class + #otherwise we use the legacy procedure + if COTS_UE.Check_Exists(device_id): + #switch device to Airplane mode ON (ie Radio OFF) + COTS_UE.Set_Airplane(device_id, 'ON') + elif device_id == '84B7N16418004022': SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) @@ -2741,7 +2793,7 @@ class OaiCiTest(): copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') - HTML.SethtmlUEFailureMsg('Could not copy UE logfile to analyze it!') + HTML.htmlUEFailureMsg='Could not copy UE logfile to analyze it!' HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') self.UELogFile = '' return @@ -2754,9 +2806,9 @@ class OaiCiTest(): ueAction = 'Connection' if (logStatus < 0): logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - HTML.SethtmlUEFailureMsg('' + ueAction + ' Failed\n' + HTML.GethtmlUEFailureMsg()) + HTML.htmlUEFailureMsg='' + ueAction + ' Failed\n' + HTML.htmlUEFailureMsg HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': # In case of sniffing on commercial eNBs we have random results # Not an error then if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): @@ -2768,7 +2820,7 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - HTML.SethtmlUEFailureMsg('' + ueAction + ' Completed\n' + HTML.GethtmlUEFailureMsg()) + HTML.htmlUEFailureMsg='' + ueAction + ' Completed\n' + HTML.htmlUEFailureMsg HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.UELogFile = '' else: @@ -2777,41 +2829,41 @@ class OaiCiTest(): def AutoTerminateUEandeNB(self): if (self.ADBIPAddress != 'none'): self.testCase_id = 'AUTO-KILL-UE' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of UE' - HTML.Setdesc('Automatic Termination of UE') + HTML.desc='Automatic Termination of UE' self.ShowTestID() self.TerminateUE() if (self.Initialize_OAI_UE_args != ''): self.testCase_id = 'AUTO-KILL-OAI-UE' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of OAI-UE' - HTML.Setdesc('Automatic Termination of OAI-UE') + HTML.desc='Automatic Termination of OAI-UE' self.ShowTestID() self.TerminateOAIUE() - if (RAN.GetInitialize_eNB_args() != ''): + if (RAN.Initialize_eNB_args != ''): self.testCase_id = 'AUTO-KILL-eNB' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of eNB' - HTML.Setdesc('Automatic Termination of eNB') + HTML.desc='Automatic Termination of eNB' self.ShowTestID() - RAN.SeteNB_instance('0') + RAN.eNB_instance=0 RAN.TerminateeNB() - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: self.testCase_id = 'AUTO-KILL-flexran-ctl' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of FlexRan CTL' - HTML.Setdesc('Automatic Termination of FlexRan CTL') + HTML.desc='Automatic Termination of FlexRan CTL' self.ShowTestID() self.TerminateFlexranCtrl() - RAN.SetprematureExit(True) + RAN.prematureExit=True def IdleSleep(self): time.sleep(self.idle_sleep_time) HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName + cmd = "curl --silent http://" + EPC.IPAddress + ":9999/stats | jq '.' > " + fileName message = cmd + '\n' logging.debug(cmd) subprocess.run(cmd, shell=True) @@ -2860,7 +2912,7 @@ class OaiCiTest(): logging.debug(msg) fullMessage += msg + '\n' if self.x2_ho_options == 'network': - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] self.x2ENBBsIds.append([]) @@ -2875,7 +2927,7 @@ class OaiCiTest(): eNB_cnt = self.x2NbENBs cnt = 0 while cnt < eNB_cnt: - cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" + cmd = "curl -XPOST http://" + EPC.IPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -2889,7 +2941,7 @@ class OaiCiTest(): while cnt < eNB_cnt: ueIdx = 0 while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]): - cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) + cmd = "curl -XPOST http://" + EPC.IPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -2921,11 +2973,11 @@ class OaiCiTest(): HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) def LogCollectBuild(self): - if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): - IPAddress = RAN.GeteNBIPAddress() - UserName = RAN.GeteNBUserName() - Password = RAN.GeteNBPassword() - SourceCodePath = RAN.GeteNBSourceCodePath() + if (RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != ''): + IPAddress = RAN.eNBIPAddress + UserName = RAN.eNBUserName + Password = RAN.eNBPassword + SourceCodePath = RAN.eNBSourceCodePath elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): IPAddress = self.UEIPAddress UserName = self.UEUserName @@ -2940,8 +2992,8 @@ class OaiCiTest(): SSH.command('zip build.log.zip build_log_*/*', '\$', 60) SSH.close() def LogCollectPing(self): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f ping.log.zip', '\$', 5) SSH.command('zip ping.log.zip ping*.log', '\$', 60) @@ -2949,8 +3001,8 @@ class OaiCiTest(): SSH.close() def LogCollectIperf(self): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f iperf.log.zip', '\$', 5) SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) @@ -2967,20 +3019,20 @@ class OaiCiTest(): SSH.close() def RetrieveSystemVersion(self, machine): - if RAN.GeteNBIPAddress() == 'none' or self.UEIPAddress == 'none': - HTML.SetOsVersion('Ubuntu 16.04.5 LTS', 0) - HTML.SetKernelVersion('4.15.0-45-generic', 0) - HTML.SetUhdVersion('3.13.0.1-0', 0) - HTML.SetUsrpBoard('B210', 0) - HTML.SetCpuNb('4', 0) - HTML.SetCpuModel('Intel(R) Core(TM) i5-6200U', 0) - HTML.SetCpuMHz('2399.996 MHz', 0) + if RAN.eNBIPAddress == 'none' or self.UEIPAddress == 'none': + HTML.OsVersion[0]='Ubuntu 16.04.5 LTS' + HTML.KernelVersion[0]='4.15.0-45-generic' + HTML.UhdVersion[0]='3.13.0.1-0' + HTML.UsrpBoard[0]='B210' + HTML.CpuNb[0]='4' + HTML.CpuModel[0]='Intel(R) Core(TM) i5-6200U' + HTML.CpuMHz[0]='2399.996 MHz' return 0 if machine == 'eNB': - if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': - IPAddress = RAN.GeteNBIPAddress() - UserName = RAN.GeteNBUserName() - Password = RAN.GeteNBPassword() + if RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != '': + IPAddress = RAN.eNBIPAddress + UserName = RAN.eNBUserName + Password = RAN.eNBPassword idx = 0 else: return -1 @@ -2999,7 +3051,7 @@ class OaiCiTest(): if result is not None: OsVersion = result.group('os_type') logging.debug('OS is: ' + OsVersion) - HTML.SetOsVersion(OsVersion, idx) + HTML.OsVersion[idx]=OsVersion else: SSH.command('hostnamectl', '\$', 5) result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) @@ -3011,26 +3063,26 @@ class OaiCiTest(): if result is not None: OsVersion = OsVersion.replace('7 ', result.group('os_version')) logging.debug('OS is: ' + OsVersion) - HTML.SetOsVersion(OsVersion, idx) + HTML.OsVersion[idx]=OsVersion SSH.command('uname -r', '\$', 5) result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) if result is not None: KernelVersion = result.group('kernel_version') logging.debug('Kernel Version is: ' + KernelVersion) - HTML.SetKernelVersion(KernelVersion, idx) + HTML.KernelVersion[idx]=KernelVersion SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + UhdVersion) - HTML.SetUhdVersion(UhdVersion, idx) + HTML.UhdVersion[idx]=UhdVersion else: SSH.command('uhd_config_info --version', '\$', 5) result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) if result is not None: UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + UhdVersion) - HTML.SetUhdVersion(UhdVersion, idx) + HTML.UhdVersion[idx]=UhdVersion SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 60) usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) count = 0 @@ -3042,115 +3094,148 @@ class OaiCiTest(): count += 1 if count > 0: logging.debug('USRP Board(s) : ' + UsrpBoard) - HTML.SetUsrpBoard(UsrpBoard, idx) + HTML.UsrpBoard[idx]=UsrpBoard SSH.command('lscpu', '\$', 5) result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: CpuNb = result.group('nb_cpus') logging.debug('nb_cpus: ' + CpuNb) - HTML.SetCpuNb(CpuNb, idx) + HTML.CpuNb[idx]=CpuNb CpuModel = result.group('model') logging.debug('model: ' + CpuModel) - HTML.SetCpuModel(CpuModel, idx) + HTML.CpuModel[idx]=CpuModel CpuMHz = result.group('cpu_mhz') + ' MHz' logging.debug('cpu_mhz: ' + CpuMHz) - HTML.SetCpuMHz(CpuMHz, idx) + HTML.CpuMHz[idx]=CpuMHz SSH.close() -#----------------------------------------------------------- -# ShowTestID() -#----------------------------------------------------------- def ShowTestID(self): logging.debug('\u001B[1m----------------------------------------\u001B[0m') logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') logging.debug('\u001B[1m' + self.desc + '\u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') -def CheckClassValidity(action,id): - if action!='Build_PhySim' and action!='Run_PhySim' and action != 'Build_eNB' and action != 'WaitEndBuild_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 != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' 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 != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': - logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) - return False - return True + + +#----------------------------------------------------------- +# General Functions +#----------------------------------------------------------- + + + +def CheckClassValidity(xml_class_list,action,id): + if action not in xml_class_list: + logging.debug('ERROR: test-case ' + id + ' has unlisted class ' + action + ' ##CHECK xml_class_list.yml') + resp=False + else: + resp=True + return resp + + +#assigning parameters to object instance attributes (even if the attributes do not exist !!) +def AssignParams(params_dict): + + for key,value in params_dict.items(): + setattr(CiTestObj, key, value) + setattr(RAN, key, value) + setattr(HTML, key, value) + setattr(ldpc, key, value) + + def GetParametersFromXML(action): if action == 'Build_eNB': - RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) + RAN.Build_eNB_args=test.findtext('Build_eNB_args') forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): - RAN.SetBuild_eNB_forced_workspace_cleanup(False) + RAN.Build_eNB_forced_workspace_cleanup=False else: if re.match('true', forced_workspace_cleanup, re.IGNORECASE): - RAN.SetBuild_eNB_forced_workspace_cleanup(True) + RAN.Build_eNB_forced_workspace_cleanup=True else: - RAN.SetBuild_eNB_forced_workspace_cleanup(False) - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') + RAN.Build_eNB_forced_workspace_cleanup=False + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 + else: + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): - RAN.SetbackgroundBuild(False) + RAN.backgroundBuild=False else: if re.match('true', xmlBgBuildField, re.IGNORECASE): - RAN.SetbackgroundBuild(True) + RAN.backgroundBuild=True else: - RAN.SetbackgroundBuild(False) + RAN.backgroundBuild=False - if action == 'WaitEndBuild_eNB': - RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') - - if action == 'Initialize_eNB': - RAN.SetInitialize_eNB_args(test.findtext('Initialize_eNB_args')) - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') - CiTestObj.air_interface = test.findtext('air_interface') - if (CiTestObj.air_interface is None): - CiTestObj.air_interface = 'lte' + elif action == 'WaitEndBuild_eNB': + RAN.Build_eNB_args=test.findtext('Build_eNB_args') + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() - RAN.Setair_interface(CiTestObj.air_interface) + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' - if action == 'Terminate_eNB': - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') - CiTestObj.air_interface = test.findtext('air_interface') - if (CiTestObj.air_interface is None): - CiTestObj.air_interface = 'lte' + elif action == 'Initialize_eNB': + RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args') + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() - RAN.Setair_interface(CiTestObj.air_interface) + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem' + elif (air_interface.lower() in ['nr','lte']): + RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem' + else : + RAN.air_interface[RAN.eNB_instance] = 'ocp-enb' - if action == 'Attach_UE': + elif action == 'Terminate_eNB': + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 + else: + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem' + elif (air_interface.lower() in ['nr','lte']): + RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem' + else : + RAN.air_interface[RAN.eNB_instance] = 'ocp-enb' + + elif action == 'Attach_UE': nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') if (nbMaxUEtoAttach is None): CiTestObj.nbMaxUEtoAttach = -1 else: CiTestObj.nbMaxUEtoAttach = int(nbMaxUEtoAttach) - if action == 'CheckStatusUE': + elif action == 'CheckStatusUE': expectedNBUE = test.findtext('expectedNbOfConnectedUEs') if (expectedNBUE is None): CiTestObj.expectedNbOfConnectedUEs = -1 else: CiTestObj.expectedNbOfConnectedUEs = int(expectedNBUE) - if action == 'Build_OAI_UE': + elif action == 'Build_OAI_UE': CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') CiTestObj.clean_repository = test.findtext('clean_repository') if (CiTestObj.clean_repository == 'false'): @@ -3158,27 +3243,46 @@ def GetParametersFromXML(action): else: CiTestObj.clean_repository = True - if action == 'Initialize_OAI_UE': + elif action == 'Initialize_OAI_UE': CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') - CiTestObj.UE_instance = test.findtext('UE_instance') - if (CiTestObj.UE_instance is None): - CiTestObj.UE_instance = '0' - CiTestObj.air_interface = test.findtext('air_interface') - if (CiTestObj.air_interface is None): - CiTestObj.air_interface = 'lte' + UE_instance = test.findtext('UE_instance') + if (UE_instance is None): + CiTestObj.UE_instance = 0 else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() + CiTestObj.UE_instance = UE_instance + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + CiTestObj.air_interface = 'lte-uesoftmodem' + elif (air_interface.lower() in ['nr','lte']): + CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem' + else : + #CiTestObj.air_interface = 'ocp-enb' + logging.error('OCP UE -- NOT SUPPORTED') - if action == 'Terminate_OAI_UE': - RAN.SeteNB_instance(test.findtext('UE_instance')) - if (CiTestObj.UE_instance is None): + elif action == 'Terminate_OAI_UE': + UE_instance=test.findtext('UE_instance') + if (UE_instance is None): CiTestObj.UE_instance = '0' + else: + CiTestObj.UE_instance = int(UE_instance) + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + CiTestObj.air_interface = 'lte-uesoftmodem' + elif (air_interface.lower() in ['nr','lte']): + CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem' + else : + #CiTestObj.air_interface = 'ocp-enb' + logging.error('OCP UE -- NOT SUPPORTED') - if action == 'Ping' or action == 'Ping_CatM_module': + elif (action == 'Ping') or (action == 'Ping_CatM_module'): CiTestObj.ping_args = test.findtext('ping_args') CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') - if action == 'Iperf': + elif action == 'Iperf': CiTestObj.iperf_args = test.findtext('iperf_args') CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') CiTestObj.iperf_profile = test.findtext('iperf_profile') @@ -3196,14 +3300,14 @@ def GetParametersFromXML(action): logging.debug('ERROR: test-case has wrong option ' + CiTestObj.iperf_options) CiTestObj.iperf_options = 'check' - if action == 'IdleSleep': + elif action == 'IdleSleep': string_field = test.findtext('idle_sleep_time_in_sec') if (string_field is None): CiTestObj.idle_sleep_time = 5 else: CiTestObj.idle_sleep_time = int(string_field) - if action == 'Perform_X2_Handover': + elif action == 'Perform_X2_Handover': string_field = test.findtext('x2_ho_options') if (string_field is None): CiTestObj.x2_ho_options = 'network' @@ -3214,7 +3318,7 @@ def GetParametersFromXML(action): else: CiTestObj.x2_ho_options = string_field - if action == 'Build_PhySim': + elif action == 'Build_PhySim': ldpc.buildargs = test.findtext('physim_build_args') forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): @@ -3225,8 +3329,9 @@ def GetParametersFromXML(action): else: ldpc.forced_workspace_cleanup=False - if action == 'Run_PhySim': + else: # ie action == 'Run_PhySim': ldpc.runargs = test.findtext('physim_run_args') + #check if given test is in list #it is in list if one of the strings in 'list' is at the beginning of 'test' @@ -3240,207 +3345,95 @@ def test_in_list(test, list): def receive_signal(signum, frame): sys.exit(1) -#----------------------------------------------------------- -# Parameter Check -#----------------------------------------------------------- -mode = '' -CiTestObj = OaiCiTest() -import sshconnection -import epc -import helpreadme as HELP -import ran -import html -import constants + + + + +#----------------------------------------------------------- +# MAIN PART +#----------------------------------------------------------- + +#loading xml action list from yaml +import yaml +xml_class_list_file='xml_class_list.yml' +if (os.path.isfile(xml_class_list_file)): + yaml_file=xml_class_list_file +elif (os.path.isfile('ci-scripts/'+xml_class_list_file)): + yaml_file='ci-scripts/'+xml_class_list_file +else: + logging.error("XML action list yaml file cannot be found") + sys.exit("XML action list yaml file cannot be found") + +with open(yaml_file,'r') as f: + # The FullLoader parameter handles the conversion-$ + #from YAML scalar values to Python dictionary format$ + xml_class_list = yaml.load(f,Loader=yaml.FullLoader) + + + +mode = '' + +CiTestObj = OaiCiTest() SSH = sshconnection.SSHConnection() EPC = epc.EPCManagement() RAN = ran.RANManagement() HTML = html.HTMLManagement() -EPC.SetHtmlObj(HTML) -RAN.SetHtmlObj(HTML) -RAN.SetEpcObj(EPC) +EPC.htmlObj=HTML +RAN.htmlObj=HTML +RAN.epcObj=EPC + -import cls_physim #class PhySim for physical simulators build and test ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU build -argvs = sys.argv -argc = len(argvs) + + +#----------------------------------------------------------- +# Parsing Command Line Arguments +#----------------------------------------------------------- + +import args_parse +py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,HELP) + + + +#----------------------------------------------------------- +# TEMPORARY params management +#----------------------------------------------------------- +#temporary solution for testing: +if py_param_file_present == True: + AssignParams(py_params) + +#for debug +#print(RAN.__dict__) +#print(CiTestObj.__dict__) +#print(HTML.__dict__) +#print(ldpc.__dict__) +#for debug + + +#----------------------------------------------------------- +# COTS UE instanciation +#----------------------------------------------------------- +#COTS_UE instanciation and ADB server init +#ue id and ue mode are retrieved from xml +COTS_UE=cls_cots_ue.CotsUe(CiTestObj.ADBIPAddress, CiTestObj.ADBUserName,CiTestObj.ADBPassword) + + +#----------------------------------------------------------- +# XML class (action) analysis +#----------------------------------------------------------- cwd = os.getcwd() -while len(argvs) > 1: - myArgv = argvs.pop(1) # 0th is this file's name - - if re.match('^\-\-help$', myArgv, re.IGNORECASE): - HELP.GenericHelp(CONST.Version) - sys.exit(0) - elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) - mode = matchReg.group(1) - elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ranRepository = matchReg.group(1) - RAN.SetranRepository(matchReg.group(1)) - HTML.SetranRepository(matchReg.group(1)) - ldpc.ranRepository=matchReg.group(1) - elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) - doMerge = matchReg.group(1) - ldpc.ranAllowMerge=matchReg.group(1) - if ((doMerge == 'true') or (doMerge == 'True')): - CiTestObj.ranAllowMerge = True - RAN.SetranAllowMerge(True) - HTML.SetranAllowMerge(True) - elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ranBranch = matchReg.group(1) - RAN.SetranBranch(matchReg.group(1)) - HTML.SetranBranch(matchReg.group(1)) - ldpc.ranBranch=matchReg.group(1) - elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - CiTestObj.ranCommitID = matchReg.group(1) - RAN.SetranCommitID(matchReg.group(1)) - HTML.SetranCommitID(matchReg.group(1)) - ldpc.ranCommitID=matchReg.group(1) - elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - CiTestObj.ranTargetBranch = matchReg.group(1) - RAN.SetranTargetBranch(matchReg.group(1)) - HTML.SetranTargetBranch(matchReg.group(1)) - ldpc.ranTargetBranch=matchReg.group(1) - elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBIPAddress(matchReg.group(1)) - ldpc.eNBIpAddr=matchReg.group(1) - elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1IPAddress(matchReg.group(1)) - elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2IPAddress(matchReg.group(1)) - elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBUserName(matchReg.group(1)) - ldpc.eNBUserName=matchReg.group(1) - elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1UserName(matchReg.group(1)) - elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2UserName(matchReg.group(1)) - elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBPassword(matchReg.group(1)) - ldpc.eNBPassWord=matchReg.group(1) - elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1Password(matchReg.group(1)) - elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2Password(matchReg.group(1)) - elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBSourceCodePath(matchReg.group(1)) - ldpc.eNBSourceCodePath=matchReg.group(1) - elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1SourceCodePath(matchReg.group(1)) - elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2SourceCodePath(matchReg.group(1)) - elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - EPC.SetIPAddress(matchReg.group(1)) - elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - EPC.SetUserName(matchReg.group(1)) - elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - EPC.SetPassword(matchReg.group(1)) - elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - EPC.SetSourceCodePath(matchReg.group(1)) - elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) - if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-Docker', matchReg.group(1), re.IGNORECASE): - EPC.SetType(matchReg.group(1)) - else: - sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS or OAI-Rel14-Docker)') - elif re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE) - EPC.SetContainerPrefix(matchReg.group(1)) - elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ADBIPAddress = matchReg.group(1) - elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ADBUserName = matchReg.group(1) - elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) - if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): - if re.match('distributed', matchReg.group(1), re.IGNORECASE): - CiTestObj.ADBCentralized = False - else: - CiTestObj.ADBCentralized = True - else: - sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') - elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ADBPassword = matchReg.group(1) - elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.testXMLfiles.append(matchReg.group(1)) - HTML.SettestXMLfiles(matchReg.group(1)) - HTML.SetnbTestXMLfiles(HTML.GetnbTestXMLfiles()+1) - elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEIPAddress = matchReg.group(1) - elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEUserName = matchReg.group(1) - elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEPassword = matchReg.group(1) - elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UESourceCodePath = matchReg.group(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')): - CiTestObj.finalStatus = True - else: - HELP.GenericHelp(CONST.Version) - sys.exit('Invalid Parameter: ' + myArgv) - if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - RAN.SeteNB_serverId('0') - RAN.SeteNB_instance('0') - RAN.SeteNBSourceCodePath('/tmp/') + RAN.eNB_serverId='0' + RAN.eNB_instance=0 + RAN.eNBSourceCodePath='/tmp/' RAN.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): @@ -3455,52 +3448,52 @@ elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): signal.signal(signal.SIGUSR1, receive_signal) CiTestObj.TerminateOAIUE() elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath== '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): + if (RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectBuild() elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectHSS() elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectMME() elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectSPGW() elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectPing() elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectIperf() @@ -3515,7 +3508,7 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): sys.exit('Insufficient Parameter') count = 0 foundCount = 0 - while (count < HTML.GetnbTestXMLfiles()): + while (count < HTML.nbTestXMLfiles): #xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count] xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count] if (os.path.isfile(xml_test_file)): @@ -3524,21 +3517,21 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): except: print("Error while parsing file: " + xml_test_file) xmlRoot = xmlTree.getroot() - HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='test-tab-' + str(count))) - HTML.SethtmlTabIcons(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='test-tab-' + str(count))) + HTML.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) foundCount += 1 count += 1 - if foundCount != HTML.GetnbTestXMLfiles(): - HTML.SetnbTestXMLfiles(foundCount) + if foundCount != HTML.nbTestXMLfiles: + HTML.nbTestXMLfiles=foundCount if (CiTestObj.ADBIPAddress != 'none'): terminate_ue_flag = False CiTestObj.GetAllUEDevices(terminate_ue_flag) CiTestObj.GetAllCatMDevices(terminate_ue_flag) HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) - HTML.SethtmlNb_Smartphones(len(CiTestObj.UEDevices)) - HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices)) + HTML.htmlNb_Smartphones=len(CiTestObj.UEDevices) + HTML.htmlNb_CATM_Modules=len(CiTestObj.CatMDevices) HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): logging.debug('\u001B[1m----------------------------------------\u001B[0m') @@ -3550,19 +3543,19 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': + if RAN.eNBIPAddress == '' or RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '' or EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': HELP.GenericHelp(CONST.Version) - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': - HELP.EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) - if RAN.GetranRepository() == '': - HELP.GitSrvHelp(RAN.GetranRepository(), RAN.GetranBranch(), RAN.GetranCommitID(), RAN.GetranAllowMerge(), RAN.GetranTargetBranch()) - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': - HELP.eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath()) + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or EPC.Type == '': + HELP.EPCSrvHelp(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath, EPC.Type) + if RAN.ranRepository == '': + HELP.GitSrvHelp(RAN.ranRepository, RAN.ranBranch, RAN.ranCommitID, RAN.ranAllowMerge, RAN.ranTargetBranch) + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': + HELP.eNBSrvHelp(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath) sys.exit('Insufficient Parameter') - if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/active_net_interfaces.awk", "/tmp") + if (EPC.IPAddress!= '') and (EPC.IPAddress != 'none'): + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, cwd + "/active_net_interfaces.awk", "/tmp") else: if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': HELP.GenericHelp(CONST.Version) @@ -3570,7 +3563,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re #read test_case_list.xml file # if no parameters for XML file, use default value - if (HTML.GetnbTestXMLfiles() != 1): + if (HTML.nbTestXMLfiles != 1): xml_test_file = cwd + "/test_case_list.xml" else: xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] @@ -3580,9 +3573,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (HTML.GetnbTestXMLfiles() == 1): - HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0')) + if (HTML.nbTestXMLfiles == 1): + HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') CiTestObj.repeatCounts.append(int(repeatCount)) all_tests=xmlRoot.findall('testCase') @@ -3610,7 +3603,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: logging.debug('ERROR: requested test is invalidly formatted: ' + test) sys.exit(1) - if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): + if (EPC.IPAddress != '') and (EPC.IPAddress != 'none'): CiTestObj.CheckFlexranCtrlInstallation() EPC.SetMmeIPAddress() @@ -3635,35 +3628,36 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.CreateHtmlTabHeader() CiTestObj.FailReportCnt = 0 - RAN.SetprematureExit(True) - HTML.SetstartTime(int(round(time.time() * 1000))) - while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): - RAN.SetprematureExit(False) + RAN.prematureExit=True + HTML.startTime=int(round(time.time() * 1000)) + while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.prematureExit: + RAN.prematureExit=False # At every iteratin of the retry loop, a separator will be added # pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt) for test_case_id in todo_tests: - if RAN.GetprematureExit(): + if RAN.prematureExit: break for test in all_tests: - if RAN.GetprematureExit(): + if RAN.prematureExit: break id = test.get('id') if test_case_id != id: continue CiTestObj.testCase_id = id - HTML.SettestCase_id(CiTestObj.testCase_id) - EPC.SetTestCase_id(CiTestObj.testCase_id) + HTML.testCase_id=CiTestObj.testCase_id + EPC.testCase_id=CiTestObj.testCase_id CiTestObj.desc = test.findtext('desc') - HTML.Setdesc(CiTestObj.desc) + HTML.desc=CiTestObj.desc action = test.findtext('class') - if (CheckClassValidity(action, id) == False): + if (CheckClassValidity(xml_class_list, action, id) == False): continue CiTestObj.ShowTestID() GetParametersFromXML(action) if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': if (CiTestObj.ADBIPAddress != 'none'): - terminate_ue_flag = False + #in these cases, having no devices is critical, GetAllUEDevices function has to manage it as a critical error, reason why terminate_ue_flag is set to True + terminate_ue_flag = True CiTestObj.GetAllUEDevices(terminate_ue_flag) if action == 'Build_eNB': RAN.BuildeNB() @@ -3672,7 +3666,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'Initialize_eNB': check_eNB = False check_OAI_UE = False - RAN.SetpStatus(CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE)) + RAN.pStatus=CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE) RAN.InitializeeNB() elif action == 'Terminate_eNB': @@ -3739,15 +3733,17 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'Run_PhySim': HTML=ldpc.Run_PhySim(HTML,CONST,id) else: - sys.exit('Invalid action') + sys.exit('Invalid class (action) from xml') CiTestObj.FailReportCnt += 1 - if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): + if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.prematureExit: logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(True) +elif re.match('^LoadParams$', mode, re.IGNORECASE): + pass else: HELP.GenericHelp(CONST.Version) sys.exit('Invalid mode') diff --git a/ci-scripts/py_params.yaml b/ci-scripts/py_params.yaml new file mode 100644 index 0000000000..303d5d1006 --- /dev/null +++ b/ci-scripts/py_params.yaml @@ -0,0 +1,53 @@ +eNBRepository : b +ranRepository : c +eNB_AllowMerge : +ranAllowMerge : +eNBBranch : f +ranBranch : g +eNBCommitID : +ranCommitID : i +eNBTargetBranch : j +ranTargetBranch : k + +nodes : + - type : eNB + IPAddress : 001.1.1 + UserName : toto + Password : qwe + SourceCodePath : l + - type : gNB + IPAddress : 002.2.2 + UserName : tata + Password : asd + SourceCodePath : m + - type : eNB + IPAddress : 003.3.3 + UserName : titi + Password : zxc + SourceCodePath : n + - type : gNB + IPAddress : 004.4.4 + UserName : caca + Password : pepe + SourceCodePath : o + +EPCIPAddress : p +EPCUserName : q +EPCPassword : r +EPCSourceCodePath : s +EPCType : t +EPCContainerPrefix : u + +ADBIPAddress : v +ADBUserName : w +ADBType : x +ADBPassword : y + +XMLTestFile : z + +UEIPAddress : qqq +UEUserName : www +UEPassword : eee +UESourceCodePath : yyy + +finalStatus : bbb \ No newline at end of file diff --git a/ci-scripts/py_params_template.yaml b/ci-scripts/py_params_template.yaml new file mode 100644 index 0000000000..aaf31c1576 --- /dev/null +++ b/ci-scripts/py_params_template.yaml @@ -0,0 +1,97 @@ +eNBRepository : b +ranRepository : c +eNB_AllowMerge : +ranAllowMerge : +eNBBranch : f +ranBranch : g +eNBCommitID : +ranCommitID : i +eNBTargetBranch : j +ranTargetBranch : k + + +RAN: + RAN_inst_0: + name : RAN_1 + nodes : + - type : eNB + IPAddress : 001.1.1 + UserName : toto + Password : qwe + SourceCodePath : l + - type : gNB + IPAddress : 002.2.2 + UserName : tata + Password : asd + SourceCodePath : m + - type : eNB + IPAddress : 003.3.3 + UserName : titi + Password : zxc + SourceCodePath : n + - type : gNB + IPAddress : 004.4.4 + UserName : caca + Password : pepe + SourceCodePath : o + RAN_inst_1: + name : RAN_2 + nodes : + - type : eNB + IPAddress : 101.1.1 + UserName : toto + Password : qwe + SourceCodePath : l + - type : gNB + IPAddress : 102.2.2 + UserName : zaza + Password : asd + SourceCodePath : m + - type : eNB + IPAddress : 103.3.3 + UserName : zizi + Password : zxc + SourceCodePath : n + - type : gNB + IPAddress : 104.4.4 + UserName : aaaa + Password : pepe + SourceCodePath : o + + + +EPC: + EPC_inst_0: + EPCIPAddress : p + EPCUserName : q + EPCPassword : r + EPCSourceCodePath : s + EPCType : t + EPCContainerPrefix : u + +ADB: + ADBIPAddress : v + ADBUserName : w + ADBType : x + ADBPassword : y + + +UE: + UE_inst_0: + name : UE_1 + type : + UEIPAddress : qqq + UEUserName : www + UEPassword : eee + UESourceCodePath : yyy + UE_inst_1: + name : UE_2 + type : + UEIPAddress : bloblob + UEUserName : gwou + UEPassword : zebu + UESourceCodePath : pop + + +XMLTestFile : z +finalStatus : bbb \ No newline at end of file diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 287c18021e..d5906e9567 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -77,8 +77,8 @@ class RANManagement(): self.backgroundBuildTestId = ['', '', ''] self.Build_eNB_forced_workspace_cleanup = False self.Initialize_eNB_args = '' - self.air_interface = 'lte' - self.eNB_instance = '' + self.air_interface = ['', '', ''] #changed from 'lte' to '' may lead to side effects in main + self.eNB_instance = 0 self.eNB_serverId = '' self.eNBLogFiles = ['', '', ''] self.eNBOptions = ['', '', ''] @@ -90,141 +90,9 @@ class RANManagement(): self.epcPcapFile = '' self.htmlObj = None self.epcObj = None + self.runtime_stats= '' -#----------------------------------------------------------- -# Setters and Getters on Public members -#----------------------------------------------------------- - def SetHtmlObj(self, obj): - self.htmlObj = obj - def SetEpcObj(self, obj): - self.epcObj = obj - - def SetflexranCtrlInstalled(self,fxrctin): - self.flexranCtrlInstalled = fxrctin - def GetflexranCtrlInstalled(self): - return self.flexranCtrlInstalled - def SetflexranCtrlStarted(self,fxrctst): - self.flexranCtrlStarted = fxrctst - def GetflexranCtrlStarted(self): - return self.flexranCtrlStarted - def SetpStatus(self, pSt): - self.pStatus = pSt - def SetranRepository(self, repository): - self.ranRepository = repository - def GetranRepository(self): - return self.ranRepository - def SetranBranch(self, branch): - self.ranBranch = branch - def GetranBranch(self): - return self.ranBranch - def SetranCommitID(self, commitid): - self.ranCommitID = commitid - def GetranCommitID(self): - return self.ranCommitID - def SeteNB_serverId(self, enbsrvid): - self.eNB_serverId = enbsrvid - def GeteNB_serverId(self): - return self.eNB_serverId - def SeteNBIPAddress(self, enbip): - self.eNBIPAddress = enbip - def GeteNBIPAddress(self): - return self.eNBIPAddress - def SeteNBUserName(self, enbusr): - self.eNBUserName = enbusr - def GeteNBUserName(self): - return self.eNBUserName - def SeteNBPassword(self, enbpw): - self.eNBPassword = enbpw - def GeteNBPassword(self): - return self.eNBPassword - def SeteNBSourceCodePath(self, enbcodepath): - self.eNBSourceCodePath = enbcodepath - def GeteNBSourceCodePath(self): - return self.eNBSourceCodePath - def SetranAllowMerge(self, merge): - self.ranAllowMerge = merge - def GetranAllowMerge(self): - return self.ranAllowMerge - def SetranTargetBranch(self, tbranch): - self.ranTargetBranch = tbranch - def GetranTargetBranch(self): - return self.ranTargetBranch - def SetBuild_eNB_args(self, enbbuildarg): - self.Build_eNB_args = enbbuildarg - def GetBuild_eNB_args(self): - return self.Build_eNB_args - def SetInitialize_eNB_args(self, initenbarg): - self.Initialize_eNB_args = initenbarg - def GetInitialize_eNB_args(self): - return self.Initialize_eNB_args - def SetbackgroundBuild(self, bkbuild): - self.backgroundBuild = bkbuild - def GetbackgroundBuild(self): - return self.backgroundBuild - def SetbackgroundBuildTestId(self, bkbuildid): - self.backgroundBuildTestId = bkbuildid - def GetbackgroundBuildTestId(self): - return self.backgroundBuildTestId - def SetBuild_eNB_forced_workspace_cleanup(self, fcdwspclean): - self.Build_eNB_forced_workspace_cleanup = fcdwspclean - def GetBuild_eNB_forced_workspace_cleanup(self): - return self.Build_eNB_forced_workspace_cleanup - def Setair_interface(self, airif): - self.air_interface = airif - def Getair_interface(self): - return self.air_interface - def SeteNB_instance(self, enbinst): - self.eNB_instance = enbinst - def GeteNB_instance(self): - return self.eNB_instance - - def SeteNBLogFile(self, enblog, idx): - self.eNBLogFiles[idx] = enblog - def GeteNBLogFile(self, idx): - return self.eNBLogFiles[idx] - - def GeteNBmbmsEnable(self, idx): - return self.eNBmbmsEnables[idx] - - def SeteNB1IPAddress(self,enb1ip): - self.eNB1IPAddress = enb1ip - def GeteNB1IPAddress(self): - return self.eNB1IPAddress - def SeteNB1UserName(self, enb1usr): - self.eNB1UserName = enb1usr - def GeteNB1UserName(self): - return self.eNB1UserName - def SeteNB1Password(self, enb1pw): - self.eNB1Password = enb1pw - def GeteNB1Password(self): - return self.eNB1Password - def SeteNB1SourceCodePath(self, enb1codepath): - self.eNB1SourceCodePath = enb1codepath - def GeteNB1SourceCodePath(self): - return self.eNB1SourceCodePath - - def SeteNB2IPAddress(self, enb2ip): - self.eNB2IPAddress = enb2ip - def GeteNB2IPAddress(self): - return self.eNB2IPAddress - def SeteNB2UserName(self, enb2usr): - self.eNB2UserName = enb2usr - def GeteNB2UserName(self): - return self.eNB2UserName - def SeteNB2Password(self, enb2pw): - self.eNB2Password = enb2pw - def GeteNB2Password(self): - return self.eNB2Password - def SeteNB2SourceCodePath(self, enb2codepath): - self.eNB2SourceCodePath = enb2codepath - def GeteNB2SourceCodePath(self): - return self.eNB2SourceCodePath - - def SetprematureExit(self, premex): - self.prematureExit = premex - def GetprematureExit(self): - return self.prematureExit #----------------------------------------------------------- # RAN management functions @@ -254,17 +122,23 @@ class RANManagement(): sys.exit('Insufficient Parameter') mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) - # Check if we build an 5G-NR gNB or an LTE eNB - result = re.search('--gNB', self.Build_eNB_args) + + # Check if we build an 5G-NR gNB or an LTE eNB or an OCP eNB + result = re.search('--eNBocp', self.Build_eNB_args) if result is not None: - self.air_interface = 'nr' - else: - self.air_interface = 'lte' + self.air_interface[self.eNB_instance] = 'ocp-enb' + else: + result = re.search('--gNB', self.Build_eNB_args) + if result is not None: + self.air_interface[self.eNB_instance] = 'nr-softmodem' + else: + self.air_interface[self.eNB_instance] = 'lte-softmodem' + # Worakround for some servers, we need to erase completely the workspace if self.Build_eNB_forced_workspace_cleanup: mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) if self.htmlObj is not None: - self.testCase_id = self.htmlObj.GettestCase_id() + self.testCase_id = self.htmlObj.testCase_id else: self.testCase_id = '000000' # on RedHat/CentOS .git extension is mandatory @@ -332,7 +206,8 @@ class RANManagement(): if self.backgroundBuild: mySSH.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) mySSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) - mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S ls', '\$', 5) + mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-build.sh' + ' > ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ' + ' 2>&1 &', lUserName, 5) mySSH.close() if self.htmlObj is not None: self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) @@ -378,21 +253,21 @@ class RANManagement(): def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): if self.htmlObj is not None: - self.htmlObj.SettestCase_id(testcaseId) + self.htmlObj.testCase_id=testcaseId + mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) mySSH.command('ls ran_build/build', '\$', 3) mySSH.command('ls ran_build/build', '\$', 3) - if self.air_interface == 'nr': - nodeB_prefix = 'g' - else: - nodeB_prefix = 'e' - buildStatus = True - result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) + + #check if we have the build corresponding to the air interface keywords (nr-softmode, lte-softmodem, ocp-enb) + logging.info('CHECK Build with IP='+lIpAddr+' SourcePath='+lSourcePath) + result = re.search(self.air_interface[self.eNB_instance], mySSH.getBefore()) if result is None: - buildStatus = False + buildStatus = False #if not, build failed else: + buildStatus = True # Generating a BUILD INFO file mySSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) mySSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) @@ -404,6 +279,8 @@ class RANManagement(): mySSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: mySSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + + mySSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) mySSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) mySSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) @@ -420,18 +297,20 @@ class RANManagement(): os.remove('./tmp_build' + testcaseId + '.zip') mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) mySSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - mySSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + #-qq quiet / -u update orcreate files + mySSH.command('unzip -u -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) mySSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) mySSH.close() else: mySSH.close() + #generate logging info depending on buildStatus and air interface if buildStatus: - logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') + logging.info('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Pass\u001B[0m') if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) else: - logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') + logging.error('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Failed\u001B[0m') if self.htmlObj is not None: self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) self.htmlObj.CreateHtmlTabFooter(False) @@ -458,22 +337,22 @@ class RANManagement(): sys.exit('Insufficient Parameter') if self.htmlObj is not None: - self.testCase_id = self.htmlObj.GettestCase_id() + self.testCase_id = self.htmlObj.testCase_id else: self.testCase_id = '000000' mySSH = SSH.SSHConnection() if (self.pStatus < 0): if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', self.pStatus) + self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' ' + self.Initialize_eNB_args, 'KO', self.pStatus) self.htmlObj.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) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.GetIPAddress() - localEpcUserName = self.epcObj.GetUserName() - localEpcPassword = self.epcObj.GetPassword() + localEpcIpAddr = self.epcObj.IPAddress + localEpcUserName = self.epcObj.UserName + localEpcPassword = self.epcObj.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) mySSH.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', mySSH.getBefore()) @@ -522,12 +401,14 @@ class RANManagement(): # Make a copy and adapt to EPC / eNB IP addresses mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) if self.epcObj is not None: - localMmeIpAddr = self.epcObj.GetMmeIPAddress() + localMmeIpAddr = self.epcObj.MmeIPAddress mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_GNB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_FR1_CTL_ENB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); if self.flexranCtrlInstalled and self.flexranCtrlStarted: mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); else: @@ -549,15 +430,11 @@ class RANManagement(): if self.air_interface == 'nr': mySSH.command('if [ -e rbconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) mySSH.command('if [ -e reconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm reconfig.raw; fi', '\$', 5) - mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + # NOTE: WE SHALL do a check if the executable is present (in case build went wrong) + mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) mySSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - mySSH.command('hostnamectl','\$', 5) - result = re.search('CentOS Linux 7', mySSH.getBefore()) - if result is not None: - mySSH.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) - else: - mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' if extra_options != '': self.eNBOptions[int(self.eNB_instance)] = extra_options @@ -574,15 +451,15 @@ class RANManagement(): mySSH.command('killall --signal SIGKILL record', '\$', 5) mySSH.close() doLoop = False - logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') + logging.error('\u001B[1;37;41m eNB/gNB/ocp-eNB logging system did not show got sync! \u001B[0m') if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) # 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) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.GetIPAddress() - localEpcUserName = self.epcObj.GetUserName() - localEpcPassword = self.epcObj.GetPassword() + localEpcIpAddr = self.epcObj.IPAddress + localEpcUserName = self.epcObj.UserName + localEpcPassword = self.epcObj.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -634,8 +511,8 @@ class RANManagement(): mySSH.close() if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) - logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') + self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) + logging.debug('\u001B[1m Initialize eNB/gNB/ocp-eNB Completed\u001B[0m') def CheckeNBProcess(self, status_queue): try: @@ -658,8 +535,8 @@ class RANManagement(): lPassWord = self.eNBPassword mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) - mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) - result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface[self.eNB_instance] + ' | grep -v grep', '\$', 5) + result = re.search(self.air_interface[self.eNB_instance], mySSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') status_queue.put(CONST.ENB_PROCESS_FAILED) @@ -691,29 +568,28 @@ class RANManagement(): mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - if self.air_interface == 'lte': + if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): nodeB_prefix = 'e' else: nodeB_prefix = 'g' - mySSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', mySSH.getBefore()) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never -e softmodem -e ocp-enb | grep -v grep', '\$', 5) + result = re.search('(-softmodem|ocp)', mySSH.getBefore()) if result is not None: - mySSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) - mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem ocp-enb || true', '\$', 5) time.sleep(10) - mySSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', mySSH.getBefore()) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never -e softmodem -e ocp-enb | grep -v grep', '\$', 5) + result = re.search('(-softmodem|ocp)', mySSH.getBefore()) if result is not None: - mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem ocp-enb || true', '\$', 5) time.sleep(5) mySSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) mySSH.close() # 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) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.GetIPAddress() - localEpcUserName = self.epcObj.GetUserName() - localEpcPassword = self.epcObj.GetPassword() + localEpcIpAddr = self.epcObj.IPAddress + localEpcUserName = self.epcObj.UserName + localEpcPassword = self.epcObj.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -739,7 +615,7 @@ class RANManagement(): logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) self.eNBLogFiles[int(self.eNB_instance)] = '' else: analyzeFile = False @@ -752,7 +628,7 @@ class RANManagement(): if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') if self.htmlObj is not None: - self.htmlObj.SetHmleNBFailureMsg('Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!') + self.htmlObj.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' self.htmlObj.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBmbmsEnables[int(self.eNB_instance)] = False return @@ -768,10 +644,10 @@ class RANManagement(): return else: if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) else: if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 @@ -823,7 +699,34 @@ class RANManagement(): X2HO_inNbProcedures = 0 X2HO_outNbProcedures = 0 global_status = CONST.ALL_PROCESSES_OK + # Runtime statistics + runTime = '' + userTime = '' + systemTime = '' + maxPhyMemUsage = '' + nbContextSwitches = '' for line in enb_log_file.readlines(): + # Runtime statistics + result = re.search('Run time:' ,str(line)) + if result is not None: + runTime = str(line).strip() + if runTime != '': + result = re.search('Time executing user inst', str(line)) + if result is not None: + fields=line.split(':') + userTime = 'userTime : ' + fields[1].replace('\n','') + result = re.search('Time executing system inst', str(line)) + if result is not None: + fields=line.split(':') + systemTime = 'systemTime : ' + fields[1].replace('\n','') + result = re.search('Max. Phy. memory usage:', str(line)) + if result is not None: + fields=line.split(':') + maxPhyMemUsage = 'maxPhyMemUsage : ' + fields[1].replace('\n','') + result = re.search('Number of context switch.*process origin', str(line)) + if result is not None: + fields=line.split(':') + nbContextSwitches = 'nbContextSwitches : ' + fields[1].replace('\n','') if X2HO_state == CONST.X2_HO_REQ_STATE__IDLE: result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) if result is not None: @@ -896,8 +799,7 @@ class RANManagement(): if result is not None: rrcSetupComplete += 1 result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) - if result is not None: - rrcReleaseRequest += 1 + if result is not None: rrcReleaseRequest += 1 result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) if result is not None: rrcReconfigRequest += 1 @@ -955,11 +857,11 @@ class RANManagement(): mbmsRequestMsg += 1 enb_log_file.close() logging.debug(' File analysis completed') - if self.air_interface == 'lte': + if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): nodeB_prefix = 'e' else: nodeB_prefix = 'g' - if self.air_interface == 'nr': + if self.air_interface[self.eNB_instance] == 'nr-softmodem': if ulschReceiveOK > 0: statMsg = nodeB_prefix + 'NB showed ' + str(ulschReceiveOK) + ' "ULSCH received ok" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') @@ -1080,5 +982,13 @@ class RANManagement(): htmleNBFailureMsg += rlcMsg + '\n' global_status = CONST.ENB_PROCESS_REALTIME_ISSUE if self.htmlObj is not None: - self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) + self.htmlObj.htmleNBFailureMsg=htmleNBFailureMsg + # Runtime statistics for console output and HTML + if runTime != '': + logging.debug(runTime) + logging.debug(userTime) + logging.debug(systemTime) + logging.debug(maxPhyMemUsage) + logging.debug(nbContextSwitches) + self.runtime_stats='
'+runTime + '\n'+ userTime + '\n' + systemTime + '\n' + maxPhyMemUsage + '\n' + nbContextSwitches+'
' return global_status diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index 897f9285e9..b05ccf39db 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -620,6 +620,101 @@ function report_test { #IPERF_TESTS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_ul*client*txt | grep -v mbms 2> /dev/null` #analyzeIperfFiles done + + # FeMBMS Case + CN_CONFIG="noS1" + TMODE="fdd" + BW_CASES=(05) + for BW in ${BW_CASES[@]} + do + echo " " >> ./test_simulator_results.html + echo " Test FeMBMS without EPC (aka noS1): ${TMODE} -- ${BW}MHz " >> ./test_simulator_results.html + echo " " >> ./test_simulator_results.html + ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_enb_fembms.log + UE_LOG=`echo $ENB_LOG | sed -e "s#enb#ue#"` + if [ -f $ENB_LOG ] && [ -f $UE_LOG ] + then + NAME_ENB=`echo $ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"` + NAME_UE=`echo $UE_LOG | sed -e "s#$ARCHIVES_LOC/##"` + echo " " >> ./test_simulator_results.html + echo " $NAME_ENB --- $NAME_UE" >> ./test_simulator_results.html + echo " N/A" >> ./test_simulator_results.html + #NB_ENB_GOT_SYNC=`egrep -c "got sync" $ENB_LOG` + NB_ENB_TUNNEL_UP=`egrep -c "Interface oaitun_enb1 successfully configured" $ENB_LOG` + NB_ENB_MTUNNEL_UP=`egrep -c "Interface oaitun_enm1 successfully configured" $ENB_LOG` + #NB_UE_GOT_SYNC=`egrep -c "rfsimulator: Success" $UE_LOG` + #NB_ENB_SYNCED_WITH_UE=`egrep -c "Generating RRCConnectionReconfigurationComplete" $UE_LOG` + NB_UE_TUNNEL_UP=`egrep -c "Interface oaitun_ue1 successfully configured" $UE_LOG` + NB_UE_MTUNNEL_UP=`egrep -c "Interface oaitun_uem1 successfully configured" $UE_LOG` + NB_UE_MBMS_PUSH_MSG=`egrep -c "TRIED TO PUSH MBMS DATA TO" $UE_LOG` + #if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -gt 0 ] && [ $NB_ENB_SYNCED_WITH_UE -gt 0 ] && [ $NB_UE_MBMS_PUSH_MSG -gt 0 ] + if [ $NB_UE_MBMS_PUSH_MSG -gt 0 ] + then + echo " OK" >> ./test_simulator_results.html + else + echo " KO" >> ./test_simulator_results.html + fi + echo "
" >> ./test_simulator_results.html
+                #if [ $NB_ENB_GOT_SYNC -gt 0 ]
+                #then
+                #    echo "- eNB --> got sync" >> ./test_simulator_results.html
+                #else
+                #    echo "- eNB NEVER got sync" >> ./test_simulator_results.html
+                #fi
+                if [ $NB_ENB_TUNNEL_UP -gt 0 ]
+                then
+                    echo "- eNB mounted oaitun_enb1 interface" >> ./test_simulator_results.html
+                else
+                    echo "- eNB NEVER mounted oaitun_enb1 interface" >> ./test_simulator_results.html
+                fi
+                if [ $NB_ENB_MTUNNEL_UP -gt 0 ]
+                then
+                    echo "- eNB mounted oaitun_enm1 interface" >> ./test_simulator_results.html
+                else
+                    echo "- eNB NEVER mounted oaitun_enm1 interface" >> ./test_simulator_results.html
+                fi
+                #if [ $NB_UE_GOT_SYNC -gt 0 ]
+                #then
+                #    echo "- LTE UE --> got sync" >> ./test_simulator_results.html
+                #else
+                #    echo "- LTE UE NEVER got sync" >> ./test_simulator_results.html
+                #fi
+                #if [ $NB_ENB_SYNCED_WITH_UE -gt 0 ]
+                #then
+                #    echo "- LTE UE attached to eNB" >> ./test_simulator_results.html
+                #else
+                #    echo "- LTE UE NEVER attached to eNB" >> ./test_simulator_results.html
+                #fi
+                if [ $NB_UE_TUNNEL_UP -gt 0 ]
+                then
+                    echo "- LTE UE mounted oaitun_ue1 interface" >> ./test_simulator_results.html
+                else
+                    echo "- LTE UE NEVER mounted oaitun_ue1 interface" >> ./test_simulator_results.html
+                fi
+                if [ $NB_UE_MTUNNEL_UP -gt 0 ]
+                then
+                    echo "- LTE UE mounted oaitun_uem1 interface" >> ./test_simulator_results.html
+                else
+                    echo "- LTE UE NEVER mounted oaitun_uem1 interface" >> ./test_simulator_results.html
+                fi
+                if [ $NB_UE_MBMS_PUSH_MSG -gt 0 ]
+                then
+                    echo "- LTE UE tried to push ${NB_UE_MBMS_PUSH_MSG} MBMS DATA" >> ./test_simulator_results.html
+                else
+                    echo "- LTE UE NEVER pushed MBMS DATA" >> ./test_simulator_results.html
+                fi
+                echo "        
" >> ./test_simulator_results.html + echo " " >> ./test_simulator_results.html + fi + #PING_LOGS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_ping*.log 2> /dev/null` + #analyzePingFiles + + #IPERF_TESTS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_dl*client*txt | grep -v mbms 2> /dev/null` + #analyzeIperfFiles + + #IPERF_TESTS=`ls $ARCHIVES_LOC/${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_ul*client*txt | grep -v mbms 2> /dev/null` + #analyzeIperfFiles + done echo " " >> ./test_simulator_results.html echo " " >> ./test_simulator_results.html diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 0db2264c76..e6b93b5b4d 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -2027,6 +2027,70 @@ function run_test_on_vm { done + #################### + ## FeMBMS CASE noS1 ## + #################### + CONF_FILE=lte-fdd-fembms-basic-sim.conf + CN_CONFIG="noS1" + S1_NOS1_CFG=0 + LTEBOX=0 + TMODE="fdd" + FREQUENCY=2680 + BW_CASES=(05) + FeMBMS_STATUS=0 + + for BW in ${BW_CASES[@]} + do + if [[ $BW =~ .*05.* ]]; then PRB=25; fi + if [[ $BW =~ .*10.* ]]; then PRB=50; fi + if [[ $BW =~ .*20.* ]]; then PRB=100; fi + + echo "############################################################" + echo "${CN_CONFIG} : Starting the eNB with MSMS in ${TMODE}-${BW}MHz mode" + echo "############################################################" + CURRENT_ENB_LOG_FILE=${TMODE}_${BW}MHz_${CN_CONFIG}_enb_fembms.log + start_rf_sim_enb $ENB_VM_CMDS "$ENB_VM_IP_ADDR" "$EPC_VM_IP_ADDR" $CURRENT_ENB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG + + echo "############################################################" + echo "${CN_CONFIG} : Starting the UE" + echo "############################################################" + CURRENT_UE_LOG_FILE=${TMODE}_${BW}MHz_${CN_CONFIG}_ue_fembms.log + start_rf_sim_ue $UE_VM_CMDS $UE_VM_IP_ADDR $ENB_VM_IP_ADDR $CURRENT_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1 + if [ $UE_SYNC -eq 0 ] + then + echo "Problem w/ eNB and UE not syncing" + terminate_enb_ue_basic_sim $ENB_VM_CMDS $ENB_VM_IP_ADDR 1 + terminate_enb_ue_basic_sim $UE_VM_CMDS $UE_VM_IP_ADDR 2 + scp -o StrictHostKeyChecking=no ubuntu@$ENB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_ENB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_UE_LOG_FILE $ARCHIVES_LOC + STATUS=-1 + break + fi + + echo "############################################################" + echo "${CN_CONFIG} : iperf DL -- UE is server and eNB is client" + echo "############################################################" + get_enb_mbms_noS1_ip_addr $ENB_VM_CMDS $ENB_VM_IP_ADDR + IPERF_LOG_FILE=${TMODE}_${BW}MHz_${CN_CONFIG}_iperf_dl_fembms + get_ue_mbms_ip_addr $UE_VM_CMDS $UE_VM_IP_ADDR 1 + THROUGHPUT=2 + generic_iperf $UE_VM_CMDS $UE_VM_IP_ADDR $UE_IP_ADDR $ENB_VM_CMDS $ENB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $IPERF_LOG_FILE 1 0 + scp -o StrictHostKeyChecking=no ubuntu@$UE_VM_IP_ADDR:/home/ubuntu/${IPERF_LOG_FILE}_server.txt $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$ENB_VM_IP_ADDR:/home/ubuntu/${IPERF_LOG_FILE}_client.txt $ARCHIVES_LOC + #check_iperf $ARCHIVES_LOC/$IPERF_LOG_FILE $THROUGHPUT + + echo "############################################################" + echo "${CN_CONFIG} : Terminate enb/ue simulators" + echo "############################################################" + terminate_enb_ue_basic_sim $ENB_VM_CMDS $ENB_VM_IP_ADDR 1 + terminate_enb_ue_basic_sim $UE_VM_CMDS $UE_VM_IP_ADDR 2 + scp -o StrictHostKeyChecking=no ubuntu@$ENB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_ENB_LOG_FILE $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_UE_LOG_FILE $ARCHIVES_LOC + NB_UE_FeMBMS_MESSAGES=`egrep -c "TRIED TO PUSH MBMS DATA TO" $ARCHIVES_LOC/$CURRENT_UE_LOG_FILE` + if [ $NB_UE_FeMBMS_MESSAGES -eq 0 ]; then FeMBMS_STATUS=-1; fi + + done + full_l2_sim_destroy echo "############################################################" @@ -2042,6 +2106,13 @@ function run_test_on_vm { echo "LTE MBMS RFSIM seems to FAIL" STATUS=-1 fi + if [ $FeMBMS_STATUS -eq 0 ] + then + echo "LTE FeMBMS RFSIM seems OK" + else + echo "LTE FeMBMS RFSIM seems to FAIL" + STATUS=-1 + fi if [ $STATUS -eq 0 ] then echo "LTE RFSIM seems OK" @@ -2050,6 +2121,7 @@ function run_test_on_vm { echo "LTE RFSIM seems to FAIL" echo "LTE: TEST_KO" > $ARCHIVES_LOC/test_final_status.log fi + fi if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]] @@ -2064,7 +2136,7 @@ function run_test_on_vm { NR_STATUS=0 ######### start of loop - while [ $try_cnt -lt 1 ] + while [ $try_cnt -lt 4 ] do SYNC_STATUS=0 PING_STATUS=0 diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index ba0f900f29..ed0cf5379a 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -101,6 +101,18 @@ class SSHConnection(): else: sys.exit('SSH Connection Failed') + + + + def cde_check_value(self, commandline, expected, timeout): + logging.debug(commandline) + self.ssh.timeout = timeout + self.ssh.sendline(commandline) + expected.append(pexpect.EOF) + expected.append(pexpect.TIMEOUT) + self.sshresponse = self.ssh.expect(expected) + return self.sshresponse + def command(self, commandline, expectedline, timeout): logging.debug(commandline) self.ssh.timeout = timeout diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml new file mode 100755 index 0000000000..2c20988851 --- /dev/null +++ b/ci-scripts/xml_class_list.yml @@ -0,0 +1,34 @@ + - Build_PhySim + - Run_PhySim + - Build_eNB + - WaitEndBuild_eNB + - Initialize_eNB + - Terminate_eNB + - Initialize_UE + - Terminate_UE + - Attach_UE + - Detach_UE + - Build_OAI_UE + - Initialize_OAI_UE + - Terminate_OAI_UE + - DataDisable_UE + - DataEnable_UE + - CheckStatusUE + - Ping + - Iperf + - Reboot_UE + - Initialize_FlexranCtrl + - Terminate_FlexranCtrl + - Initialize_HSS + - Terminate_HSS + - Initialize_MME + - Terminate_MME + - Initialize_SPGW + - Terminate_SPGW + - Initialize_CatM_module + - Terminate_CatM_module + - Attach_CatM_module + - Detach_CatM_module + - Ping_CatM_module + - IdleSleep + - Perform_X2_Handover diff --git a/ci-scripts/xml_files/enb_ocp_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/enb_ocp_usrp210_band7_test_05mhz_tm1.xml new file mode 100644 index 0000000000..a4caa77075 --- /dev/null +++ b/ci-scripts/xml_files/enb_ocp_usrp210_band7_test_05mhz_tm1.xml @@ -0,0 +1,147 @@ + + + test-05-tm1 + Test-05MHz-TM1 + tasks + 4 + + 030201 + 040101 + 030101 040301 040501 040603 040604 040605 040606 040607 040641 040642 040643 040644 040401 040201 030201 + + + + + Initialize_eNB + Initialize OCP-eNB (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf + ocp + + + + Terminate_eNB + Terminate OCP-eNB + ocp + + + + 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_ocp_usrp210_build.xml b/ci-scripts/xml_files/enb_ocp_usrp210_build.xml new file mode 100644 index 0000000000..33a0fc205e --- /dev/null +++ b/ci-scripts/xml_files/enb_ocp_usrp210_build.xml @@ -0,0 +1,38 @@ + + + build-tab + Build + wrench + + 010101 + + + + + Build_eNB + Build eNB OCP (USRP) + -w USRP -c --eNBocp --ninja + + + diff --git a/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_fembms_no_s1.xml b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_fembms_no_s1.xml new file mode 100644 index 0000000000..775ef2e023 --- /dev/null +++ b/ci-scripts/xml_files/enb_ue_usrp210_band7_test_05mhz_tm1_fembms_no_s1.xml @@ -0,0 +1,82 @@ + + + test-05-tm1-fembms-nos1-tunnel + Test-05MHz-FEMBMS-TM1-noS1-tunnel + tasks + 2 + + 030201 090109 + 030104 000001 090104 000002 040605 000001 090109 030201 + + + + + IdleSleep + Sleep + 10 + + + + IdleSleep + Sleep + 15 + + + + IdleSleep + Sleep + 60 + + + + Initialize_eNB + Initialize eNB (FDD/Band7/5MHz/MBMS) + -O ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf --noS1 --eNBs.[0].rrc_inactivity_threshold 0 --nokrnmod 1 --eNBs.[0].component_carriers.[0].eutra_band 7 --eNBs.[0].component_carriers.[0].downlink_frequency 2680000000 --eNBs.[0].component_carriers.[0].uplink_frequency_offset -120000000 --eNBs.[0].component_carriers.[0].mbms_dedicated_serving_cell ENABLE --MCEs.[0].mbms_sched_info.mbms_area_config_list.[0].pmch_config_list.[0].allocated_sf_end 512 + + + + Terminate_eNB + Terminate eNB + + + + Initialize_OAI_UE + Initialize OAI UE (FDD/Band7/5MHz/MBMS) + -C 2680000000 -r 25 --ue-rxgain 120 --ue-txgain 0 --ue-max-power 0 --ue-scan-carrier --nokrnmod 1 --noS1 + + + + Terminate_OAI_UE + Terminate OAI UE + + + + Iperf + iperf (5MHz - DL/1.5Mbps/UDP/MBMS-sink)(20 sec) + -c 10.0.2.2 -u -b 1.5M -t 20 -i 1 -fm -B 10.0.2.1 + 50 + sink + + + diff --git a/ci-scripts/xml_files/fr1_epc_closure.xml b/ci-scripts/xml_files/fr1_epc_closure.xml new file mode 100644 index 0000000000..2fd8031936 --- /dev/null +++ b/ci-scripts/xml_files/fr1_epc_closure.xml @@ -0,0 +1,47 @@ + + + epc-closure + EPC-Closure + log-out + +060000 060001 060002 + + + + + Terminate_HSS + Terminate HSS + + + + Terminate_MME + Terminate MME + + + + Terminate_SPGW + Terminate SPGW + + + diff --git a/ci-scripts/xml_files/fr1_epc_start.xml b/ci-scripts/xml_files/fr1_epc_start.xml new file mode 100644 index 0000000000..5cef2b5a6a --- /dev/null +++ b/ci-scripts/xml_files/fr1_epc_start.xml @@ -0,0 +1,48 @@ + + + epc-start-tab + EPC-Start + log-in + + 000100 000101 000102 + + + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + Initialize_SPGW + Initialize SPGW + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_build.xml b/ci-scripts/xml_files/fr1_multi_node_build.xml new file mode 100644 index 0000000000..7b4eacef3a --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_build.xml @@ -0,0 +1,66 @@ + + + build-tab + Build + wrench + + 000001 000002 + 000003 000004 + + + + + Build_eNB + Build eNB + -w USRP -c --eNB --ninja + 0 + 0 + True + + + + WaitEndBuild_eNB + Wait for end of Build eNB + 0 + 0 + + + + Build_eNB + Build gNB + -w USRP -c --gNB --ninja + 1 + 1 + True + + + + WaitEndBuild_eNB + Wait for end of Build gNB + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_test.xml b/ci-scripts/xml_files/fr1_multi_node_test.xml new file mode 100644 index 0000000000..8c56f0bcec --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_test.xml @@ -0,0 +1,77 @@ + + + test-fr1-tm1 + Test-FR1-TM1 + tasks + 1 + + 030000 + 040000 + 000001 + 070001 + 070000 + + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf + 0 + 0 + lte + + + + Initialize_eNB + Initialize gNB (3/4 sampling rate) + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E + 1 + 1 + nr + + + + IdleSleep + Sleep + 30 + + + + Terminate_eNB + Terminate eNB + 0 + 0 + + + + Terminate_eNB + Terminate gNB + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/fr1_ran_ue_proc.xml b/ci-scripts/xml_files/fr1_ran_ue_proc.xml new file mode 100644 index 0000000000..e86a36d2db --- /dev/null +++ b/ci-scripts/xml_files/fr1_ran_ue_proc.xml @@ -0,0 +1,117 @@ + + + TEST-FR1-TM1 + FR1 + tasks + + 010000 + 030000 + 040000 + 010001 + 000001 + 050000 + 050001 + 070001 + 070000 + 010002 + 010003 + + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf + 0 + 0 + lte + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E + 1 + 1 + nr + + + + IdleSleep + Sleep + 20 + + + + Ping + Ping: 20pings in 20sec + -c 20 + 0 + + + + Ping + Ping: 5pings in 1sec + -c 5 -i 0.2 + 0 + + + + Terminate_eNB + Terminate eNB + 0 + 0 + + + + Terminate_eNB + Terminate gNB + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index c51093c178..a344cb6a7f 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -52,7 +52,7 @@ Initialize_OAI_UE Initialize NR UE USRP - --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --threadoffset 16 --rrc_config_path . + --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 75 --threadoffset 16 --rrc_config_path . NR diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml index b4290ae6a3..9e5e0a2bac 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run_multi_thread.xml @@ -52,7 +52,7 @@ Initialize_OAI_UE Initialize NR UE USRP - --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --threadoffset 16 --rrc_config_path . + --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 75 --threadoffset 16 --rrc_config_path . NR diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index 97d6ef06f6..e2662180c5 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -34,7 +34,7 @@ TesteNB Build_eNB Build gNB (USRP) - --gNB -w USRP + --gNB -w USRP --ninja True diff --git a/ci-scripts/xml_files/nr_ue_usrp_build.xml b/ci-scripts/xml_files/nr_ue_usrp_build.xml index c3c842b85a..bc04efdb4b 100644 --- a/ci-scripts/xml_files/nr_ue_usrp_build.xml +++ b/ci-scripts/xml_files/nr_ue_usrp_build.xml @@ -34,7 +34,7 @@ TestUE Build_OAI_UE Build NR UE (USRP) - --nrUE -w USRP + --nrUE -w USRP --ninja false diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 0b60172747..0977f6c0d9 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -27,6 +27,10 @@ cmake_minimum_required (VERSION 3.0) # Base directories, compatible with legacy OAI building # ######################################################### set (OPENAIR_DIR $ENV{OPENAIR_DIR}) +if("${OPENAIR_DIR}" STREQUAL "") + string(REGEX REPLACE "/cmake_targets.*$" "" OPENAIR_DIR ${CMAKE_CURRENT_BINARY_DIR}) +endif() + set (NFAPI_DIR ${OPENAIR_DIR}/nfapi/open-nFAPI) set (NFAPI_USER_DIR ${OPENAIR_DIR}/nfapi/oai_integration) set (OPENAIR1_DIR ${OPENAIR_DIR}/openair1) @@ -759,6 +763,42 @@ 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") +# Benetel 4G library +###################################################################### + +set(HWLIB_BENETEL_4G_SOURCE + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/benetel.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/shared_buffers.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/low.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/low_dpdk.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/dpdk_driver.c + ) +add_library(benetel_4g MODULE ${HWLIB_BENETEL_4G_SOURCE} ) + +set_target_properties(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +TARGET_LINK_LIBRARIES(benetel_4g ${DPDK_LIBS}) +TARGET_LINK_LIBRARIES(benetel_4g pthread dl rt m numa) + +# Benetel 5G library +###################################################################### + +set(HWLIB_BENETEL_5G_SOURCE + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/benetel.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/shared_buffers.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/low.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/low_dpdk.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/dpdk_driver.c + ) +add_library(benetel_5g MODULE ${HWLIB_BENETEL_5G_SOURCE} ) + +set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include") + +SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive") +TARGET_LINK_LIBRARIES(benetel_5g ${DPDK_LIBS}) +TARGET_LINK_LIBRARIES(benetel_5g pthread dl rt m numa) + ########################################################## include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON") @@ -1252,7 +1292,7 @@ set(SCHED_SRC_NR_UE ${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c ${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c - ${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c + ${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_uci_ue_nr.c ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_power_control_ue_nr.c @@ -1543,11 +1583,12 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c + ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/filt16a_32.c ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c - ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c + ${OPENAIR1_DIR}/PHY/NR_ESTIMATION/nr_measurements_gNB.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c #${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c @@ -1595,6 +1636,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c + ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/filt16a_32.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -1740,9 +1782,15 @@ set(NR_RLC_SRC ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_sdu.c ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_ue_manager.c ) + +set(NR_PDCP_SRC + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c + ) set(L2_SRC - ${OPENAIR2_DIR}/LAYER2/openair2_proc.c ${PDCP_DIR}/pdcp.c ${PDCP_DIR}/pdcp_fifo.c ${PDCP_DIR}/pdcp_sequence_manager.c @@ -1750,6 +1798,7 @@ set(L2_SRC ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c + ${OPENAIR2_DIR}/LAYER2/openair2_proc.c # ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_eNB.c ${RRC_DIR}/rrc_eNB_endc.c @@ -1761,6 +1810,20 @@ set(L2_SRC ${RRC_DIR}/L2_interface_common.c ${RRC_DIR}/L2_interface_ue.c ) + +set(L2_RRC_SRC + ${OPENAIR2_DIR}/LAYER2/openair2_proc.c + # ${RRC_DIR}/rrc_UE.c + ${RRC_DIR}/rrc_eNB.c + ${RRC_DIR}/rrc_eNB_endc.c + ${RRC_DIR}/rrc_eNB_S1AP.c + ${RRC_DIR}/rrc_eNB_M2AP.c + ${RRC_DIR}/rrc_eNB_UE_context.c + ${RRC_DIR}/rrc_common.c + ${RRC_DIR}/L2_interface.c + ${RRC_DIR}/L2_interface_common.c + ${RRC_DIR}/L2_interface_ue.c + ) set(L2_LTE_SRC ${RLC_V2} @@ -1768,6 +1831,7 @@ set(L2_LTE_SRC set(L2_NR_SRC ${NR_RLC_SRC} + ${NR_PDCP_SRC} ${NR_RRC_DIR}/rrc_gNB.c ${NR_RRC_DIR}/nr_rrc_common.c ${NR_RRC_DIR}/L2_nr_interface.c @@ -1792,19 +1856,16 @@ set(L2_SRC_UE ${RRC_DIR}/L2_interface_ue.c ) -set(LTE_NR_L2_SRC_UE - ${PDCP_DIR}/pdcp.c - ${PDCP_DIR}/pdcp_fifo.c - ${PDCP_DIR}/pdcp_sequence_manager.c - ${PDCP_DIR}/pdcp_primitives.c - ${PDCP_DIR}/pdcp_util.c - ${PDCP_DIR}/pdcp_security.c - ${PDCP_DIR}/pdcp_netlink.c - ${RLC_V2} - ) - +set(L2_RRC_SRC_UE + ${RRC_DIR}/rrc_UE.c + ${RRC_DIR}/rrc_common.c + ${RRC_DIR}/L2_interface_common.c + ${RRC_DIR}/L2_interface_ue.c + ) + set(NR_L2_SRC_UE ${NR_RLC_SRC} + ${NR_PDCP_SRC} ${NR_UE_RRC_DIR}/L2_interface_ue.c ${NR_UE_RRC_DIR}/main_ue.c ${NR_UE_RRC_DIR}/rrc_UE.c @@ -1914,6 +1975,14 @@ add_library(L2_NR ${MAC_NR_SRC} ${GNB_APP_SRC} ) + +add_library(L2_LTE_NR + ${L2_RRC_SRC} + ${MAC_SRC} + ${ENB_APP_SRC} + ${MCE_APP_SRC} +) + add_dependencies(L2_NR rrc_flag nr_rrc_flag s1ap_flag x2_flag) add_library(L2_UE @@ -1921,6 +1990,11 @@ add_library(L2_UE ${MAC_SRC_UE} ) +add_library(L2_UE_LTE_NR + ${L2_RRC_SRC_UE} + ${MAC_SRC_UE} +) + if (NOT ${NOS1}) target_compile_definitions(L2_UE PUBLIC -DPDCP_USE_NETLINK) endif() @@ -2303,6 +2377,7 @@ add_library(LFDS7 add_library(SIMU_COMMON ${OPENAIR1_DIR}/SIMULATION/TOOLS/random_channel.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/rangen_double.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/phase_noise.c ) # Simulation library @@ -2474,8 +2549,8 @@ add_library(uescope MODULE ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} ${XFORMS_ target_link_libraries(enbscope ${XFORMS_LIBRARIES}) target_link_libraries(uescope ${XFORMS_LIBRARIES}) -add_library(gnbscope MODULE ${XFORMS_SOURCE_NR}) -target_link_libraries(gnbscope ${XFORMS_LIBRARIES}) +add_library(nrscope MODULE ${XFORMS_SOURCE_NR}) +target_link_libraries(nrscope ${XFORMS_LIBRARIES}) add_library(rfsimulator MODULE @@ -2624,7 +2699,7 @@ add_executable(ocp-enb ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} ) -add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer) +add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer coding params_libconfig rfsimulator) target_link_libraries (ocp-enb -Wl,--start-group @@ -2731,7 +2806,7 @@ add_executable(nr-softmodem ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${GTPU_need_ITTI} - ${XFORMS_SOURCE_NR} + ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} @@ -2741,7 +2816,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_NR_COMMON PHY_RU LFDS NR_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 MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB + S1AP_LIB S1AP_ENB L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB X2AP_LIB X2AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB} -Wl,--end-group z dl) @@ -2773,7 +2848,7 @@ add_executable(nr-uesoftmodem ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c - ${XFORMS_SOURCE_NR} + ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${UTIL_SRC} ${CONFIG_SOURCES} @@ -2783,7 +2858,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_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB + PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB S1AP_LIB S1AP_ENB ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} -Wl,--end-group z dl) @@ -2902,6 +2977,7 @@ add_executable(nr_dlschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c + ${OPENAIR_DIR}/common/utils/utils.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} @@ -2915,6 +2991,7 @@ add_executable(nr_pbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c + ${OPENAIR_DIR}/common/utils/utils.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} @@ -2930,6 +3007,7 @@ add_executable(nr_pucchsim ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/utils.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} @@ -2941,6 +3019,7 @@ target_link_libraries(nr_pucchsim add_executable(nr_dlsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlsim.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR_DIR}/executables/softmodem-common.c @@ -2956,6 +3035,7 @@ target_compile_definitions(nr_dlsim PUBLIC -DPHYSICAL_SIMULATOR) add_executable(nr_prachsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c @@ -2967,6 +3047,7 @@ target_link_libraries(nr_prachsim add_executable(nr_ulschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${UTIL_SRC} @@ -2980,6 +3061,7 @@ target_link_libraries(nr_ulschsim add_executable(nr_ulsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c + ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${OPENAIR_DIR}/executables/softmodem-common.c @@ -3000,6 +3082,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/utils.c ${XFORMS_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} @@ -3086,7 +3169,7 @@ if (${T_TRACER}) SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX - L2 L2_LTE L2_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_NR MAC_UE_NR + L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_NR MAC_UE_NR CN_UTILS GTPV1U NR_GTPV1U SCTP_CLIENT MME_APP UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB ldpc_orig ldpc_optim ldpc_optim8seg ldpc PROTO_AGENT dfts) if (TARGET ${i}) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 786002e982..7e43a9d01c 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1276,7 +1276,10 @@ (Test2: MCS 16 50 PRBs), (Test3: MCS 28 50 PRBs), (Test4: MCS 9 217 PRBs), - (Test5: MCS 9 273 PRBs) + (Test5: MCS 9 273 PRBs), + (Test6: DMRS Type A, 3 DMRS, 4 PTRS, 5 Interpolated Symbols), + (Test7: DMRS Type B, 3 DMRS, 2 PTRS, 7 Interpolated Symbols), + (Test8: DMRS Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1287,8 +1290,11 @@ -n100 -m16 -s10 -n100 -m28 -s20 -n100 -m9 -R217 -r217 -s5 - -n100 -m9 -R273 -r273 -s5 - nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 + -n100 -m9 -R273 -r273 -s5 + -n100 -s5 -T 2 1 2 -U 2 0 2 + -n100 -s5 -T 2 2 2 -U 2 1 2 + -n100 -s5 -a4 -b8 -T 2 1 2 -U 2 1 3 + nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 PUSCH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 88b8811575..f301908495 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -67,7 +67,7 @@ UE_TIMING_TRACE="False" USRP_REC_PLAY="False" BUILD_ECLIPSE=0 NR="False" -OPTIONAL_LIBRARIES="telnetsrv enbscope uescope msc" +OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope msc" trap handle_ctrl_c INT function print_help() { @@ -96,7 +96,9 @@ Options enable cmake debugging messages --eNB Makes the LTE softmodem ---gNB +--eNBocp + Makes the OCP LTE softmodem +-gNB Makes the NR softmodem --nrUE Makes the NR UE softmodem @@ -209,7 +211,7 @@ function main() { GDB=0 CMAKE_BUILD_TYPE="RelWithDebInfo" echo_info "Will Compile with gdb symbols" - CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=RelWithDebInfo" + CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_EXPORT_COMPILE_COMMANDS=1" shift ;; "MinSizeRel") @@ -237,7 +239,11 @@ function main() { eNB=1 echo_info "Will compile eNB" shift;; - --gNB) + --eNBocp) + eNBocp=1 + echo_info "Will compile OCP eNB" + shift;; + --gNB) gNB=1 NR="True" echo_info "Will compile gNB" @@ -443,7 +449,7 @@ function main() { ######################################################## # to be discussed - if [ "$eNB" = "1" -o "$gNB" = "1" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$gNB" = "1" ] ; then if [ "$HW" = "None" -a "$TP" = "None" ] ; then echo_info "No local radio head and no transport protocol selected" fi @@ -574,12 +580,13 @@ function main() { config_libconfig_shlib=params_libconfig # first generate the CMakefile in the right directory - if [ "$eNB" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HW" = "EXMIMO" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HW" = "EXMIMO" ] ; then # softmodem compilation cmake_file=$DIR/$build_dir/CMakeLists.txt echo "cmake_minimum_required(VERSION 2.8)" > $cmake_file + echo "project (OpenAirInterface)" >> $cmake_file echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file @@ -606,6 +613,9 @@ function main() { if [ "$eNB" = "1" ] ; then execlist="$execlist lte-softmodem" fi + if [ "$eNBocp" = "1" ] ; then + execlist="$execlist ocp-enb" + fi if [ "$gNB" = "1" ] ; then execlist="$execlist nr-softmodem" fi @@ -821,7 +831,7 @@ function main() { #################################################### # Build RF device and transport protocol libraries # #################################################### - if [ "$eNB" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HWLAT" = "1" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HWLAT" = "1" ] ; then # build RF device libraries if [ "$HW" != "None" ] ; then diff --git a/common/utils/T/defs.h b/common/utils/T/defs.h index 69b379ce0b..a194e621db 100644 --- a/common/utils/T/defs.h +++ b/common/utils/T/defs.h @@ -1,5 +1,5 @@ -#ifndef _TRACER_DEFS_H_ -#define _TRACER_DEFS_H_ +#ifndef _COMMON_UTILS_T_DEFS_H_ +#define _COMMON_UTILS_T_DEFS_H_ /* types of plots */ #define PLOT_VS_TIME 0 @@ -27,4 +27,4 @@ void *forwarder(char *ip, int port); void forward(void *forwarder, char *buf, int size); void forward_start_client(void *forwarder, int socket); -#endif /* _TRACER_DEFS_H_ */ +#endif /* _COMMON_UTILS_T_DEFS_H_ */ diff --git a/common/utils/T/tracer/defs.h b/common/utils/T/tracer/defs.h index 443fabdde8..394351eab0 100644 --- a/common/utils/T/tracer/defs.h +++ b/common/utils/T/tracer/defs.h @@ -1,5 +1,5 @@ -#ifndef _TRACER_DEFS_H_ -#define _TRACER_DEFS_H_ +#ifndef _COMMON_UTILS_T_TRACER_DEFS_H_ +#define _COMMON_UTILS_T_TRACER_DEFS_H_ /* types of plots */ #define PLOT_VS_TIME 0 @@ -21,4 +21,4 @@ void t_gui_start(void); void t_gui_set_input_signal(int eNB, int frame, int subframe, int antenna, int size, void *buf); -#endif /* _TRACER_DEFS_H_ */ +#endif /* _COMMON_UTILS_T_TRACER_DEFS_H_ */ diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 22933fdd5b..1680410ebb 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -80,7 +80,7 @@ task_list_t tasks[TASK_MAX]; void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size) { void *ptr = NULL; - AssertFatal ((ptr=malloc (size)) != NULL, "Memory allocation of %zu bytes failed (%d -> %d)!\n", + AssertFatal ((ptr=calloc (size, 1)) != NULL, "Memory allocation of %zu bytes failed (%d -> %d)!\n", size, origin_task_id, destination_task_id); return ptr; } diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 06a5d350c7..03f7af99bc 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -53,6 +53,7 @@ #include #include "common/utils/load_module_shlib.h" #include "common/config/config_userapi.h" +#include "common/utils/threadPool/thread-pool.h" #include "executables/softmodem-common.h" #include @@ -507,12 +508,22 @@ int process_command(char *buf) { } rt= CMDSTATUS_FOUND; - } else if (strncasecmp(cmd,"get",3) == 0 || strncasecmp(cmd,"set",3) == 0) { + } else if (strcasecmp(cmd,"get") == 0 || strcasecmp(cmd,"set") == 0) { rt= setgetvar(i,cmd[0],cmdb); } else { for (k=0 ; telnetparams.CmdParsers[i].cmd[k].cmdfunc != NULL ; k++) { if (strncasecmp(cmd, telnetparams.CmdParsers[i].cmd[k].cmdname,sizeof(telnetparams.CmdParsers[i].cmd[k].cmdname)) == 0) { - telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf); + if (telnetparams.CmdParsers[i].cmd[k].qptr != NULL) { + notifiedFIFO_elt_t *msg =newNotifiedFIFO_elt(sizeof(telnetsrv_qmsg_t),0,NULL,NULL); + telnetsrv_qmsg_t *cmddata=NotifiedFifoData(msg); + cmddata->cmdfunc=(qcmdfunc_t)telnetparams.CmdParsers[i].cmd[k].cmdfunc; + cmddata->prnt=client_printf; + cmddata->debug=telnetparams.telnetdbg; + cmddata->cmdbuff=strdup(cmdb); + pushNotifiedFIFO(telnetparams.CmdParsers[i].cmd[k].qptr, msg); + } else { + telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf); + } rt= CMDSTATUS_FOUND; } } /* for k */ @@ -673,6 +684,16 @@ void run_telnetsrv(void) { return; } +void poll_telnetcmdq(void *qid, void *arg) { + notifiedFIFO_elt_t *msg = pollNotifiedFIFO((notifiedFIFO_t *)qid); + + if (msg != NULL) { + telnetsrv_qmsg_t *msgdata=NotifiedFifoData(msg); + msgdata->cmdfunc(msgdata->cmdbuff,msgdata->debug,msgdata->prnt,arg); + free(msgdata->cmdbuff); + delNotifiedFIFO_elt(msg); + } +} /*------------------------------------------------------------------------------------------------*/ /* load the commands delivered with the telnet server * @@ -758,6 +779,7 @@ int telnetsrv_autoinit(void) { */ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd) { int i; + notifiedFIFO_t *afifo=NULL; if( modulename == NULL || var == NULL || cmd == NULL) { fprintf(stderr,"[TELNETSRV] Telnet server, add_telnetcmd: invalid parameters\n"); @@ -769,6 +791,13 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde strncpy(telnetparams.CmdParsers[i].module,modulename,sizeof(telnetparams.CmdParsers[i].module)-1); telnetparams.CmdParsers[i].cmd = cmd; telnetparams.CmdParsers[i].var = var; + if (cmd->cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) { + if (afifo == NULL) { + afifo = malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(afifo); + } + cmd->qptr = afifo; + } printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n", i,telnetparams.CmdParsers[i].module); break; @@ -797,8 +826,10 @@ int telnetsrv_checkbuildver(char *mainexec_buildversion, char **shlib_buildvers } int telnetsrv_getfarray(loader_shlibfunc_t **farray) { - *farray=malloc(sizeof(loader_shlibfunc_t)); + *farray=malloc(sizeof(loader_shlibfunc_t)*2); (*farray)[0].fname=TELNET_ADDCMD_FNAME; (*farray)[0].fptr=(int (*)(void) )add_telnetcmd; - return 1; + (*farray)[1].fname=TELNET_POLLCMDQ_FNAME; + (*farray)[1].fptr=(int (*)(void) )poll_telnetcmdq; + return ( 2); } diff --git a/common/utils/telnetsrv/telnetsrv.h b/common/utils/telnetsrv/telnetsrv.h index debb9f02ec..b66641d5c8 100644 --- a/common/utils/telnetsrv/telnetsrv.h +++ b/common/utils/telnetsrv/telnetsrv.h @@ -53,13 +53,26 @@ /* to add a set of new command to the telnet server shell */ typedef void(*telnet_printfunc_t)(const char* format, ...); typedef int(*cmdfunc_t)(char*, int, telnet_printfunc_t prnt); +typedef int(*qcmdfunc_t)(char*, int, telnet_printfunc_t prnt,void *arg); +#define TELNETSRV_CMDFLAG_PUSHINTPOOLQ (1<<0) // ask the telnet server to push the command in a thread pool queue typedef struct cmddef { char cmdname[TELNET_CMD_MAXSIZE]; char helpstr[TELNET_HELPSTR_SIZE]; cmdfunc_t cmdfunc; + unsigned int cmdflags; + void *qptr; } telnetshell_cmddef_t; +/*----------------------------------------------------------------------------*/ +/* structure used to send a command via a message queue to enable */ +/* executing a command in a thread different from the telnet server thread */ +typedef struct telnetsrv_qmsg { + qcmdfunc_t cmdfunc; + telnet_printfunc_t prnt; + int debug; + char *cmdbuff; +} telnetsrv_qmsg_t; /*----------------------------------------------------------------------------*/ /*structure to be used when adding a module to the telnet server */ /* This is the first parameter of the add_telnetcmd function, which can be used */ @@ -111,9 +124,6 @@ typedef struct { } telnetsrv_params_t; - -typedef int(*addcmdfunc_t)(char*, telnetshell_vardef_t*, telnetshell_cmddef_t*); - typedef void(*settelnetmodule_t)(char *name, void *ptr); /*-------------------------------------------------------------------------------------------*/ @@ -133,7 +143,9 @@ VT escape sequence definition, for smarter display.... /*---------------------------------------------------------------------------------------------*/ #define TELNET_ADDCMD_FNAME "add_telnetcmd" +#define TELNET_POLLCMDQ_FNAME "poll_telnetcmdq" typedef int(*add_telnetcmd_func_t)(char *, telnetshell_vardef_t *, telnetshell_cmddef_t *); +typedef void(*poll_telnetcmdq_func_t)(void *qid,void *arg); #ifdef TELNETSERVERCODE int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd); void set_sched(pthread_t tid, int pid,int priority); diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index cbb2dbe3d9..e1446f15d7 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -111,9 +111,10 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { pool->activated=true; initNotifiedFIFO(&pool->incomingFifo); char *saveptr, * curptr; + char *parms_cpy=strdup(params); pool->nbThreads=0; pool->restrictRNTI=false; - curptr=strtok_r(params,",",&saveptr); + curptr=strtok_r(parms_cpy,",",&saveptr); struct one_thread * ptr; while ( curptr!=NULL ) { int c=toupper(curptr[0]); @@ -145,7 +146,7 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { curptr=strtok_r(NULL,",",&saveptr); } - + free(parms_cpy); if (pool->activated && pool->nbThreads==0) { printf("No servers created in the thread pool, exit\n"); exit(1); diff --git a/common/utils/utils.c b/common/utils/utils.c index a807a27096..7f7aafc94a 100644 --- a/common/utils/utils.c +++ b/common/utils/utils.c @@ -105,3 +105,9 @@ char *itoa(int i) { return strdup(buffer); } +void *memcpy1(void *dst,const void *src,size_t n) { + + void *ret=dst; + asm volatile("rep movsb" : "+D" (dst) : "c"(n), "S"(src) : "cc","memory"); + return(ret); +} diff --git a/common/utils/utils.h b/common/utils/utils.h index 11db07056e..da7c453b03 100644 --- a/common/utils/utils.h +++ b/common/utils/utils.h @@ -15,6 +15,9 @@ int hex_char_to_hex_value (char c); // Converts an hexadecimal ASCII coded string into its value.** int hex_string_to_hex_value (uint8_t *hex_value, const char *hex_string, int size); +void *memcpy1(void *dst,const void *src,size_t n); + + char *itoa(int i); #define findInList(keY, result, list, element_type) {\ diff --git a/doc/BUILD.md b/doc/BUILD.md index 97f9047596..ba5db55cab 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -16,6 +16,7 @@ This page is valid on tags starting from **`2019.w09`**. # Soft Modem Build Script +The OAI EPC is developed in a distinct project with it's own [documentation](https://github.com/OPENAIRINTERFACE/openair-epc-fed/wiki) , it is not described here. OAI softmodem sources, which aim to implement 3GPP compliant UEs, eNodeB and gNodeB can be downloaded from the Eurecom [gitlab repository](./GET_SOURCES.md). @@ -33,7 +34,7 @@ The main oai binaries, which are tested by the Continuous Integration process ar Running the [build_oai](../cmake_targets/build_oai) script also generates some utilities required to build and/or run the oai softmodem binaries: -- `con2uedata`: a binary used to build the UE data from a configuration file. The created file emulates the sim card of a 3GPP compliant phone. +- `conf2uedata`: a binary used to build the UE data from a configuration file. The created file emulates the sim card of a 3GPP compliant phone. - `nvram`: a binary used to build UE (IMEI...) and EMM (IMSI, registered PLMN) non volatile data. - `rb_tool`: radio bearer utility - `genids` T Tracer utility, used at build time to generate T_IDs.h include file. This binary is located in the [T Tracer source file directory](../common/utils/T) . diff --git a/doc/GET_SOURCES.md b/doc/GET_SOURCES.md index e27e9dbb74..854ff3b504 100644 --- a/doc/GET_SOURCES.md +++ b/doc/GET_SOURCES.md @@ -33,12 +33,8 @@ holds the source code for (eNB RAN + UE RAN). For legal issues (licenses), the core network (EPC) source code is now moved away from the above openairinterface5g git repository. -* A very old version of the EPC is located under the same GitLab Eurecom server (splitted into 2 Git repos): - * [openair-cn](https://gitlab.eurecom.fr/oai/openair-cn.git) with apache license - * [xtables-addons-oai](https://gitlab.eurecom.fr/oai/xtables-addons-oai.git) with GPL license - * **These repositories are no more maintained.** * A more recent version is available under our GitHub domain: - * [OAI GitHub openair-cn](https://github.com/OPENAIRINTERFACE/openair-cn) + * [OAI GitHub openair-cn domain](https://github.com/OPENAIRINTERFACE) * Check its wiki pages for more details Configure git with your name/email address (only important if you are developer and want to contribute/push code to Git Repository): @@ -80,8 +76,6 @@ you do not have account on gitlab.eurecom.fr, please register yourself to gitlab * `git clone git@gitlab.eurecom.fr:oai/openairinterface5g.git` * Clone with user name/password prompt: * `git clone https://YOUR_USERNAME@gitlab.eurecom.fr/oai/openairinterface5g.git` - * `git clone https://YOUR_USERNAME@gitlab.eurecom.fr/oai/openair-cn.git` - * `git clone https://YOUR_USERNAME@gitlab.eurecom.fr/oai/xtables-addons-oai.git` (optional, openair-cn build script can do it for you) # Which branch to checkout? diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md new file mode 100644 index 0000000000..7365bc0f4c --- /dev/null +++ b/doc/TESTBenches.md @@ -0,0 +1,45 @@ +## Table of Contents ## + +1. [Legacy 1 Bench](#legacy-1-bench) +2. [Legacy 2 Bench](#legacy-2-bench) +3. [Next Bench for DEV](#next-bench-for-dev) +4. [Next Bench for CI](#next-bench-for-ci) +5. [Indoor Live Network Bench](#indoor-live-network-bench) +6. [Outdoor Live Network Bench](#outdoor-live-network-bench) + + +## Legacy 1 Bench + +**Purpose** : FDD Band 7 and Band 13, LTE-M +**Note** : Legacy1 and Legacy2 are duplicated so that they can run in parallel, thus avoiding a CI bottleneck +**Note** : Faraday Cages 1 and 2 are physically the same cage + +![image info](./testbenches_doc_resources/legacy1.jpg) + +## Legacy 2 Bench + +**Purpose** : TDD Band 40, TM2 2xTX 2xRX +**Note** : CN can run in a container, could also run on Massive + +![image info](./testbenches_doc_resources/legacy2.jpg) + +## Next Bench for DEV + +**Note** : Benetel CI can also run on this bench at night + +![image info](./testbenches_doc_resources/next_dev.jpg) + + +## Next Bench for CI + +**Note** : The current test running on Caracal could run on this bench with a N300/N300 setup + +![image info](./testbenches_doc_resources/next_ci.jpg) + +## Indoor Live Network Bench + +![image info](./testbenches_doc_resources/indoor_live.jpg) + +## Outdoor Live Network Bench + +![image info](./testbenches_doc_resources/outdoor_live.jpg) diff --git a/doc/TESTING_GNB_W_COTS_UE.md b/doc/TESTING_GNB_W_COTS_UE.md index e507050239..17f37ad2d7 100644 --- a/doc/TESTING_GNB_W_COTS_UE.md +++ b/doc/TESTING_GNB_W_COTS_UE.md @@ -1,4 +1,5 @@ -STATUS 2020/06/26 : information is up to date, but under continuous improvement +STATUS 2020/09/10 : updated the status of interop (end to end UL/DL traffic) + ## Table of Contents ## @@ -11,6 +12,7 @@ STATUS 2020/06/26 : information is up to date, but under continuous improvement 7. [Log file monitoring](#log-file-monitoring) 6. [Required tools for debug](#required-tools-for-debug) 7. [Status of interoperability](#status-of-interoperability) +8. [CI integration](#ci-integration) ## Configuration Overview @@ -69,7 +71,7 @@ cd cmake_targets/ - **EPC** for reference: -https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master-documentation/docs/DEPLOY_HOME.md +https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME.md @@ -78,17 +80,17 @@ https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master-documentation/do Each component (EPC, eNB, gNB) has its own configuration file. These config files are passed as arguments of the run command line, using the option -O \ -Some config examples can be found in the following folder: -https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/develop/targets/PROJECTS/GENERIC-LTE-EPC/CONF - -Also base config files can be found here: -[enb conf file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/enb.conf) -[gnb conf file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/gnb.conf) - -TO DO : attach base confif files +The **REFERENCE** files for eNB and gNB, **used by the CI**, can be found here: +[enb conf file](../ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf) +[gnb conf file](../ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf) These files have to be updated manually to set the IP addresses and frequency. + +**ATTENTION** : an **EXTERNAL** clock is used to sync the eNB and gNB, +whether the clock is internal or external is defined in the configuration files (!! details needed !!) + + 1- In the **eNB configuration file** : - look for MME IP address, and update the **ipv4 field** with the IP address of the **EPC** server ``` @@ -128,7 +130,7 @@ These files have to be updated manually to set the IP addresses and frequency. } ); ``` -- look for X2 IP address, and update the **4 fields** with the IP address of the **eNB** server (notice : even if -in principle- S1 MME is not required for gNB setting) +- look for X2 IP address, and update the **4 fields** with the IP address of the **eNB** server / **gNB** server as below (notice : even if -in principle- S1 MME is not required for gNB setting) ``` ///X2 @@ -146,11 +148,11 @@ These files have to be updated manually to set the IP addresses and frequency. { GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "**YOUR_ENB_IP_ADDR**"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "**YOUR_GNB_IP_ADDR**"; GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "**YOUR_ENB_IP_ADDR**"; + GNB_IPV4_ADDRESS_FOR_S1U = "**YOUR_GNB_IP_ADDR**"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 - GNB_IPV4_ADDRESS_FOR_X2C = "**YOUR_ENB_IP_ADDR**"; + GNB_IPV4_ADDRESS_FOR_X2C = "**YOUR_GNB_IP_ADDR**"; GNB_PORT_FOR_X2C = 36422; # Spec 36422 }; @@ -193,7 +195,7 @@ The order to run the different components is important: 1- first, CN 2- then, eNB 3- then, gNB -4- finally, switch UE from airplane mode OFF to ON +4- finally, switch UE from airplane mode ON to OFF (ie Radio from OFF to ON) It is recommended to redirect the run commands to the same log file (fur further analysis and debug), using ```| tee **YOUR_LOG_FILE**``` especially for eNB and gNB. It is not very useful for the CN. @@ -203,7 +205,7 @@ The test takes typically a few seconds, max 10-15 seconds. If it takes more than - **EPC** (on EPC host): for reference: -https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master-documentation/docs/DEPLOY_HOME.md +https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME.md @@ -215,27 +217,20 @@ Execute: ``` -For example: -``` -~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf | tee mylogfile.log -``` - - - **gNB** (on the gNB host) +**ATTENTION** : for the gNB execution, +The **-E** option is required to enable the tri-quarter sampling rate when using a B2xx serie USRP +The **-E** option is **NOT supported** when using a a N300 USRP + Execute: ``` -~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** | tee **YOUR_LOG_FILE** +~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** -E | tee **YOUR_LOG_FILE** ``` -For example: -``` -~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf | tee mylogfile.log -``` - ## Test Case @@ -382,13 +377,24 @@ The following parts have been validated with FR1 COTS UE: PDCCH DCI format 1_1 and correponding PDSCH are decoded correctlyby the phone ACK/NACK (PUCCH format 0) are successfully received at gNB -- On going: - validation of HARQ procedures - Integration with higher layers to replace dummy data with real traffic +- **End-to end UL / DL traffic with HARQ procedures validated (ping, iperf)** -- Known limitations as of May 2020: - only dummy DL traffic - no UL traffic - no end-to-end traffic possible +- Known limitations as of September 2020: + DL traffic : 3Mbps + UL traffic : 1Mbps + some packet losses might still occur even in ideal channel conditions +## CI integration +The automation scripts are available on ILIADE. +The end-to-end test is integrated in the CI flow in a semi-automated manner, comprising 3 steps: +- update a YAML file comprising the IT resources definition, branch and commit number the test has to run on +- run the python script that generates the test from the YAML file +``` +python3 obj_build_from_yaml.py py_params_template.yaml fr1.sh +``` +- run the test (fr1.sh) + +At the date of writing, the test comprises the deployment of the components (epc, eNB, gNB, cots ue) and the execution of 2 pings procedures (20 pings in 20sec, then 5 pings in 1sec) + +This automation is run for every integration branch to be merged into develop. diff --git a/doc/testbenches_doc_resources/benches.vsdx b/doc/testbenches_doc_resources/benches.vsdx new file mode 100755 index 0000000000..6ad3a5b576 Binary files /dev/null and b/doc/testbenches_doc_resources/benches.vsdx differ diff --git a/doc/testbenches_doc_resources/indoor_live.jpg b/doc/testbenches_doc_resources/indoor_live.jpg new file mode 100755 index 0000000000..ce8b9cda48 Binary files /dev/null and b/doc/testbenches_doc_resources/indoor_live.jpg differ diff --git a/doc/testbenches_doc_resources/legacy1.jpg b/doc/testbenches_doc_resources/legacy1.jpg new file mode 100755 index 0000000000..c3579df3e4 Binary files /dev/null and b/doc/testbenches_doc_resources/legacy1.jpg differ diff --git a/doc/testbenches_doc_resources/legacy2.jpg b/doc/testbenches_doc_resources/legacy2.jpg new file mode 100755 index 0000000000..f40d167a2d Binary files /dev/null and b/doc/testbenches_doc_resources/legacy2.jpg differ diff --git a/doc/testbenches_doc_resources/next_ci.jpg b/doc/testbenches_doc_resources/next_ci.jpg new file mode 100755 index 0000000000..2d4111510c Binary files /dev/null and b/doc/testbenches_doc_resources/next_ci.jpg differ diff --git a/doc/testbenches_doc_resources/next_dev.jpg b/doc/testbenches_doc_resources/next_dev.jpg new file mode 100755 index 0000000000..72e9f63bf9 Binary files /dev/null and b/doc/testbenches_doc_resources/next_dev.jpg differ diff --git a/doc/testbenches_doc_resources/outdoor_live.jpg b/doc/testbenches_doc_resources/outdoor_live.jpg new file mode 100755 index 0000000000..eba44a3c00 Binary files /dev/null and b/doc/testbenches_doc_resources/outdoor_live.jpg differ diff --git a/docker/Dockerfile.enb.rhel7.oc4-4 b/docker/Dockerfile.enb.rhel7.oc4-4 new file mode 100644 index 0000000000..12d9a19640 --- /dev/null +++ b/docker/Dockerfile.enb.rhel7.oc4-4 @@ -0,0 +1,92 @@ +#/* +# * 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 +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface eNB service +# Valid for RHEL7 in the OpenShift context (v4.4) +# +#--------------------------------------------------------------------- + + +ARG REGISTRY=localhost +FROM $REGISTRY/oai-build-base:latest.el7 AS builder + +ARG GIT_TAG=v1.1.1 + +WORKDIR /root + +RUN if [ "$EURECOM_PROXY" == true ]; then git config --global http.proxy http://:@proxy.eurecom.fr:8080; fi + +RUN git clone --depth=1 --branch=$GIT_TAG https://gitlab.eurecom.fr/oai/openairinterface5g.git +COPY patches patches/ +RUN patch -p1 -d openairinterface5g < patches/disable_building_nasmesh_and_rbtool.patch \ + && patch -p1 -d openairinterface5g < patches/disable_sched_fifo_fail_exits.patch +RUN cd openairinterface5g/cmake_targets \ + && ln -sf /usr/local/bin/asn1c_oai /usr/local/bin/asn1c \ + && ln -sf /usr/local/share/asn1c_oai /usr/local/share/asn1c \ + && ./build_oai -c --eNB -w USRP --verbose-compile + + +FROM registry.redhat.io/ubi7/ubi +LABEL name="oai-enb" \ + version="$GIT_TAG" \ + maintainer="Frank A. Zdarsky " \ + io.k8s.description="openairinterface5g eNB $GIT_TAG." \ + io.openshift.tags="oai,enb" \ + io.openshift.non-scalable="true" + +RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ + && REPOLIST="rhel-7-server-optional-rpms" \ + && PKGLIST="boost libconfig lksctp-tools protobuf-c iproute iputils procps-ng bind-utils xforms nettle libyaml libusb" \ + # && yum -y upgrade-minimal --setopt=tsflags=nodocs --security --sec-severity=Critical --sec-severity=Important && \ + && yum -y install --enablerepo ${REPOLIST} --setopt=tsflag=nodocs ${PKGLIST} \ + && yum -y clean all \ + && rm -rf /var/cache/yum + +ENV APP_ROOT=/opt/oai-enb +ENV PATH=${APP_ROOT}:${PATH} HOME=${APP_ROOT} +COPY --from=builder /root/openairinterface5g/cmake_targets/lte_build_oai/build/lte-softmodem ${APP_ROOT}/bin/ +COPY --from=builder /root/openairinterface5g/cmake_targets/lte_build_oai/build/*.so* /lib64 +COPY --from=builder /usr/local/lib64 /lib64 +COPY --from=builder /usr/local/bin/uhd_* /usr/local/bin +COPY --from=builder /usr/local/share/uhd /usr/local/share/uhd +RUN cd /lib64 \ + && ln -sf liboai_eth_transpro.so liboai_transpro.so \ + && ln -sf liboai_usrpdevif.so liboai_device.so \ + && ln -sf libuhd.so.3.13 libuhd.so.3 \ + && ln -sf libuhd.so.3 libuhd.so +COPY scripts ${APP_ROOT}/bin/ +COPY configs ${APP_ROOT}/etc/ +RUN chmod -R u+x ${APP_ROOT} && \ + chgrp -R 0 ${APP_ROOT} && \ + chmod -R g=u ${APP_ROOT} /etc/passwd +USER 10001 +WORKDIR ${APP_ROOT} + +EXPOSE 2152/udp # S1U, GTP/UDP +EXPOSE 22100/tcp # ? +EXPOSE 36412/udp # S1C, SCTP/UDP +EXPOSE 36422/udp # X2C, SCTP/UDP +EXPOSE 50000/udp # IF5 / ORI (control) +EXPOSE 50001/udp # IF5 / ECPRI (data) + +CMD ["/opt/oai-enb/bin/lte-softmodem", "-O", "/opt/oai-enb/etc/enb.conf"] +ENTRYPOINT ["/opt/oai-enb/bin/entrypoint.sh"] diff --git a/executables/main-fs6.c b/executables/main-fs6.c index ffa44bd978..c4a0d85b34 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -401,7 +401,7 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ hULUE(newUDPheader)->O_ACK=eNB->ulsch[UE_id]->harq_processes[harq_pid]->O_ACK; memcpy(hULUE(newUDPheader)->o_ACK, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK, sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK)); - hULUE(newUDPheader)->ta=lte_est_timing_advance_pusch(eNB, UE_id); + hULUE(newUDPheader)->ta=lte_est_timing_advance_pusch(&eNB->frame_parms, eNB->pusch_vars[UE_id]->drs_ch_estimates_time); hULUE(newUDPheader)->segment=segmentID; memcpy(hULUE(newUDPheader)->o, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o, sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o)); @@ -917,7 +917,7 @@ void phy_procedures_eNB_TX_fromsplit(uint8_t *bufferZone, int nbBlocks, PHY_VARS if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { if (is_pmch_subframe(frame,subframe,fp)) { - pmch_procedures(eNB,proc); + pmch_procedures(eNB,proc,0); } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH common_signal_procedures(eNB,frame, subframe); diff --git a/executables/main-ocp.c b/executables/main-ocp.c index e4e42b4f23..cd221b155a 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -1123,9 +1123,6 @@ int restart_L1L2(module_id_t enb_id) { sync_var = -1; pthread_mutex_unlock(&sync_mutex); RC.ru_mask |= (1 << ru->idx); - /* copy the changed frame parameters to the RU */ - /* TODO this should be done for all RUs associated to this eNB */ - memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS)); /* reset the list of connected UEs in the MAC, since in this process with * loose all UEs (have to reconnect) */ init_UE_info(&RC.mac[enb_id]->UE_info); @@ -1167,6 +1164,7 @@ int main ( int argc, char **argv ) { T_Config_Init(); #endif configure_linux(); + set_softmodem_sighandler(); cpuf=get_cpu_freq_GHz(); set_taus_seed (0); @@ -1347,7 +1345,7 @@ int main ( int argc, char **argv ) { // end of CI modifications //getchar(); if(IS_SOFTMODEM_DOFORMS) - load_softscope("enb"); + load_softscope("enb", NULL); itti_wait_tasks_end(); oai_exit=1; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index ca484a0443..ede6ff2458 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -180,6 +180,17 @@ int attach_rru(RU_t *ru) ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), "RU %d failed send configuration to remote radio\n",ru->idx); + + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + msg_len))<0) { + LOG_I(PHY,"Waiting for RRU %d\n",ru->idx); + } else if (rru_config_msg.type == RRU_config_ok) { + LOG_I(PHY, "RRU_config_ok received\n"); + } else { + LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); + } + return 0; } @@ -1442,6 +1453,8 @@ void *ru_thread( void *param ) { LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); + memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); + if(emulate_rf) { fill_rf_config(ru,ru->rf_config_file); nr_init_frame_parms(&ru->config, fp); @@ -1464,8 +1477,6 @@ void *ru_thread( void *param ) { AssertFatal(ret==0,"Cannot connect to remote radio\n"); } - memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); - if (ru->if_south == LOCAL_RF) { // configure RF parameters only nr_init_frame_parms(&ru->config, fp); nr_dump_frame_parms(fp); @@ -1571,7 +1582,8 @@ void *ru_thread( void *param ) { if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { //if (proc->tti_rx==8) { - if (ru->feprx) ru->feprx(ru,proc->tti_rx); + if (ru->feprx) { + ru->feprx(ru,proc->tti_rx); //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); @@ -1614,6 +1626,7 @@ void *ru_thread( void *param ) { } free_nr_ru_prach_entry(ru,prach_id); } + } } // At this point, all information for subframe has been received on FH interface @@ -2154,26 +2167,29 @@ void set_function_spec_param(RU_t *ru) { ru->fh_north_out = NULL; // no outgoing fronthaul to north ru->nr_start_if = NULL; // no if interface ru->rfdevice.host_type = RAU_HOST; + + // FK this here looks messed up. The following lines should be part of the if (ru->function == gNodeB_3GPP), shouldn't they? + + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->start_write_thread = start_write_thread; // starting RF TX in different thread + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); } - ru->fh_south_in = rx_rf; // local synchronous RF RX - ru->fh_south_out = tx_rf; // local synchronous RF TX - ru->start_rf = start_rf; // need to start the local RF interface - ru->stop_rf = stop_rf; - ru->start_write_thread = start_write_thread; // starting RF TX in different thread - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); /* - if (ru->function == gNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise - fill_rf_config(ru,rf_config_file); - init_frame_parms(&ru->frame_parms,1); - nr_phy_init_RU(ru); - } + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + fill_rf_config(ru,rf_config_file); + init_frame_parms(&ru->frame_parms,1); + nr_phy_init_RU(ru); - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - }*/ + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + */ break; case REMOTE_IF5: // the remote unit is IF5 RRU @@ -2226,6 +2242,15 @@ void set_function_spec_param(RU_t *ru) { exit(-1); } + if (ru->ifdevice.get_internal_parameter != NULL) { + void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); + if (t != NULL) + ru->fh_south_in = t; + t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); + if (t != NULL) + ru->fh_south_out = t; + } + malloc_IF4p5_buffer(ru); break; diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index bf77125975..a3d0b325d6 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -75,7 +75,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "system.h" #include - +#include "PHY/TOOLS/phy_scope_interface.h" #include "PHY/TOOLS/nr_phy_scope.h" #include "stats.h" #include "nr-softmodem.h" @@ -84,9 +84,6 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "NB_IoT_interface.h" #include "x2ap_eNB.h" -short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT] = {0,0,16384,16384,-16384,-16384,16384,16384,16384,-16384,-16384,16384,-16384,-16384,7327,7327,7327,21981,21981,7327,21981,21981,7327,-7327,7327,-21981,21981,-7327,21981,-21981,-7327,7327,-7327,21981,-21981,7327,-21981,21981,-7327,-7327,-7327,-21981,-21981,-7327,-21981,-21981,10726,10726,10726,3576,3576,10726,3576,3576,10726,17876,10726,25027,3576,17876,3576,25027,17876,10726,17876,3576,25027,10726,25027,3576,17876,17876,17876,25027,25027,17876,25027,25027,10726,-10726,10726,-3576,3576,-10726,3576,-3576,10726,-17876,10726,-25027,3576,-17876,3576,-25027,17876,-10726,17876,-3576,25027,-10726,25027,-3576,17876,-17876,17876,-25027,25027,-17876,25027,-25027,-10726,10726,-10726,3576,-3576,10726,-3576,3576,-10726,17876,-10726,25027,-3576,17876,-3576,25027,-17876,10726,-17876,3576,-25027,10726,-25027,3576,-17876,17876,-17876,25027,-25027,17876,-25027,25027,-10726,-10726,-10726,-3576,-3576,-10726,-3576,-3576,-10726,-17876,-10726,-25027,-3576,-17876,-3576,-25027,-17876,-10726,-17876,-3576,-25027,-10726,-25027,-3576,-17876,-17876,-17876,-25027,-25027,-17876,-25027,-25027,8886,8886,8886,12439,12439,8886,12439,12439,8886,5332,8886,1778,12439,5332,12439,1778,5332,8886,5332,12439,1778,8886,1778,12439,5332,5332,5332,1778,1778,5332,1778,1778,8886,19547,8886,15993,12439,19547,12439,15993,8886,23101,8886,26655,12439,23101,12439,26655,5332,19547,5332,15993,1778,19547,1778,15993,5332,23101,5332,26655,1778,23101,1778,26655,19547,8886,19547,12439,15993,8886,15993,12439,19547,5332,19547,1778,15993,5332,15993,1778,23101,8886,23101,12439,26655,8886,26655,12439,23101,5332,23101,1778,26655,5332,26655,1778,19547,19547,19547,15993,15993,19547,15993,15993,19547,23101,19547,26655,15993,23101,15993,26655,23101,19547,23101,15993,26655,19547,26655,15993,23101,23101,23101,26655,26655,23101,26655,26655,8886,-8886,8886,-12439,12439,-8886,12439,-12439,8886,-5332,8886,-1778,12439,-5332,12439,-1778,5332,-8886,5332,-12439,1778,-8886,1778,-12439,5332,-5332,5332,-1778,1778,-5332,1778,-1778,8886,-19547,8886,-15993,12439,-19547,12439,-15993,8886,-23101,8886,-26655,12439,-23101,12439,-26655,5332,-19547,5332,-15993,1778,-19547,1778,-15993,5332,-23101,5332,-26655,1778,-23101,1778,-26655,19547,-8886,19547,-12439,15993,-8886,15993,-12439,19547,-5332,19547,-1778,15993,-5332,15993,-1778,23101,-8886,23101,-12439,26655,-8886,26655,-12439,23101,-5332,23101,-1778,26655,-5332,26655,-1778,19547,-19547,19547,-15993,15993,-19547,15993,-15993,19547,-23101,19547,-26655,15993,-23101,15993,-26655,23101,-19547,23101,-15993,26655,-19547,26655,-15993,23101,-23101,23101,-26655,26655,-23101,26655,-26655,-8886,8886,-8886,12439,-12439,8886,-12439,12439,-8886,5332,-8886,1778,-12439,5332,-12439,1778,-5332,8886,-5332,12439,-1778,8886,-1778,12439,-5332,5332,-5332,1778,-1778,5332,-1778,1778,-8886,19547,-8886,15993,-12439,19547,-12439,15993,-8886,23101,-8886,26655,-12439,23101,-12439,26655,-5332,19547,-5332,15993,-1778,19547,-1778,15993,-5332,23101,-5332,26655,-1778,23101,-1778,26655,-19547,8886,-19547,12439,-15993,8886,-15993,12439,-19547,5332,-19547,1778,-15993,5332,-15993,1778,-23101,8886,-23101,12439,-26655,8886,-26655,12439,-23101,5332,-23101,1778,-26655,5332,-26655,1778,-19547,19547,-19547,15993,-15993,19547,-15993,15993,-19547,23101,-19547,26655,-15993,23101,-15993,26655,-23101,19547,-23101,15993,-26655,19547,-26655,15993,-23101,23101,-23101,26655,-26655,23101,-26655,26655,-8886,-8886,-8886,-12439,-12439,-8886,-12439,-12439,-8886,-5332,-8886,-1778,-12439,-5332,-12439,-1778,-5332,-8886,-5332,-12439,-1778,-8886,-1778,-12439,-5332,-5332,-5332,-1778,-1778,-5332,-1778,-1778,-8886,-19547,-8886,-15993,-12439,-19547,-12439,-15993,-8886,-23101,-8886,-26655,-12439,-23101,-12439,-26655,-5332,-19547,-5332,-15993,-1778,-19547,-1778,-15993,-5332,-23101,-5332,-26655,-1778,-23101,-1778,-26655,-19547,-8886,-19547,-12439,-15993,-8886,-15993,-12439,-19547,-5332,-19547,-1778,-15993,-5332,-15993,-1778,-23101,-8886,-23101,-12439,-26655,-8886,-26655,-12439,-23101,-5332,-23101,-1778,-26655,-5332,-26655,-1778,-19547,-19547,-19547,-15993,-15993,-19547,-15993,-15993,-19547,-23101,-19547,-26655,-15993,-23101,-15993,-26655,-23101,-19547,-23101,-15993,-26655,-19547,-26655,-15993,-23101,-23101,-23101,-26655,-26655,-23101,-26655,-26655}; - - pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex @@ -156,7 +153,6 @@ char channels[128] = "0"; int rx_input_level_dBm; -uint32_t do_forms=0; int otg_enabled; //int number_of_cards = 1; @@ -454,7 +450,11 @@ static void get_options(void) { paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ; + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(SOFTMODEM_GNB_BIT ); config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + @@ -723,9 +723,6 @@ int restart_L1L2(module_id_t gnb_id) { RC.ru_mask |= (1 << ru->idx); - /* copy the changed frame parameters to the RU */ - /* TODO this should be done for all RUs associated to this gNB */ - memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id]->frame_parms, sizeof(NR_DL_FRAME_PARMS)); set_function_spec_param(RC.ru[gnb_id]); LOG_I(GNB_APP, "attempting to create ITTI tasks\n"); // No more rrc thread, as many race conditions are hidden behind @@ -817,7 +814,6 @@ int main( int argc, char **argv ) configure_linux(); printf("Reading in command-line options\n"); get_options (); - get_common_options(SOFTMODEM_GNB_BIT ); if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { fprintf(stderr,"Getting configuration failed\n"); @@ -959,14 +955,14 @@ if(!IS_SOFTMODEM_NOS1) printf("RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) printf("ALL RUs ready - init gNBs\n"); - - if (do_forms==1) { + if(IS_SOFTMODEM_DOFORMS) { + scopeParms_t p; p.argc=&argc; p.argv=argv; p.gNB=RC.gNB[0]; p.ru=RC.ru[0]; - gNBinitScope(&p); + load_softscope("nr",&p); } if (nfapi_mode != 1 && nfapi_mode != 2) { diff --git a/executables/nr-softmodem.h b/executables/nr-softmodem.h index d113ae45aa..d6cfe6b906 100644 --- a/executables/nr-softmodem.h +++ b/executables/nr-softmodem.h @@ -19,21 +19,12 @@ /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_PARAMS_DESC_GNB { \ {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ - {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&wait_for_sync, defintval:0, TYPE_INT, 0}, \ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT64, 0}, \ - {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ - {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \ {"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \ {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ - {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, 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}, \ {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \ {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ } diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 2f99027b75..1600d8add0 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -35,9 +35,7 @@ #include "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/phy_frame_config_nr.h" #include "SCHED_NR_UE/defs.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -123,7 +121,7 @@ extern double cpuf; #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 */ + #define DURATION_RX_TO_TX (6) /* 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 @@ -366,8 +364,6 @@ static void UE_synch(void *arg) { } void processSlotTX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { - - fapi_nr_config_request_t *cfg = &UE->nrUE_config; int tx_slot_type = nr_ue_slot_select(cfg, proc->frame_tx, proc->nr_tti_tx); uint8_t gNB_id = 0; @@ -475,21 +471,22 @@ void UE_processing(void *arg) { UE_nr_rxtx_proc_t *proc = &rxtxD->proc; PHY_VARS_NR_UE *UE = rxtxD->UE; - uint8_t gNB_id = 0; - - // params for UL time alignment procedure - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &UE->ul_time_alignment[gNB_id]; - uint8_t numerology = UE->frame_parms.numerology_index; - uint16_t bwp_ul_NB_RB = UE->frame_parms.N_RB_UL; - int slot_tx = proc->nr_tti_tx; - int frame_tx = proc->frame_tx; + processSlotRX(UE, proc); + processSlotTX(UE, proc); /* UL time alignment // If the current tx frame and slot match the TA configuration in ul_time_alignment // then timing advance is processed and set to be applied in the next UL transmission */ if (UE->mac_enabled == 1) { + uint8_t gNB_id = 0; + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &UE->ul_time_alignment[gNB_id]; + int slot_tx = proc->nr_tti_tx; + int frame_tx = proc->frame_tx; if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { + uint8_t numerology = UE->frame_parms.numerology_index; + uint16_t bwp_ul_NB_RB = UE->frame_parms.N_RB_UL; + LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx); //if (nfapi_mode!=3){ @@ -499,9 +496,6 @@ void UE_processing(void *arg) { //} } } - - processSlotRX(UE, proc); - processSlotTX(UE, proc); } void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) { @@ -577,12 +571,6 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { int computeSamplesShift(PHY_VARS_NR_UE *UE) { - if (IS_SOFTMODEM_RFSIM) { - LOG_D(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 < UE->frame_parms.samples_per_frame/2 && UE->rx_offset > 0 ) { @@ -632,6 +620,7 @@ void *UE_thread(void *arg) { notifiedFIFO_t freeBlocks; initNotifiedFIFO_nothreadSafe(&freeBlocks); NR_UE_MAC_INST_t *mac = get_mac_inst(0); + int timing_advance = UE->timing_advance; for (int i=0; iframe_parms.nb_antennas_tx; i++) txp[i] = (void *)&UE->common_vars.txdata[i][UE->frame_parms.get_samples_slot_timestamp( - ((curMsg->proc.nr_tti_rx + DURATION_RX_TO_TX)%nb_slot_frame),&UE->frame_parms,0)]; + ((slot_nr + DURATION_RX_TO_TX - RX_NB_TH)%nb_slot_frame),&UE->frame_parms,0)]; int readBlockSize, writeBlockSize; if (slot_nr<(nb_slot_frame - 1)) { readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms); - writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms); + writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms); } else { UE->rx_offset_diff = computeSamplesShift(UE); readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) - UE->rx_offset_diff; - writeBlockSize=UE->frame_parms.get_samples_per_slot(curMsg->proc.nr_tti_tx,&UE->frame_parms) - + writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff; } + if (UE->timing_advance != timing_advance) { + writeBlockSize -= UE->timing_advance - timing_advance; + timing_advance = UE->timing_advance; + } + AssertFatal(readBlockSize == UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, @@ -758,29 +752,19 @@ void *UE_thread(void *arg) { readBlockSize, UE->frame_parms.nb_antennas_rx),""); - AssertFatal( writeBlockSize == - UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+ - UE->frame_parms.get_samples_slot_timestamp(slot_nr, - &UE->frame_parms,DURATION_RX_TO_TX) - firstSymSamp - - 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=UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0; // first symbol of every frames - if ( first_symbols > 0 ) + if ( first_symbols > 0 ) { + openair0_timestamp ignore_timestamp; AssertFatal(first_symbols == UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, + &ignore_timestamp, (void **)UE->common_vars.rxdata, first_symbols, UE->frame_parms.nb_antennas_rx),""); - else + } else LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols); } @@ -791,18 +775,15 @@ void *UE_thread(void *arg) { notifiedFIFO_elt_t *res; while (nbSlotProcessing >= RX_NB_TH) { - if ( (res=tryPullTpool(&nf, Tpool)) != NULL ) { - nbSlotProcessing--; - processingData_t *tmp=(processingData_t *)res->msgData; + res=pullTpool(&nf, Tpool); + nbSlotProcessing--; + processingData_t *tmp=(processingData_t *)res->msgData; - if (tmp->proc.decoded_frame_rx != -1) - decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); - //decoded_frame_rx=tmp->proc.decoded_frame_rx; + if (tmp->proc.decoded_frame_rx != -1) + decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); + //decoded_frame_rx=tmp->proc.decoded_frame_rx; - pushNotifiedFIFO_nothreadSafe(&freeBlocks,res); - } - - usleep(200); + pushNotifiedFIFO_nothreadSafe(&freeBlocks,res); } if ( (decoded_frame_rx != curMsg->proc.frame_rx) && @@ -811,6 +792,20 @@ void *UE_thread(void *arg) { LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n", decoded_frame_rx, curMsg->proc.frame_rx ); + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+ + UE->frame_parms.get_samples_slot_timestamp(slot_nr, + &UE->frame_parms,DURATION_RX_TO_TX - RX_NB_TH) - firstSymSamp - + openair0_cfg[0].tx_sample_advance - UE->N_TA_offset - UE->timing_advance, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + 1),""); + + for (int i=0; iframe_parms.nb_antennas_tx; i++) + memset(txp[i], 0, writeBlockSize); + nbSlotProcessing++; msgToPush->key=slot_nr; pushTpool(Tpool, msgToPush); @@ -829,6 +824,7 @@ void *UE_thread(void *arg) { pushNotifiedFIFO_nothreadSafe(&freeBlocks,res); } + } // while !oai_exit return NULL; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6d3bbc9038..e6d644453c 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -38,13 +38,12 @@ #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 "openair1/PHY/MODULATION/nr_modulation.h" #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 "PHY/NR_REFSIG/nr_mod_table.h" #include "LAYER2/MAC/mac_vars.h" #include "RRC/LTE/rrc_vars.h" @@ -76,12 +75,12 @@ unsigned short config_frames[4] = {2,9,11,13}; #include #include +/* Callbacks, globals and object handlers */ + //#include "stats.h" // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) +#include "PHY/TOOLS/phy_scope_interface.h" #include "PHY/TOOLS/nr_phy_scope.h" -// at eNB 0, an UL scope for every UE -//FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - #include #include "executables/softmodem-common.h" #include "executables/thread-common.h" @@ -151,14 +150,11 @@ char ref[128] = "internal"; char channels[128] = "0"; -static char *parallel_config = NULL; -static char *worker_config = NULL; - int rx_input_level_dBm; //static int online_log_messages=0; -uint32_t do_forms=0; + int otg_enabled; //int number_of_cards = 1; @@ -588,7 +584,7 @@ void init_pdcp(void) { LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); - nr_ip_over_LTE_DRB_preconfiguration();*/ + nr_DRB_preconfiguration();*/ pdcp_module_init(pdcp_initmask); pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); @@ -689,11 +685,14 @@ int main( int argc, char **argv ) { fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; nr_init_frame_parms_ue(frame_parms[CC_id],nrUE_config,NORMAL); - + // Overwrite DL frequency (for FR2 testing) - if (downlink_frequency[0][0]!=0) + if (downlink_frequency[0][0]!=0) { frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0]; + frame_parms[CC_id]->ul_CarrierFreq = downlink_frequency[0][0]; + } + init_symbol_rotation(frame_parms[CC_id],frame_parms[CC_id]->dl_CarrierFreq); init_nr_ue_vars(UE[CC_id],frame_parms[CC_id],0,abstraction_flag); UE[CC_id]->mac_enabled = 1; @@ -761,20 +760,16 @@ int main( int argc, char **argv ) { memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); configure_linux(); mlockall(MCL_CURRENT | MCL_FUTURE); - if (do_forms) - nrUEinitScope(PHY_vars_UE_g[0][0]); + + if(IS_SOFTMODEM_DOFORMS) { + load_softscope("nr",PHY_vars_UE_g[0][0]); + } 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; PHY_vars_UE_g[0][CC_id]->timing_advance = timing_advance; -#else - PHY_vars_UE_g[0][CC_id]->hw_timing_advance = 160; -#endif - } init_NR_UE_threads(1); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 43b921001a..418ed54fc6 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -61,19 +61,11 @@ {"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, u64ptr:&(downlink_frequency[0][0]), defuintval:0,TYPE_UINT64, 0}, \ - {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ - {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:&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}, \ - {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, iptr:&vcdflag, defintval:0, TYPE_INT, 0}, \ - {"numerology" , CONFIG_HLP_NUMEROLOGY, 0, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ - {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ - {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ - {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&UE_no_timing_correction, defintval:0, TYPE_INT, 0}, \ diff --git a/executables/split_headers.h b/executables/split_headers.h index 4e328f74c4..dc451773c5 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -28,6 +28,7 @@ #include #include #include +#include #define CU_PORT "7878" #define DU_PORT "8787" @@ -279,7 +280,7 @@ int init_rf(RU_t *ru); void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc); void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); -void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); +void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, int fembms_flag); bool dlsch_procedures(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int harq_pid, @@ -325,5 +326,6 @@ void fep_full(RU_t *ru, int subframe); void feptx_prec(RU_t *ru,int frame,int subframe); void feptx_ofdm(RU_t *ru, int frame, int subframe); void oai_subframe_ind(uint16_t sfn, uint16_t sf); +void softmodem_printresources(int sig, telnet_printfunc_t pf); extern uint16_t sf_ahead; #endif diff --git a/executables/stats.h b/executables/stats.h index 6c847a2860..9bd4c6f080 100644 --- a/executables/stats.h +++ b/executables/stats.h @@ -21,8 +21,8 @@ /* Header file generated by fdesign on Thu Aug 28 12:13:51 2014 */ -#ifndef FD_stats_form_h_ -#define FD_stats_form_h_ +#ifndef _EXECUTABLES_STATS_H_ +#define _EXECUTABLES_STATS_H_ #include @@ -43,4 +43,4 @@ typedef struct { extern FD_stats_form *create_form_stats_form( void ); -#endif /* FD_stats_form_h_ */ +#endif /* _EXECUTABLES_STATS_H_ */ diff --git a/executables/threads_t.h b/executables/threads_t.h index 0671f40988..c4b233ccc9 100644 --- a/executables/threads_t.h +++ b/executables/threads_t.h @@ -1,5 +1,5 @@ -#ifndef _THREADS_T_H_ -#define _THREADS_T_H_ +#ifndef _EXECUTABLES_THREADS_T_H_ +#define _EXECUTABLES_THREADS_T_H_ typedef struct threads_s { int main; @@ -18,4 +18,4 @@ typedef struct threads_s { //int dlsch_td1_three; } threads_t; -#endif /* _THREADS_T_H_ */ +#endif /* _EXECUTABLES_THREADS_T_H_ */ diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index e57e481dc4..63a1e3c6a8 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -365,7 +365,7 @@ typedef struct //table 3-22 typedef struct { - nfapi_uint8_tlv_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007 + nfapi_uint16_tlv_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007 nfapi_uint8_tlv_t frame_duplex_type;//Frame duplex type Value: 0 = FDD 1 = TDD } nfapi_nr_cell_config_t; diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 345122ca1d..b42ac6e4c8 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -396,17 +396,17 @@ int test_ldpc(short No_iteration, decParams.numMaxIter=No_iteration; decParams.outMode = nrLDPC_outMode_BIT; //decParams.outMode =nrLDPC_outMode_LLRINT8; - - - for(j=0;j 1280, 2401 -> 2560 diff --git a/openair1/PHY/CODING/nrLDPC_decoder_LYC/bgs/BG1_compact_in_C.h b/openair1/PHY/CODING/nrLDPC_decoder_LYC/bgs/BG1_compact_in_C.h new file mode 100644 index 0000000000..9a6086998e --- /dev/null +++ b/openair1/PHY/CODING/nrLDPC_decoder_LYC/bgs/BG1_compact_in_C.h @@ -0,0 +1,478 @@ + +h_element host_h_compact1_I0 [46*19] = +{{0 ,0,250},{1 ,0,2},{2 ,0,106},{3 ,0,121},{4 ,0,157},{5 ,0,205},{6 ,0,183},{7 ,0,220},{8 ,0,112},{9 ,0,103},{10 ,1,98},{11 ,0,77},{12 ,0,160},{13 ,0,177},{14 ,0,206},{15 ,0,40},{16 ,1,64},{17 ,0,7},{18 ,1,42},{19 ,0,60},{20 ,0,151},{21 ,1,249},{22 ,0,64},{23 ,1,156},{24 ,0,112},{25 ,1,23},{26 ,0,195},{27 ,1,25},{28 ,0,128},{29 ,1,86},{30 ,0,216},{31 ,1,95},{32 ,0,221},{33 ,1,2},{34 ,0,127},{35 ,1,161},{36 ,0,37},{37 ,1,198},{38 ,0,167},{39 ,1,173},{40 ,0,157},{41 ,1,167},{42 ,0,149},{43 ,1,151},{44 ,0,139},{45 ,1,149}, +{0 ,1,69},{1 ,2,239},{2 ,1,111},{3 ,1,89},{4 ,1,102},{5 ,1,236},{6 ,6,22},{7 ,1,44},{8 ,1,4},{9 ,1,182},{10 ,2,149},{11 ,1,41},{12 ,1,42},{13 ,3,248},{14 ,12,55},{15 ,1,96},{16 ,3,49},{17 ,14,164},{18 ,12,233},{19 ,1,73},{20 ,3,186},{21 ,5,121},{22 ,12,142},{23 ,2,147},{24 ,3,86},{25 ,6,136},{26 ,2,243},{27 ,6,104},{28 ,4,165},{29 ,14,236},{30 ,10,73},{31 ,7,177},{32 ,12,112},{33 ,2,187},{34 ,7,167},{35 ,6,197},{36 ,14,105},{37 ,13,220},{38 ,9,151},{39 ,3,139},{40 ,8,137},{41 ,3,173},{42 ,4,157},{43 ,16,163},{44 ,7,157},{45 ,6,151}, +{0 ,2,226},{1 ,3,117},{2 ,2,185},{3 ,3,84},{4 ,26,0},{5 ,3,194},{6 ,10,28},{7 ,4,159},{8 ,3,7},{9 ,10,109},{10 ,4,167},{11 ,12,83},{12 ,10,21},{13 ,7,151},{14 ,15,206},{15 ,10,65},{16 ,11,49},{17 ,16,59},{18 ,13,8},{19 ,7,72},{20 ,9,217},{21 ,16,109},{22 ,13,188},{23 ,10,170},{24 ,4,236},{25 ,7,116},{26 ,4,215},{27 ,8,194},{28 ,19,181},{29 ,18,84},{30 ,13,120},{31 ,22,172},{32 ,14,199},{33 ,11,41},{34 ,15,164},{35 ,12,207},{36 ,15,51},{37 ,23,122},{38 ,10,157},{39 ,7,149},{40 ,17,149},{41 ,9,139},{42 ,24,137},{43 ,18,173},{44 ,9,163},{45 ,10,167}, +{0 ,3,159},{1 ,4,124},{2 ,4,63},{3 ,4,20},{0 ,0,-1},{5 ,12,231},{6 ,11,67},{7 ,7,31},{8 ,12,211},{9 ,11,21},{10 ,7,160},{11 ,16,182},{12 ,11,32},{13 ,20,185},{14 ,16,127},{15 ,13,63},{16 ,20,51},{17 ,17,1},{18 ,18,155},{19 ,8,127},{20 ,11,47},{21 ,20,131},{22 ,17,158},{23 ,18,152},{24 ,11,116},{25 ,14,182},{26 ,15,61},{27 ,49,0},{28 ,21,63},{29 ,25,6},{30 ,24,9},{31 ,25,61},{32 ,24,121},{33 ,21,211},{34 ,17,159},{35 ,22,103},{36 ,18,120},{37 ,59,0},{38 ,12,163},{39 ,19,0},{40 ,62,0},{41 ,18,151},{42 ,64,0},{43 ,25,139},{44 ,22,173},{45 ,67,0}, +{0 ,5,100},{1 ,5,71},{2 ,5,117},{3 ,6,150},{0 ,0,-1},{5 ,16,28},{6 ,13,244},{7 ,8,167},{8 ,16,102},{9 ,13,142},{10 ,8,49},{11 ,21,78},{12 ,13,234},{13 ,23,62},{14 ,17,16},{15 ,18,75},{16 ,22,154},{17 ,21,144},{18 ,19,147},{19 ,10,224},{20 ,22,160},{21 ,21,171},{22 ,44,0},{23 ,45,0},{24 ,22,222},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,10},{1 ,7,222},{2 ,6,93},{3 ,7,131},{0 ,0,-1},{5 ,21,123},{6 ,17,11},{7 ,14,104},{8 ,19,164},{9 ,17,14},{10 ,14,58},{11 ,22,252},{12 ,18,7},{13 ,35,0},{14 ,21,229},{15 ,25,179},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,59},{1 ,8,104},{2 ,7,229},{3 ,8,243},{0 ,0,-1},{5 ,22,115},{6 ,18,157},{7 ,29,0},{8 ,21,109},{9 ,18,61},{10 ,32,0},{11 ,23,22},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,229},{1 ,9,173},{2 ,8,177},{3 ,10,136},{0 ,0,-1},{5 ,27,0},{6 ,20,211},{0 ,0,-1},{8 ,22,241},{9 ,20,216},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,110},{1 ,11,220},{2 ,9,95},{3 ,11,86},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,90},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,191},{1 ,12,102},{2 ,10,39},{3 ,12,246},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,9},{1 ,14,109},{2 ,13,142},{3 ,13,219},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,195},{1 ,15,132},{2 ,14,225},{3 ,14,211},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,23},{1 ,16,142},{2 ,15,225},{3 ,16,240},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,190},{1 ,17,155},{2 ,17,245},{3 ,17,76},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,35},{1 ,19,255},{2 ,18,205},{3 ,18,244},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,239},{1 ,21,28},{2 ,19,251},{3 ,20,144},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,31},{1 ,22,0},{2 ,20,117},{3 ,21,12},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,1},{1 ,23,0},{2 ,24,0},{3 ,22,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +}; + + +h_element host_h_compact2_I0 [68*30] = +{{0 ,0,250},{0 ,1,69},{0 ,2,226},{0 ,3,159},{1 ,4,124},{0 ,5,100},{0 ,6,10},{1 ,7,222},{1 ,8,104},{0 ,9,59},{0 ,10,229},{0 ,11,110},{0 ,12,191},{0 ,13,9},{1 ,14,109},{0 ,15,195},{0 ,16,23},{1 ,17,155},{0 ,18,190},{0 ,19,35},{0 ,20,239},{0 ,21,31},{0 ,22,1},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,2},{2 ,1,111},{1 ,2,239},{1 ,3,117},{2 ,4,63},{1 ,5,71},{2 ,6,93},{2 ,7,229},{2 ,8,177},{1 ,9,173},{2 ,10,39},{1 ,11,220},{1 ,12,102},{2 ,13,142},{2 ,14,225},{1 ,15,132},{1 ,16,142},{2 ,17,245},{2 ,18,205},{1 ,19,255},{2 ,20,117},{1 ,21,28},{1 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,106},{3 ,1,89},{2 ,2,185},{3 ,3,84},{3 ,4,20},{2 ,5,117},{3 ,6,150},{3 ,7,131},{3 ,8,243},{2 ,9,95},{3 ,10,136},{3 ,11,86},{3 ,12,246},{3 ,13,219},{3 ,14,211},{2 ,15,225},{3 ,16,240},{3 ,17,76},{3 ,18,244},{2 ,19,251},{3 ,20,144},{3 ,21,12},{3 ,22,1},{11 ,23,22},{8 ,24,90},{15 ,25,179},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,121},{4 ,1,102},{10 ,2,149},{5 ,3,194},{7 ,4,159},{21 ,5,121},{6 ,6,22},{7 ,7,31},{7 ,8,167},{20 ,9,217},{6 ,10,28},{6 ,11,67},{5 ,12,231},{6 ,13,244},{7 ,14,104},{14 ,15,206},{5 ,16,28},{6 ,17,11},{6 ,18,157},{8 ,19,164},{6 ,20,211},{5 ,21,123},{5 ,22,115},{13 ,23,62},{30 ,24,9},{29 ,25,6},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,157},{5 ,1,236},{23 ,2,147},{8 ,3,7},{10 ,4,167},{0 ,0,-1},{25 ,6,136},{10 ,7,160},{10 ,8,49},{38 ,9,151},{9 ,10,109},{9 ,11,21},{8 ,12,211},{9 ,13,142},{10 ,14,58},{26 ,15,61},{8 ,16,102},{9 ,17,14},{9 ,18,61},{18 ,19,147},{9 ,20,216},{8 ,21,109},{8 ,22,241},{37 ,23,122},{32 ,24,121},{31 ,25,61},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,205},{7 ,1,44},{26 ,2,243},{13 ,3,248},{24 ,4,236},{0 ,0,-1},{27 ,6,104},{13 ,7,151},{19 ,8,127},{41 ,9,139},{12 ,10,21},{12 ,11,32},{11 ,12,83},{12 ,13,234},{17 ,14,164},{34 ,15,164},{11 ,16,182},{14 ,17,16},{12 ,18,7},{28 ,19,181},{13 ,20,185},{11 ,21,78},{11 ,22,252},{0 ,0,-1},{42 ,24,137},{43 ,25,139},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,183},{8 ,1,4},{33 ,2,187},{16 ,3,49},{26 ,4,215},{0 ,0,-1},{35 ,6,197},{19 ,7,72},{27 ,8,194},{44 ,9,163},{15 ,10,65},{16 ,11,49},{14 ,12,55},{15 ,13,63},{25 ,14,182},{36 ,15,51},{14 ,16,127},{17 ,17,1},{15 ,18,75},{39 ,19,0},{16 ,20,51},{14 ,21,229},{16 ,22,154},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,220},{9 ,1,182},{0 ,0,-1},{20 ,3,186},{28 ,4,165},{0 ,0,-1},{45 ,6,151},{25 ,7,116},{40 ,8,137},{0 ,0,-1},{19 ,10,224},{20 ,11,47},{18 ,12,233},{18 ,13,8},{29 ,14,236},{0 ,0,-1},{17 ,16,59},{22 ,17,158},{18 ,18,155},{0 ,0,-1},{21 ,20,131},{17 ,21,144},{20 ,22,160},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,112},{10 ,1,98},{0 ,0,-1},{24 ,3,86},{42 ,4,157},{0 ,0,-1},{0 ,0,-1},{31 ,7,177},{0 ,0,-1},{0 ,0,-1},{23 ,10,170},{24 ,11,116},{22 ,12,142},{22 ,13,188},{32 ,14,199},{0 ,0,-1},{21 ,16,109},{34 ,17,159},{23 ,18,152},{0 ,0,-1},{0 ,0,-1},{21 ,21,171},{24 ,22,222},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,103},{11 ,1,41},{0 ,0,-1},{39 ,3,139},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,167},{0 ,0,-1},{0 ,0,-1},{30 ,10,73},{33 ,11,41},{32 ,12,112},{30 ,13,120},{36 ,14,105},{0 ,0,-1},{43 ,16,163},{40 ,17,149},{29 ,18,84},{0 ,0,-1},{0 ,0,-1},{28 ,21,63},{31 ,22,172},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,77},{12 ,1,42},{0 ,0,-1},{41 ,3,173},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,149},{0 ,0,-1},{0 ,0,-1},{38 ,10,157},{0 ,0,-1},{35 ,12,207},{37 ,13,220},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,120},{0 ,0,-1},{0 ,0,-1},{33 ,21,211},{35 ,22,103},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,160},{15 ,1,96},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,157},{0 ,0,-1},{0 ,0,-1},{45 ,10,167},{0 ,0,-1},{38 ,12,163},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,151},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,173},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,177},{16 ,1,64},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,173},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,206},{18 ,1,42},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,40},{19 ,1,73},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,7},{21 ,1,249},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,60},{23 ,1,156},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,151},{25 ,1,23},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,64},{27 ,1,25},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,112},{29 ,1,86},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,195},{31 ,1,95},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,128},{33 ,1,2},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,216},{35 ,1,161},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,221},{37 ,1,198},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,127},{39 ,1,173},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,37},{41 ,1,167},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,167},{43 ,1,151},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,157},{45 ,1,149},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,149},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,139},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + +//--------------------------------------------------BG1_I0----------------------------------------------------------------- + + +//--------------------------------------------------BG1_I1----------------------------------------------------------------- + +h_element host_h_compact1_I1 [46*19] = +{{0 ,0,307},{1 ,0,76},{2 ,0,205},{3 ,0,276},{4 ,0,332},{5 ,0,195},{6 ,0,278},{7 ,0,9},{8 ,0,307},{9 ,0,366},{10 ,1,101},{11 ,0,48},{12 ,0,77},{13 ,0,313},{14 ,0,142},{15 ,0,241},{16 ,1,13},{17 ,0,260},{18 ,1,130},{19 ,0,145},{20 ,0,187},{21 ,1,205},{22 ,0,30},{23 ,1,24},{24 ,0,298},{25 ,1,72},{26 ,0,71},{27 ,1,194},{28 ,0,222},{29 ,1,252},{30 ,0,159},{31 ,1,100},{32 ,0,102},{33 ,1,323},{34 ,0,230},{35 ,1,320},{36 ,0,210},{37 ,1,269},{38 ,0,185},{39 ,1,258},{40 ,0,175},{41 ,1,52},{42 ,0,113},{43 ,1,113},{44 ,0,80},{45 ,1,135}, +{0 ,1,19},{1 ,2,76},{2 ,1,250},{3 ,1,87},{4 ,1,181},{5 ,1,14},{6 ,6,257},{7 ,1,62},{8 ,1,179},{9 ,1,232},{10 ,2,339},{11 ,1,102},{12 ,1,186},{13 ,3,177},{14 ,12,248},{15 ,1,2},{16 ,3,338},{17 ,14,303},{18 ,12,163},{19 ,1,213},{20 ,3,206},{21 ,5,102},{22 ,12,11},{23 ,2,89},{24 ,3,158},{25 ,6,17},{26 ,2,81},{27 ,6,194},{28 ,4,19},{29 ,14,5},{30 ,10,229},{31 ,7,215},{32 ,12,201},{33 ,2,8},{34 ,7,148},{35 ,6,335},{36 ,14,313},{37 ,13,82},{38 ,9,177},{39 ,3,93},{40 ,8,37},{41 ,3,314},{42 ,4,14},{43 ,16,132},{44 ,7,78},{45 ,6,149}, +{0 ,2,50},{1 ,3,73},{2 ,2,328},{3 ,3,0},{4 ,26,0},{5 ,3,115},{6 ,10,1},{7 ,4,316},{8 ,3,165},{9 ,10,321},{10 ,4,274},{11 ,12,8},{12 ,10,174},{13 ,7,266},{14 ,15,137},{15 ,10,210},{16 ,11,57},{17 ,16,81},{18 ,13,280},{19 ,7,344},{20 ,9,264},{21 ,16,328},{22 ,13,233},{23 ,10,61},{24 ,4,235},{25 ,7,383},{26 ,4,76},{27 ,8,101},{28 ,19,244},{29 ,18,147},{30 ,13,260},{31 ,22,258},{32 ,14,175},{33 ,11,361},{34 ,15,202},{35 ,12,2},{36 ,15,297},{37 ,23,115},{38 ,10,289},{39 ,7,346},{40 ,17,312},{41 ,9,139},{42 ,24,218},{43 ,18,114},{44 ,9,163},{45 ,10,15}, +{0 ,3,369},{1 ,4,288},{2 ,4,332},{3 ,4,275},{0 ,0,-1},{5 ,12,166},{6 ,11,351},{7 ,7,333},{8 ,12,18},{9 ,11,133},{10 ,7,111},{11 ,16,47},{12 ,11,232},{13 ,20,115},{14 ,16,89},{15 ,13,318},{16 ,20,289},{17 ,17,358},{18 ,18,132},{19 ,8,242},{20 ,11,341},{21 ,20,213},{22 ,17,22},{23 ,18,27},{24 ,11,339},{25 ,14,312},{26 ,15,136},{27 ,49,0},{28 ,21,274},{29 ,25,78},{30 ,24,90},{31 ,25,256},{32 ,24,287},{33 ,21,105},{34 ,17,312},{35 ,22,266},{36 ,18,21},{37 ,59,0},{38 ,12,214},{39 ,19,297},{40 ,62,0},{41 ,18,288},{42 ,64,0},{43 ,25,168},{44 ,22,274},{45 ,67,0}, +{0 ,5,181},{1 ,5,144},{2 ,5,256},{3 ,6,199},{0 ,0,-1},{5 ,16,241},{6 ,13,92},{7 ,8,290},{8 ,16,39},{9 ,13,57},{10 ,8,383},{11 ,21,188},{12 ,13,50},{13 ,23,370},{14 ,17,347},{15 ,18,55},{16 ,22,57},{17 ,21,375},{18 ,19,4},{19 ,10,197},{20 ,22,59},{21 ,21,97},{22 ,44,0},{23 ,45,0},{24 ,22,234},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,216},{1 ,7,331},{2 ,6,161},{3 ,7,153},{0 ,0,-1},{5 ,21,51},{6 ,17,253},{7 ,14,114},{8 ,19,224},{9 ,17,303},{10 ,14,354},{11 ,22,334},{12 ,18,74},{13 ,35,0},{14 ,21,12},{15 ,25,269},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,317},{1 ,8,331},{2 ,7,267},{3 ,8,56},{0 ,0,-1},{5 ,22,157},{6 ,18,18},{7 ,29,0},{8 ,21,368},{9 ,18,63},{10 ,32,0},{11 ,23,115},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,288},{1 ,9,178},{2 ,8,160},{3 ,10,132},{0 ,0,-1},{5 ,27,0},{6 ,20,225},{0 ,0,-1},{8 ,22,67},{9 ,20,82},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,109},{1 ,11,295},{2 ,9,63},{3 ,11,305},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,170},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,17},{1 ,12,342},{2 ,10,129},{3 ,12,231},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,357},{1 ,14,217},{2 ,13,200},{3 ,13,341},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,215},{1 ,15,99},{2 ,14,88},{3 ,14,212},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,106},{1 ,16,354},{2 ,15,53},{3 ,16,304},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,242},{1 ,17,114},{2 ,17,131},{3 ,17,300},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,180},{1 ,19,331},{2 ,18,240},{3 ,18,271},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,330},{1 ,21,112},{2 ,19,205},{3 ,20,39},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,346},{1 ,22,0},{2 ,20,13},{3 ,21,357},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,1},{1 ,23,0},{2 ,24,0},{3 ,22,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + + +h_element host_h_compact2_I1 [68*30] = +{{0 ,0,307},{0 ,1,19},{0 ,2,50},{0 ,3,369},{1 ,4,288},{0 ,5,181},{0 ,6,216},{1 ,7,331},{1 ,8,331},{0 ,9,317},{0 ,10,288},{0 ,11,109},{0 ,12,17},{0 ,13,357},{1 ,14,217},{0 ,15,215},{0 ,16,106},{1 ,17,114},{0 ,18,242},{0 ,19,180},{0 ,20,330},{0 ,21,346},{0 ,22,1},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,76},{2 ,1,250},{1 ,2,76},{1 ,3,73},{2 ,4,332},{1 ,5,144},{2 ,6,161},{2 ,7,267},{2 ,8,160},{1 ,9,178},{2 ,10,129},{1 ,11,295},{1 ,12,342},{2 ,13,200},{2 ,14,88},{1 ,15,99},{1 ,16,354},{2 ,17,131},{2 ,18,240},{1 ,19,331},{2 ,20,13},{1 ,21,112},{1 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,205},{3 ,1,87},{2 ,2,328},{3 ,3,0},{3 ,4,275},{2 ,5,256},{3 ,6,199},{3 ,7,153},{3 ,8,56},{2 ,9,63},{3 ,10,132},{3 ,11,305},{3 ,12,231},{3 ,13,341},{3 ,14,212},{2 ,15,53},{3 ,16,304},{3 ,17,300},{3 ,18,271},{2 ,19,205},{3 ,20,39},{3 ,21,357},{3 ,22,1},{11 ,23,115},{8 ,24,170},{15 ,25,269},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,276},{4 ,1,181},{10 ,2,339},{5 ,3,115},{7 ,4,316},{21 ,5,102},{6 ,6,257},{7 ,7,333},{7 ,8,290},{20 ,9,264},{6 ,10,1},{6 ,11,351},{5 ,12,166},{6 ,13,92},{7 ,14,114},{14 ,15,137},{5 ,16,241},{6 ,17,253},{6 ,18,18},{8 ,19,224},{6 ,20,225},{5 ,21,51},{5 ,22,157},{13 ,23,370},{30 ,24,90},{29 ,25,78},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,332},{5 ,1,14},{23 ,2,89},{8 ,3,165},{10 ,4,274},{0 ,0,-1},{25 ,6,17},{10 ,7,111},{10 ,8,383},{38 ,9,177},{9 ,10,321},{9 ,11,133},{8 ,12,18},{9 ,13,57},{10 ,14,354},{26 ,15,136},{8 ,16,39},{9 ,17,303},{9 ,18,63},{18 ,19,4},{9 ,20,82},{8 ,21,368},{8 ,22,67},{37 ,23,115},{32 ,24,287},{31 ,25,256},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,195},{7 ,1,62},{26 ,2,81},{13 ,3,177},{24 ,4,235},{0 ,0,-1},{27 ,6,194},{13 ,7,266},{19 ,8,242},{41 ,9,139},{12 ,10,174},{12 ,11,232},{11 ,12,8},{12 ,13,50},{17 ,14,303},{34 ,15,202},{11 ,16,47},{14 ,17,347},{12 ,18,74},{28 ,19,244},{13 ,20,115},{11 ,21,188},{11 ,22,334},{0 ,0,-1},{42 ,24,218},{43 ,25,168},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,278},{8 ,1,179},{33 ,2,8},{16 ,3,338},{26 ,4,76},{0 ,0,-1},{35 ,6,335},{19 ,7,344},{27 ,8,101},{44 ,9,163},{15 ,10,210},{16 ,11,57},{14 ,12,248},{15 ,13,318},{25 ,14,312},{36 ,15,297},{14 ,16,89},{17 ,17,358},{15 ,18,55},{39 ,19,297},{16 ,20,289},{14 ,21,12},{16 ,22,57},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,9},{9 ,1,232},{0 ,0,-1},{20 ,3,206},{28 ,4,19},{0 ,0,-1},{45 ,6,149},{25 ,7,383},{40 ,8,37},{0 ,0,-1},{19 ,10,197},{20 ,11,341},{18 ,12,163},{18 ,13,280},{29 ,14,5},{0 ,0,-1},{17 ,16,81},{22 ,17,22},{18 ,18,132},{0 ,0,-1},{21 ,20,213},{17 ,21,375},{20 ,22,59},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,307},{10 ,1,101},{0 ,0,-1},{24 ,3,158},{42 ,4,14},{0 ,0,-1},{0 ,0,-1},{31 ,7,215},{0 ,0,-1},{0 ,0,-1},{23 ,10,61},{24 ,11,339},{22 ,12,11},{22 ,13,233},{32 ,14,175},{0 ,0,-1},{21 ,16,328},{34 ,17,312},{23 ,18,27},{0 ,0,-1},{0 ,0,-1},{21 ,21,97},{24 ,22,234},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,366},{11 ,1,102},{0 ,0,-1},{39 ,3,93},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,148},{0 ,0,-1},{0 ,0,-1},{30 ,10,229},{33 ,11,361},{32 ,12,201},{30 ,13,260},{36 ,14,313},{0 ,0,-1},{43 ,16,132},{40 ,17,312},{29 ,18,147},{0 ,0,-1},{0 ,0,-1},{28 ,21,274},{31 ,22,258},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,48},{12 ,1,186},{0 ,0,-1},{41 ,3,314},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,346},{0 ,0,-1},{0 ,0,-1},{38 ,10,289},{0 ,0,-1},{35 ,12,2},{37 ,13,82},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,21},{0 ,0,-1},{0 ,0,-1},{33 ,21,105},{35 ,22,266},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,77},{15 ,1,2},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,78},{0 ,0,-1},{0 ,0,-1},{45 ,10,15},{0 ,0,-1},{38 ,12,214},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,288},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,274},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,313},{16 ,1,13},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,114},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,142},{18 ,1,130},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,241},{19 ,1,213},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,260},{21 ,1,205},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,145},{23 ,1,24},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,187},{25 ,1,72},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,30},{27 ,1,194},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,298},{29 ,1,252},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,71},{31 ,1,100},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,222},{33 ,1,323},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,159},{35 ,1,320},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,102},{37 ,1,269},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,230},{39 ,1,258},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,210},{41 ,1,52},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,185},{43 ,1,113},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,175},{45 ,1,135},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,113},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,80},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + +//--------------------------------------------------BG1_I1----------------------------------------------------------------- + +//--------------------------------------------------BG1_I2----------------------------------------------------------------- + +h_element host_h_compact1_I2 [46*19] = +{{0 ,0,73},{1 ,0,303},{2 ,0,68},{3 ,0,220},{4 ,0,233},{5 ,0,83},{6 ,0,289},{7 ,0,12},{8 ,0,295},{9 ,0,189},{10 ,1,14},{11 ,0,16},{12 ,0,229},{13 ,0,39},{14 ,0,78},{15 ,0,229},{16 ,1,69},{17 ,0,257},{18 ,1,260},{19 ,0,64},{20 ,0,301},{21 ,1,79},{22 ,0,177},{23 ,1,249},{24 ,0,289},{25 ,1,172},{26 ,0,270},{27 ,1,210},{28 ,0,11},{29 ,1,27},{30 ,0,91},{31 ,1,222},{32 ,0,210},{33 ,1,170},{34 ,0,187},{35 ,1,207},{36 ,0,259},{37 ,1,298},{38 ,0,151},{39 ,1,102},{40 ,0,32},{41 ,1,154},{42 ,0,226},{43 ,1,228},{44 ,0,234},{45 ,1,101}, +{0 ,1,15},{1 ,2,294},{2 ,1,7},{3 ,1,208},{4 ,1,205},{5 ,1,292},{6 ,6,21},{7 ,1,88},{8 ,1,133},{9 ,1,244},{10 ,2,80},{11 ,1,147},{12 ,1,235},{13 ,3,302},{14 ,12,299},{15 ,1,290},{16 ,3,140},{17 ,14,147},{18 ,12,294},{19 ,1,181},{20 ,3,162},{21 ,5,175},{22 ,12,20},{23 ,2,50},{24 ,3,280},{25 ,6,295},{26 ,2,110},{27 ,6,29},{28 ,4,293},{29 ,14,308},{30 ,10,23},{31 ,7,308},{32 ,12,22},{33 ,2,20},{34 ,7,296},{35 ,6,158},{36 ,14,179},{37 ,13,15},{38 ,9,179},{39 ,3,77},{40 ,8,80},{41 ,3,47},{42 ,4,65},{43 ,16,69},{44 ,7,227},{45 ,6,228}, +{0 ,2,103},{1 ,3,27},{2 ,2,80},{3 ,3,30},{4 ,26,0},{5 ,3,50},{6 ,10,293},{7 ,4,207},{8 ,3,130},{9 ,10,36},{10 ,4,211},{11 ,12,290},{12 ,10,169},{13 ,7,303},{14 ,15,54},{15 ,10,60},{16 ,11,45},{17 ,16,128},{18 ,13,291},{19 ,7,101},{20 ,9,40},{21 ,16,132},{22 ,13,55},{23 ,10,133},{24 ,4,110},{25 ,7,96},{26 ,4,318},{27 ,8,304},{28 ,19,50},{29 ,18,117},{30 ,13,105},{31 ,22,66},{32 ,14,271},{33 ,11,140},{34 ,15,5},{35 ,12,55},{36 ,15,178},{37 ,23,115},{38 ,10,64},{39 ,7,192},{40 ,17,197},{41 ,9,124},{42 ,24,126},{43 ,18,176},{44 ,9,259},{45 ,10,126}, +{0 ,3,49},{1 ,4,261},{2 ,4,280},{3 ,4,197},{0 ,0,-1},{5 ,12,318},{6 ,11,13},{7 ,7,50},{8 ,12,231},{9 ,11,286},{10 ,7,75},{11 ,16,289},{12 ,11,48},{13 ,20,160},{14 ,16,61},{15 ,13,130},{16 ,20,115},{17 ,17,51},{18 ,18,141},{19 ,8,270},{20 ,11,130},{21 ,20,283},{22 ,17,316},{23 ,18,105},{24 ,11,187},{25 ,14,46},{26 ,15,67},{27 ,49,0},{28 ,21,234},{29 ,25,29},{30 ,24,135},{31 ,25,162},{32 ,24,217},{33 ,21,33},{34 ,17,44},{35 ,22,285},{36 ,18,160},{37 ,59,0},{38 ,12,181},{39 ,19,208},{40 ,62,0},{41 ,18,207},{42 ,64,0},{43 ,25,102},{44 ,22,260},{45 ,67,0}, +{0 ,5,240},{1 ,5,161},{2 ,5,38},{3 ,6,61},{0 ,0,-1},{5 ,16,201},{6 ,13,232},{7 ,8,25},{8 ,16,296},{9 ,13,151},{10 ,8,161},{11 ,21,177},{12 ,13,105},{13 ,23,37},{14 ,17,179},{15 ,18,184},{16 ,22,300},{17 ,21,228},{18 ,19,295},{19 ,10,41},{20 ,22,10},{21 ,21,103},{22 ,44,0},{23 ,45,0},{24 ,22,281},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,39},{1 ,7,133},{2 ,6,227},{3 ,7,175},{0 ,0,-1},{5 ,21,267},{6 ,17,302},{7 ,14,76},{8 ,19,110},{9 ,17,267},{10 ,14,311},{11 ,22,43},{12 ,18,52},{13 ,35,0},{14 ,21,258},{15 ,25,51},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,15},{1 ,8,4},{2 ,7,202},{3 ,8,79},{0 ,0,-1},{5 ,22,279},{6 ,18,138},{7 ,29,0},{8 ,21,269},{9 ,18,135},{10 ,32,0},{11 ,23,280},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,162},{1 ,9,80},{2 ,8,200},{3 ,10,281},{0 ,0,-1},{5 ,27,0},{6 ,20,235},{0 ,0,-1},{8 ,22,245},{9 ,20,209},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,215},{1 ,11,129},{2 ,9,71},{3 ,11,303},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,154},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,164},{1 ,12,300},{2 ,10,106},{3 ,12,253},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,133},{1 ,14,76},{2 ,13,295},{3 ,13,164},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,298},{1 ,15,266},{2 ,14,283},{3 ,14,53},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,110},{1 ,16,72},{2 ,15,301},{3 ,16,44},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,113},{1 ,17,83},{2 ,17,184},{3 ,17,28},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,16},{1 ,19,260},{2 ,18,246},{3 ,18,77},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,189},{1 ,21,301},{2 ,19,230},{3 ,20,319},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,32},{1 ,22,0},{2 ,20,276},{3 ,21,68},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,1},{1 ,23,0},{2 ,24,0},{3 ,22,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + + +h_element host_h_compact2_I2 [68*30] = +{{0 ,0,73},{0 ,1,15},{0 ,2,103},{0 ,3,49},{1 ,4,261},{0 ,5,240},{0 ,6,39},{1 ,7,133},{1 ,8,4},{0 ,9,15},{0 ,10,162},{0 ,11,215},{0 ,12,164},{0 ,13,133},{1 ,14,76},{0 ,15,298},{0 ,16,110},{1 ,17,83},{0 ,18,113},{0 ,19,16},{0 ,20,189},{0 ,21,32},{0 ,22,1},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,303},{2 ,1,7},{1 ,2,294},{1 ,3,27},{2 ,4,280},{1 ,5,161},{2 ,6,227},{2 ,7,202},{2 ,8,200},{1 ,9,80},{2 ,10,106},{1 ,11,129},{1 ,12,300},{2 ,13,295},{2 ,14,283},{1 ,15,266},{1 ,16,72},{2 ,17,184},{2 ,18,246},{1 ,19,260},{2 ,20,276},{1 ,21,301},{1 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,68},{3 ,1,208},{2 ,2,80},{3 ,3,30},{3 ,4,197},{2 ,5,38},{3 ,6,61},{3 ,7,175},{3 ,8,79},{2 ,9,71},{3 ,10,281},{3 ,11,303},{3 ,12,253},{3 ,13,164},{3 ,14,53},{2 ,15,301},{3 ,16,44},{3 ,17,28},{3 ,18,77},{2 ,19,230},{3 ,20,319},{3 ,21,68},{3 ,22,1},{11 ,23,280},{8 ,24,154},{15 ,25,51},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,220},{4 ,1,205},{10 ,2,80},{5 ,3,50},{7 ,4,207},{21 ,5,175},{6 ,6,21},{7 ,7,50},{7 ,8,25},{20 ,9,40},{6 ,10,293},{6 ,11,13},{5 ,12,318},{6 ,13,232},{7 ,14,76},{14 ,15,54},{5 ,16,201},{6 ,17,302},{6 ,18,138},{8 ,19,110},{6 ,20,235},{5 ,21,267},{5 ,22,279},{13 ,23,37},{30 ,24,135},{29 ,25,29},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,233},{5 ,1,292},{23 ,2,50},{8 ,3,130},{10 ,4,211},{0 ,0,-1},{25 ,6,295},{10 ,7,75},{10 ,8,161},{38 ,9,179},{9 ,10,36},{9 ,11,286},{8 ,12,231},{9 ,13,151},{10 ,14,311},{26 ,15,67},{8 ,16,296},{9 ,17,267},{9 ,18,135},{18 ,19,295},{9 ,20,209},{8 ,21,269},{8 ,22,245},{37 ,23,115},{32 ,24,217},{31 ,25,162},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,83},{7 ,1,88},{26 ,2,110},{13 ,3,302},{24 ,4,110},{0 ,0,-1},{27 ,6,29},{13 ,7,303},{19 ,8,270},{41 ,9,124},{12 ,10,169},{12 ,11,48},{11 ,12,290},{12 ,13,105},{17 ,14,147},{34 ,15,5},{11 ,16,289},{14 ,17,179},{12 ,18,52},{28 ,19,50},{13 ,20,160},{11 ,21,177},{11 ,22,43},{0 ,0,-1},{42 ,24,126},{43 ,25,102},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,289},{8 ,1,133},{33 ,2,20},{16 ,3,140},{26 ,4,318},{0 ,0,-1},{35 ,6,158},{19 ,7,101},{27 ,8,304},{44 ,9,259},{15 ,10,60},{16 ,11,45},{14 ,12,299},{15 ,13,130},{25 ,14,46},{36 ,15,178},{14 ,16,61},{17 ,17,51},{15 ,18,184},{39 ,19,208},{16 ,20,115},{14 ,21,258},{16 ,22,300},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,12},{9 ,1,244},{0 ,0,-1},{20 ,3,162},{28 ,4,293},{0 ,0,-1},{45 ,6,228},{25 ,7,96},{40 ,8,80},{0 ,0,-1},{19 ,10,41},{20 ,11,130},{18 ,12,294},{18 ,13,291},{29 ,14,308},{0 ,0,-1},{17 ,16,128},{22 ,17,316},{18 ,18,141},{0 ,0,-1},{21 ,20,283},{17 ,21,228},{20 ,22,10},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,295},{10 ,1,14},{0 ,0,-1},{24 ,3,280},{42 ,4,65},{0 ,0,-1},{0 ,0,-1},{31 ,7,308},{0 ,0,-1},{0 ,0,-1},{23 ,10,133},{24 ,11,187},{22 ,12,20},{22 ,13,55},{32 ,14,271},{0 ,0,-1},{21 ,16,132},{34 ,17,44},{23 ,18,105},{0 ,0,-1},{0 ,0,-1},{21 ,21,103},{24 ,22,281},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,189},{11 ,1,147},{0 ,0,-1},{39 ,3,77},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,296},{0 ,0,-1},{0 ,0,-1},{30 ,10,23},{33 ,11,140},{32 ,12,22},{30 ,13,105},{36 ,14,179},{0 ,0,-1},{43 ,16,69},{40 ,17,197},{29 ,18,117},{0 ,0,-1},{0 ,0,-1},{28 ,21,234},{31 ,22,66},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,16},{12 ,1,235},{0 ,0,-1},{41 ,3,47},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,192},{0 ,0,-1},{0 ,0,-1},{38 ,10,64},{0 ,0,-1},{35 ,12,55},{37 ,13,15},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,160},{0 ,0,-1},{0 ,0,-1},{33 ,21,33},{35 ,22,285},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,229},{15 ,1,290},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,227},{0 ,0,-1},{0 ,0,-1},{45 ,10,126},{0 ,0,-1},{38 ,12,181},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,207},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,260},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,39},{16 ,1,69},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,176},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,78},{18 ,1,260},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,229},{19 ,1,181},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,257},{21 ,1,79},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,64},{23 ,1,249},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,301},{25 ,1,172},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,177},{27 ,1,210},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,289},{29 ,1,27},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,270},{31 ,1,222},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,11},{33 ,1,170},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,91},{35 ,1,207},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,210},{37 ,1,298},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,187},{39 ,1,102},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,259},{41 ,1,154},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,151},{43 ,1,228},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,32},{45 ,1,101},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,226},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,234},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + +//--------------------------------------------------BG1_I2----------------------------------------------------------------- + + +//--------------------------------------------------BG1_I3----------------------------------------------------------------- + +h_element host_h_compact1_I3 [46*19] = +{{0 ,0,223},{1 ,0,141},{2 ,0,207},{3 ,0,201},{4 ,0,170},{5 ,0,164},{6 ,0,158},{7 ,0,17},{8 ,0,33},{9 ,0,9},{10 ,1,82},{11 ,0,52},{12 ,0,142},{13 ,0,81},{14 ,0,14},{15 ,0,90},{16 ,1,154},{17 ,0,56},{18 ,1,199},{19 ,0,8},{20 ,0,105},{21 ,1,192},{22 ,0,53},{23 ,1,88},{24 ,0,49},{25 ,1,1},{26 ,0,107},{27 ,1,208},{28 ,0,146},{29 ,1,150},{30 ,0,34},{31 ,1,175},{32 ,0,192},{33 ,1,114},{34 ,0,82},{35 ,1,192},{36 ,0,222},{37 ,1,81},{38 ,0,123},{39 ,1,12},{40 ,0,67},{41 ,1,23},{42 ,0,114},{43 ,1,206},{44 ,0,84},{45 ,1,184}, +{0 ,1,16},{1 ,2,45},{2 ,1,203},{3 ,1,18},{4 ,1,10},{5 ,1,59},{6 ,6,119},{7 ,1,76},{8 ,1,95},{9 ,1,37},{10 ,2,165},{11 ,1,11},{12 ,1,175},{13 ,3,56},{14 ,12,175},{15 ,1,120},{16 ,3,164},{17 ,14,110},{18 ,12,110},{19 ,1,6},{20 ,3,210},{21 ,5,131},{22 ,12,0},{23 ,2,203},{24 ,3,157},{25 ,6,166},{26 ,2,176},{27 ,6,141},{28 ,4,153},{29 ,14,11},{30 ,10,130},{31 ,7,49},{32 ,12,209},{33 ,2,49},{34 ,7,186},{35 ,6,173},{36 ,14,157},{37 ,13,195},{38 ,9,90},{39 ,3,77},{40 ,8,45},{41 ,3,215},{42 ,4,91},{43 ,16,22},{44 ,7,4},{45 ,6,121}, +{0 ,2,94},{1 ,3,151},{2 ,2,31},{3 ,3,165},{4 ,26,0},{5 ,3,86},{6 ,10,113},{7 ,4,104},{8 ,3,4},{9 ,10,213},{10 ,4,174},{11 ,12,2},{12 ,10,136},{13 ,7,72},{14 ,15,211},{15 ,10,131},{16 ,11,43},{17 ,16,200},{18 ,13,200},{19 ,7,103},{20 ,9,121},{21 ,16,220},{22 ,13,3},{23 ,10,168},{24 ,4,64},{25 ,7,65},{26 ,4,212},{27 ,8,174},{28 ,19,217},{29 ,18,53},{30 ,13,210},{31 ,22,177},{32 ,14,58},{33 ,11,161},{34 ,15,68},{35 ,12,26},{36 ,15,0},{37 ,23,138},{38 ,10,73},{39 ,7,49},{40 ,17,96},{41 ,9,60},{42 ,24,78},{43 ,18,134},{44 ,9,9},{45 ,10,29}, +{0 ,3,91},{1 ,4,46},{2 ,4,176},{3 ,4,5},{0 ,0,-1},{5 ,12,80},{6 ,11,21},{7 ,7,100},{8 ,12,217},{9 ,11,105},{10 ,7,19},{11 ,16,35},{12 ,11,3},{13 ,20,217},{14 ,16,191},{15 ,13,209},{16 ,20,189},{17 ,17,63},{18 ,18,143},{19 ,8,198},{20 ,11,214},{21 ,20,50},{22 ,17,148},{23 ,18,122},{24 ,11,193},{25 ,14,81},{26 ,15,127},{27 ,49,0},{28 ,21,114},{29 ,25,68},{30 ,24,123},{31 ,25,128},{32 ,24,30},{33 ,21,137},{34 ,17,150},{35 ,22,187},{36 ,18,6},{37 ,59,0},{38 ,12,10},{39 ,19,114},{40 ,62,0},{41 ,18,167},{42 ,64,0},{43 ,25,161},{44 ,22,12},{45 ,67,0}, +{0 ,5,74},{1 ,5,119},{2 ,5,180},{3 ,6,45},{0 ,0,-1},{5 ,16,182},{6 ,13,63},{7 ,8,150},{8 ,16,204},{9 ,13,89},{10 ,8,194},{11 ,21,32},{12 ,13,28},{13 ,23,78},{14 ,17,51},{15 ,18,209},{16 ,22,101},{17 ,21,4},{18 ,19,186},{19 ,10,8},{20 ,22,183},{21 ,21,106},{22 ,44,0},{23 ,45,0},{24 ,22,124},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,10},{1 ,7,157},{2 ,6,186},{3 ,7,142},{0 ,0,-1},{5 ,21,130},{6 ,17,51},{7 ,14,158},{8 ,19,39},{9 ,17,185},{10 ,14,103},{11 ,22,84},{12 ,18,182},{13 ,35,0},{14 ,21,43},{15 ,25,81},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,0},{1 ,8,133},{2 ,7,95},{3 ,8,16},{0 ,0,-1},{5 ,22,153},{6 ,18,136},{7 ,29,0},{8 ,21,58},{9 ,18,109},{10 ,32,0},{11 ,23,201},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,205},{1 ,9,87},{2 ,8,153},{3 ,10,34},{0 ,0,-1},{5 ,27,0},{6 ,20,116},{0 ,0,-1},{8 ,22,44},{9 ,20,218},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,216},{1 ,11,206},{2 ,9,177},{3 ,11,155},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,201},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,21},{1 ,12,93},{2 ,10,70},{3 ,12,213},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,215},{1 ,14,79},{2 ,13,77},{3 ,13,147},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,14},{1 ,15,9},{2 ,14,214},{3 ,14,69},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,70},{1 ,16,118},{2 ,15,77},{3 ,16,96},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,141},{1 ,17,194},{2 ,17,198},{3 ,17,74},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,198},{1 ,19,31},{2 ,18,117},{3 ,18,99},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,104},{1 ,21,187},{2 ,19,223},{3 ,20,30},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,81},{1 ,22,0},{2 ,20,90},{3 ,21,158},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,1},{1 ,23,0},{2 ,24,0},{3 ,22,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +}; + +h_element host_h_compact2_I3 [68*30] = +{{0 ,0,223},{0 ,1,16},{0 ,2,94},{0 ,3,91},{1 ,4,46},{0 ,5,74},{0 ,6,10},{1 ,7,157},{1 ,8,133},{0 ,9,0},{0 ,10,205},{0 ,11,216},{0 ,12,21},{0 ,13,215},{1 ,14,79},{0 ,15,14},{0 ,16,70},{1 ,17,194},{0 ,18,141},{0 ,19,198},{0 ,20,104},{0 ,21,81},{0 ,22,1},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,141},{2 ,1,203},{1 ,2,45},{1 ,3,151},{2 ,4,176},{1 ,5,119},{2 ,6,186},{2 ,7,95},{2 ,8,153},{1 ,9,87},{2 ,10,70},{1 ,11,206},{1 ,12,93},{2 ,13,77},{2 ,14,214},{1 ,15,9},{1 ,16,118},{2 ,17,198},{2 ,18,117},{1 ,19,31},{2 ,20,90},{1 ,21,187},{1 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,207},{3 ,1,18},{2 ,2,31},{3 ,3,165},{3 ,4,5},{2 ,5,180},{3 ,6,45},{3 ,7,142},{3 ,8,16},{2 ,9,177},{3 ,10,34},{3 ,11,155},{3 ,12,213},{3 ,13,147},{3 ,14,69},{2 ,15,77},{3 ,16,96},{3 ,17,74},{3 ,18,99},{2 ,19,223},{3 ,20,30},{3 ,21,158},{3 ,22,1},{11 ,23,201},{8 ,24,201},{15 ,25,81},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,201},{4 ,1,10},{10 ,2,165},{5 ,3,86},{7 ,4,104},{21 ,5,131},{6 ,6,119},{7 ,7,100},{7 ,8,150},{20 ,9,121},{6 ,10,113},{6 ,11,21},{5 ,12,80},{6 ,13,63},{7 ,14,158},{14 ,15,211},{5 ,16,182},{6 ,17,51},{6 ,18,136},{8 ,19,39},{6 ,20,116},{5 ,21,130},{5 ,22,153},{13 ,23,78},{30 ,24,123},{29 ,25,68},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,170},{5 ,1,59},{23 ,2,203},{8 ,3,4},{10 ,4,174},{0 ,0,-1},{25 ,6,166},{10 ,7,19},{10 ,8,194},{38 ,9,90},{9 ,10,213},{9 ,11,105},{8 ,12,217},{9 ,13,89},{10 ,14,103},{26 ,15,127},{8 ,16,204},{9 ,17,185},{9 ,18,109},{18 ,19,186},{9 ,20,218},{8 ,21,58},{8 ,22,44},{37 ,23,138},{32 ,24,30},{31 ,25,128},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,164},{7 ,1,76},{26 ,2,176},{13 ,3,56},{24 ,4,64},{0 ,0,-1},{27 ,6,141},{13 ,7,72},{19 ,8,198},{41 ,9,60},{12 ,10,136},{12 ,11,3},{11 ,12,2},{12 ,13,28},{17 ,14,110},{34 ,15,68},{11 ,16,35},{14 ,17,51},{12 ,18,182},{28 ,19,217},{13 ,20,217},{11 ,21,32},{11 ,22,84},{0 ,0,-1},{42 ,24,78},{43 ,25,161},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,158},{8 ,1,95},{33 ,2,49},{16 ,3,164},{26 ,4,212},{0 ,0,-1},{35 ,6,173},{19 ,7,103},{27 ,8,174},{44 ,9,9},{15 ,10,131},{16 ,11,43},{14 ,12,175},{15 ,13,209},{25 ,14,81},{36 ,15,0},{14 ,16,191},{17 ,17,63},{15 ,18,209},{39 ,19,114},{16 ,20,189},{14 ,21,43},{16 ,22,101},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,17},{9 ,1,37},{0 ,0,-1},{20 ,3,210},{28 ,4,153},{0 ,0,-1},{45 ,6,121},{25 ,7,65},{40 ,8,45},{0 ,0,-1},{19 ,10,8},{20 ,11,214},{18 ,12,110},{18 ,13,200},{29 ,14,11},{0 ,0,-1},{17 ,16,200},{22 ,17,148},{18 ,18,143},{0 ,0,-1},{21 ,20,50},{17 ,21,4},{20 ,22,183},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,33},{10 ,1,82},{0 ,0,-1},{24 ,3,157},{42 ,4,91},{0 ,0,-1},{0 ,0,-1},{31 ,7,49},{0 ,0,-1},{0 ,0,-1},{23 ,10,168},{24 ,11,193},{22 ,12,0},{22 ,13,3},{32 ,14,58},{0 ,0,-1},{21 ,16,220},{34 ,17,150},{23 ,18,122},{0 ,0,-1},{0 ,0,-1},{21 ,21,106},{24 ,22,124},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,9},{11 ,1,11},{0 ,0,-1},{39 ,3,77},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,186},{0 ,0,-1},{0 ,0,-1},{30 ,10,130},{33 ,11,161},{32 ,12,209},{30 ,13,210},{36 ,14,157},{0 ,0,-1},{43 ,16,22},{40 ,17,96},{29 ,18,53},{0 ,0,-1},{0 ,0,-1},{28 ,21,114},{31 ,22,177},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,52},{12 ,1,175},{0 ,0,-1},{41 ,3,215},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,49},{0 ,0,-1},{0 ,0,-1},{38 ,10,73},{0 ,0,-1},{35 ,12,26},{37 ,13,195},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,6},{0 ,0,-1},{0 ,0,-1},{33 ,21,137},{35 ,22,187},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,142},{15 ,1,120},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,4},{0 ,0,-1},{0 ,0,-1},{45 ,10,29},{0 ,0,-1},{38 ,12,10},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,167},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,12},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,81},{16 ,1,154},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,134},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,14},{18 ,1,199},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,90},{19 ,1,6},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,56},{21 ,1,192},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,8},{23 ,1,88},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,105},{25 ,1,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,53},{27 ,1,208},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,49},{29 ,1,150},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,107},{31 ,1,175},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,146},{33 ,1,114},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,34},{35 ,1,192},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,192},{37 ,1,81},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,82},{39 ,1,12},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,222},{41 ,1,23},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,123},{43 ,1,206},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,67},{45 ,1,184},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,114},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,84},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + + +//--------------------------------------------------BG1_I3----------------------------------------------------------------- + + +//--------------------------------------------------BG1_I4----------------------------------------------------------------- +h_element host_h_compact1_I4 [46*19] = +{{0 ,0,211},{1 ,0,179},{2 ,0,258},{3 ,0,187},{4 ,0,246},{5 ,0,261},{6 ,0,80},{7 ,0,169},{8 ,0,54},{9 ,0,162},{10 ,1,178},{11 ,0,55},{12 ,0,225},{13 ,0,231},{14 ,0,0},{15 ,0,170},{16 ,1,270},{17 ,0,153},{18 ,1,161},{19 ,0,0},{20 ,0,265},{21 ,1,64},{22 ,0,72},{23 ,1,180},{24 ,0,236},{25 ,1,205},{26 ,0,0},{27 ,1,45},{28 ,0,275},{29 ,1,0},{30 ,0,0},{31 ,1,144},{32 ,0,0},{33 ,1,0},{34 ,0,197},{35 ,1,199},{36 ,0,216},{37 ,1,72},{38 ,0,190},{39 ,1,153},{40 ,0,216},{41 ,1,0},{42 ,0,27},{43 ,1,52},{44 ,0,18},{45 ,1,168}, +{0 ,1,198},{1 ,2,162},{2 ,1,167},{3 ,1,145},{4 ,1,235},{5 ,1,181},{6 ,6,144},{7 ,1,189},{8 ,1,0},{9 ,1,159},{10 ,2,1},{11 ,1,23},{12 ,1,162},{13 ,3,0},{14 ,12,186},{15 ,1,0},{16 ,3,13},{17 ,14,137},{18 ,12,151},{19 ,1,0},{20 ,3,81},{21 ,5,46},{22 ,12,189},{23 ,2,0},{24 ,3,199},{25 ,6,0},{26 ,2,0},{27 ,6,36},{28 ,4,0},{29 ,14,180},{30 ,10,90},{31 ,7,144},{32 ,12,211},{33 ,2,0},{34 ,7,0},{35 ,6,278},{36 ,14,16},{37 ,13,144},{38 ,9,0},{39 ,3,0},{40 ,8,144},{41 ,3,0},{42 ,4,0},{43 ,16,243},{44 ,7,0},{45 ,6,0}, +{0 ,2,188},{1 ,3,223},{2 ,2,220},{3 ,3,166},{4 ,26,0},{5 ,3,72},{6 ,10,169},{7 ,4,154},{8 ,3,252},{9 ,10,93},{10 ,4,28},{11 ,12,274},{12 ,10,244},{13 ,7,216},{14 ,15,253},{15 ,10,183},{16 ,11,99},{17 ,16,0},{18 ,13,0},{19 ,7,118},{20 ,9,90},{21 ,16,266},{22 ,13,72},{23 ,10,0},{24 ,4,0},{25 ,7,0},{26 ,4,0},{27 ,8,72},{28 ,19,155},{29 ,18,0},{30 ,13,252},{31 ,22,166},{32 ,14,36},{33 ,11,76},{34 ,15,108},{35 ,12,0},{36 ,15,0},{37 ,23,0},{38 ,10,0},{39 ,7,165},{40 ,17,2},{41 ,9,0},{42 ,24,35},{43 ,18,0},{44 ,9,0},{45 ,10,144}, +{0 ,3,186},{1 ,4,256},{2 ,4,133},{3 ,4,108},{0 ,0,-1},{5 ,12,283},{6 ,11,90},{7 ,7,184},{8 ,12,41},{9 ,11,134},{10 ,7,267},{11 ,16,181},{12 ,11,151},{13 ,20,47},{14 ,16,16},{15 ,13,108},{16 ,20,54},{17 ,17,0},{18 ,18,241},{19 ,8,144},{20 ,11,144},{21 ,20,9},{22 ,17,257},{23 ,18,165},{24 ,11,266},{25 ,14,183},{26 ,15,277},{27 ,49,0},{28 ,21,62},{29 ,25,42},{30 ,24,173},{31 ,25,19},{32 ,24,162},{33 ,21,18},{34 ,17,0},{35 ,22,205},{36 ,18,0},{37 ,59,0},{38 ,12,0},{39 ,19,117},{40 ,62,0},{41 ,18,183},{42 ,64,0},{43 ,25,270},{44 ,22,57},{45 ,67,0}, +{0 ,5,219},{1 ,5,160},{2 ,5,243},{3 ,6,82},{0 ,0,-1},{5 ,16,254},{6 ,13,59},{7 ,8,104},{8 ,16,98},{9 ,13,45},{10 ,8,234},{11 ,21,273},{12 ,13,238},{13 ,23,36},{14 ,17,0},{15 ,18,68},{16 ,22,0},{17 ,21,162},{18 ,19,144},{19 ,10,0},{20 ,22,228},{21 ,21,18},{22 ,44,0},{23 ,45,0},{24 ,22,0},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,4},{1 ,7,76},{2 ,6,202},{3 ,7,132},{0 ,0,-1},{5 ,21,79},{6 ,17,177},{7 ,14,164},{8 ,19,46},{9 ,17,132},{10 ,14,201},{11 ,22,39},{12 ,18,243},{13 ,35,0},{14 ,21,79},{15 ,25,64},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,29},{1 ,8,202},{2 ,7,218},{3 ,8,197},{0 ,0,-1},{5 ,22,144},{6 ,18,151},{7 ,29,0},{8 ,21,15},{9 ,18,76},{10 ,32,0},{11 ,23,26},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,144},{1 ,9,117},{2 ,8,63},{3 ,10,41},{0 ,0,-1},{5 ,27,0},{6 ,20,108},{0 ,0,-1},{8 ,22,230},{9 ,20,209},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,116},{1 ,11,109},{2 ,9,0},{3 ,11,162},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,54},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,216},{1 ,12,15},{2 ,10,3},{3 ,12,57},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,115},{1 ,14,72},{2 ,13,74},{3 ,13,36},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,233},{1 ,15,152},{2 ,14,229},{3 ,14,115},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,144},{1 ,16,158},{2 ,15,0},{3 ,16,242},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,95},{1 ,17,147},{2 ,17,216},{3 ,17,165},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,216},{1 ,19,156},{2 ,18,269},{3 ,18,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,73},{1 ,21,119},{2 ,19,200},{3 ,20,113},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,261},{1 ,22,0},{2 ,20,234},{3 ,21,108},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,1},{1 ,23,0},{2 ,24,0},{3 ,22,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +}; + + +h_element host_h_compact2_I4 [68*30] = +{{0 ,0,211},{0 ,1,198},{0 ,2,188},{0 ,3,186},{1 ,4,256},{0 ,5,219},{0 ,6,4},{1 ,7,76},{1 ,8,202},{0 ,9,29},{0 ,10,144},{0 ,11,116},{0 ,12,216},{0 ,13,115},{1 ,14,72},{0 ,15,233},{0 ,16,144},{1 ,17,147},{0 ,18,95},{0 ,19,216},{0 ,20,73},{0 ,21,261},{0 ,22,1},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,179},{2 ,1,167},{1 ,2,162},{1 ,3,223},{2 ,4,133},{1 ,5,160},{2 ,6,202},{2 ,7,218},{2 ,8,63},{1 ,9,117},{2 ,10,3},{1 ,11,109},{1 ,12,15},{2 ,13,74},{2 ,14,229},{1 ,15,152},{1 ,16,158},{2 ,17,216},{2 ,18,269},{1 ,19,156},{2 ,20,234},{1 ,21,119},{1 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,258},{3 ,1,145},{2 ,2,220},{3 ,3,166},{3 ,4,108},{2 ,5,243},{3 ,6,82},{3 ,7,132},{3 ,8,197},{2 ,9,0},{3 ,10,41},{3 ,11,162},{3 ,12,57},{3 ,13,36},{3 ,14,115},{2 ,15,0},{3 ,16,242},{3 ,17,165},{3 ,18,0},{2 ,19,200},{3 ,20,113},{3 ,21,108},{3 ,22,1},{11 ,23,26},{8 ,24,54},{15 ,25,64},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,187},{4 ,1,235},{10 ,2,1},{5 ,3,72},{7 ,4,154},{21 ,5,46},{6 ,6,144},{7 ,7,184},{7 ,8,104},{20 ,9,90},{6 ,10,169},{6 ,11,90},{5 ,12,283},{6 ,13,59},{7 ,14,164},{14 ,15,253},{5 ,16,254},{6 ,17,177},{6 ,18,151},{8 ,19,46},{6 ,20,108},{5 ,21,79},{5 ,22,144},{13 ,23,36},{30 ,24,173},{29 ,25,42},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,246},{5 ,1,181},{23 ,2,0},{8 ,3,252},{10 ,4,28},{0 ,0,-1},{25 ,6,0},{10 ,7,267},{10 ,8,234},{38 ,9,0},{9 ,10,93},{9 ,11,134},{8 ,12,41},{9 ,13,45},{10 ,14,201},{26 ,15,277},{8 ,16,98},{9 ,17,132},{9 ,18,76},{18 ,19,144},{9 ,20,209},{8 ,21,15},{8 ,22,230},{37 ,23,0},{32 ,24,162},{31 ,25,19},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,261},{7 ,1,189},{26 ,2,0},{13 ,3,0},{24 ,4,0},{0 ,0,-1},{27 ,6,36},{13 ,7,216},{19 ,8,144},{41 ,9,0},{12 ,10,244},{12 ,11,151},{11 ,12,274},{12 ,13,238},{17 ,14,137},{34 ,15,108},{11 ,16,181},{14 ,17,0},{12 ,18,243},{28 ,19,155},{13 ,20,47},{11 ,21,273},{11 ,22,39},{0 ,0,-1},{42 ,24,35},{43 ,25,270},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,80},{8 ,1,0},{33 ,2,0},{16 ,3,13},{26 ,4,0},{0 ,0,-1},{35 ,6,278},{19 ,7,118},{27 ,8,72},{44 ,9,0},{15 ,10,183},{16 ,11,99},{14 ,12,186},{15 ,13,108},{25 ,14,183},{36 ,15,0},{14 ,16,16},{17 ,17,0},{15 ,18,68},{39 ,19,117},{16 ,20,54},{14 ,21,79},{16 ,22,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,169},{9 ,1,159},{0 ,0,-1},{20 ,3,81},{28 ,4,0},{0 ,0,-1},{45 ,6,0},{25 ,7,0},{40 ,8,144},{0 ,0,-1},{19 ,10,0},{20 ,11,144},{18 ,12,151},{18 ,13,0},{29 ,14,180},{0 ,0,-1},{17 ,16,0},{22 ,17,257},{18 ,18,241},{0 ,0,-1},{21 ,20,9},{17 ,21,162},{20 ,22,228},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,54},{10 ,1,178},{0 ,0,-1},{24 ,3,199},{42 ,4,0},{0 ,0,-1},{0 ,0,-1},{31 ,7,144},{0 ,0,-1},{0 ,0,-1},{23 ,10,0},{24 ,11,266},{22 ,12,189},{22 ,13,72},{32 ,14,36},{0 ,0,-1},{21 ,16,266},{34 ,17,0},{23 ,18,165},{0 ,0,-1},{0 ,0,-1},{21 ,21,18},{24 ,22,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,162},{11 ,1,23},{0 ,0,-1},{39 ,3,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,0},{0 ,0,-1},{0 ,0,-1},{30 ,10,90},{33 ,11,76},{32 ,12,211},{30 ,13,252},{36 ,14,16},{0 ,0,-1},{43 ,16,243},{40 ,17,2},{29 ,18,0},{0 ,0,-1},{0 ,0,-1},{28 ,21,62},{31 ,22,166},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,55},{12 ,1,162},{0 ,0,-1},{41 ,3,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,165},{0 ,0,-1},{0 ,0,-1},{38 ,10,0},{0 ,0,-1},{35 ,12,0},{37 ,13,144},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,0},{0 ,0,-1},{0 ,0,-1},{33 ,21,18},{35 ,22,205},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,225},{15 ,1,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,0},{0 ,0,-1},{0 ,0,-1},{45 ,10,144},{0 ,0,-1},{38 ,12,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,183},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,57},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,231},{16 ,1,270},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,0},{18 ,1,161},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,170},{19 ,1,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,153},{21 ,1,64},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,0},{23 ,1,180},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,265},{25 ,1,205},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,72},{27 ,1,45},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,236},{29 ,1,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,0},{31 ,1,144},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,275},{33 ,1,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,0},{35 ,1,199},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,0},{37 ,1,72},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,197},{39 ,1,153},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,216},{41 ,1,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,190},{43 ,1,52},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,216},{45 ,1,168},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,27},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,18},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + + +//--------------------------------------------------BG1_I4----------------------------------------------------------------- + + +//--------------------------------------------------BG1_I5----------------------------------------------------------------- +h_element host_h_compact1_I5 [46*19] = +{{0 ,0,294},{1 ,0,77},{2 ,0,226},{3 ,0,97},{4 ,0,42},{5 ,0,219},{6 ,0,294},{7 ,0,3},{8 ,0,348},{9 ,0,156},{10 ,1,175},{11 ,0,25},{12 ,0,123},{13 ,0,311},{14 ,0,22},{15 ,0,176},{16 ,1,190},{17 ,0,110},{18 ,1,47},{19 ,0,87},{20 ,0,89},{21 ,1,162},{22 ,0,280},{23 ,1,18},{24 ,0,38},{25 ,1,279},{26 ,0,325},{27 ,1,91},{28 ,0,102},{29 ,1,273},{30 ,0,171},{31 ,1,101},{32 ,0,351},{33 ,1,56},{34 ,0,60},{35 ,1,100},{36 ,0,135},{37 ,1,319},{38 ,0,164},{39 ,1,236},{40 ,0,304},{41 ,1,123},{42 ,0,288},{43 ,1,210},{44 ,0,79},{45 ,1,82}, +{0 ,1,118},{1 ,2,225},{2 ,1,35},{3 ,1,94},{4 ,1,256},{5 ,1,130},{6 ,6,73},{7 ,1,103},{8 ,1,75},{9 ,1,88},{10 ,2,253},{11 ,1,322},{12 ,1,217},{13 ,3,251},{14 ,12,322},{15 ,1,348},{16 ,3,293},{17 ,14,228},{18 ,12,286},{19 ,1,110},{20 ,3,65},{21 ,5,264},{22 ,12,157},{23 ,2,6},{24 ,3,170},{25 ,6,255},{26 ,2,326},{27 ,6,326},{28 ,4,1},{29 ,14,104},{30 ,10,16},{31 ,7,297},{32 ,12,265},{33 ,2,304},{34 ,7,320},{35 ,6,210},{36 ,14,15},{37 ,13,236},{38 ,9,196},{39 ,3,264},{40 ,8,237},{41 ,3,77},{42 ,4,83},{43 ,16,3},{44 ,7,244},{45 ,6,67}, +{0 ,2,167},{1 ,3,96},{2 ,2,213},{3 ,3,49},{4 ,26,0},{5 ,3,251},{6 ,10,330},{7 ,4,224},{8 ,3,22},{9 ,10,293},{10 ,4,27},{11 ,12,200},{12 ,10,142},{13 ,7,265},{14 ,15,277},{15 ,10,15},{16 ,11,332},{17 ,16,247},{18 ,13,246},{19 ,7,147},{20 ,9,155},{21 ,16,346},{22 ,13,236},{23 ,10,181},{24 ,4,249},{25 ,7,111},{26 ,4,226},{27 ,8,268},{28 ,19,40},{29 ,18,243},{30 ,13,95},{31 ,22,279},{32 ,14,338},{33 ,11,141},{34 ,15,112},{35 ,12,195},{36 ,15,35},{37 ,23,85},{38 ,10,209},{39 ,7,37},{40 ,17,135},{41 ,9,25},{42 ,24,17},{43 ,18,53},{44 ,9,293},{45 ,10,235}, +{0 ,3,330},{1 ,4,338},{2 ,4,302},{3 ,4,279},{0 ,0,-1},{5 ,12,322},{6 ,11,99},{7 ,7,297},{8 ,12,312},{9 ,11,111},{10 ,7,231},{11 ,16,351},{12 ,11,110},{13 ,20,94},{14 ,16,156},{15 ,13,81},{16 ,20,331},{17 ,17,116},{18 ,18,181},{19 ,8,258},{20 ,11,244},{21 ,20,143},{22 ,17,113},{23 ,18,304},{24 ,11,288},{25 ,14,54},{26 ,15,99},{27 ,49,0},{28 ,21,167},{29 ,25,107},{30 ,24,212},{31 ,25,222},{32 ,24,83},{33 ,21,101},{34 ,17,54},{35 ,22,268},{36 ,18,188},{37 ,59,0},{38 ,12,246},{39 ,19,272},{40 ,62,0},{41 ,18,272},{42 ,64,0},{43 ,25,167},{44 ,22,272},{45 ,67,0}, +{0 ,5,207},{1 ,5,268},{2 ,5,111},{3 ,6,139},{0 ,0,-1},{5 ,16,295},{6 ,13,172},{7 ,8,215},{8 ,16,224},{9 ,13,92},{10 ,8,49},{11 ,21,166},{12 ,13,176},{13 ,23,81},{14 ,17,66},{15 ,18,176},{16 ,22,114},{17 ,21,190},{18 ,19,73},{19 ,10,204},{20 ,22,30},{21 ,21,109},{22 ,44,0},{23 ,45,0},{24 ,22,194},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,165},{1 ,7,112},{2 ,6,265},{3 ,7,166},{0 ,0,-1},{5 ,21,258},{6 ,17,150},{7 ,14,39},{8 ,19,17},{9 ,17,152},{10 ,14,267},{11 ,22,338},{12 ,18,76},{13 ,35,0},{14 ,21,78},{15 ,25,113},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,243},{1 ,8,302},{2 ,7,128},{3 ,8,91},{0 ,0,-1},{5 ,22,283},{6 ,18,284},{7 ,29,0},{8 ,21,59},{9 ,18,23},{10 ,32,0},{11 ,23,192},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,250},{1 ,9,50},{2 ,8,237},{3 ,10,106},{0 ,0,-1},{5 ,27,0},{6 ,20,305},{0 ,0,-1},{8 ,22,314},{9 ,20,337},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,1},{1 ,11,167},{2 ,9,294},{3 ,11,246},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,244},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,339},{1 ,12,253},{2 ,10,127},{3 ,12,345},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,201},{1 ,14,334},{2 ,13,110},{3 ,13,269},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,53},{1 ,15,242},{2 ,14,286},{3 ,14,185},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,347},{1 ,16,257},{2 ,15,125},{3 ,16,249},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,304},{1 ,17,133},{2 ,17,131},{3 ,17,215},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,167},{1 ,19,9},{2 ,18,163},{3 ,18,143},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,47},{1 ,21,302},{2 ,19,210},{3 ,20,121},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,188},{1 ,22,0},{2 ,20,7},{3 ,21,121},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,1},{1 ,23,0},{2 ,24,0},{3 ,22,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +}; + + +h_element host_h_compact2_I5 [68*30] = +{{0 ,0,294},{0 ,1,118},{0 ,2,167},{0 ,3,330},{1 ,4,338},{0 ,5,207},{0 ,6,165},{1 ,7,112},{1 ,8,302},{0 ,9,243},{0 ,10,250},{0 ,11,1},{0 ,12,339},{0 ,13,201},{1 ,14,334},{0 ,15,53},{0 ,16,347},{1 ,17,133},{0 ,18,304},{0 ,19,167},{0 ,20,47},{0 ,21,188},{0 ,22,1},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,77},{2 ,1,35},{1 ,2,225},{1 ,3,96},{2 ,4,302},{1 ,5,268},{2 ,6,265},{2 ,7,128},{2 ,8,237},{1 ,9,50},{2 ,10,127},{1 ,11,167},{1 ,12,253},{2 ,13,110},{2 ,14,286},{1 ,15,242},{1 ,16,257},{2 ,17,131},{2 ,18,163},{1 ,19,9},{2 ,20,7},{1 ,21,302},{1 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,226},{3 ,1,94},{2 ,2,213},{3 ,3,49},{3 ,4,279},{2 ,5,111},{3 ,6,139},{3 ,7,166},{3 ,8,91},{2 ,9,294},{3 ,10,106},{3 ,11,246},{3 ,12,345},{3 ,13,269},{3 ,14,185},{2 ,15,125},{3 ,16,249},{3 ,17,215},{3 ,18,143},{2 ,19,210},{3 ,20,121},{3 ,21,121},{3 ,22,1},{11 ,23,192},{8 ,24,244},{15 ,25,113},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,97},{4 ,1,256},{10 ,2,253},{5 ,3,251},{7 ,4,224},{21 ,5,264},{6 ,6,73},{7 ,7,297},{7 ,8,215},{20 ,9,155},{6 ,10,330},{6 ,11,99},{5 ,12,322},{6 ,13,172},{7 ,14,39},{14 ,15,277},{5 ,16,295},{6 ,17,150},{6 ,18,284},{8 ,19,17},{6 ,20,305},{5 ,21,258},{5 ,22,283},{13 ,23,81},{30 ,24,212},{29 ,25,107},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,42},{5 ,1,130},{23 ,2,6},{8 ,3,22},{10 ,4,27},{0 ,0,-1},{25 ,6,255},{10 ,7,231},{10 ,8,49},{38 ,9,196},{9 ,10,293},{9 ,11,111},{8 ,12,312},{9 ,13,92},{10 ,14,267},{26 ,15,99},{8 ,16,224},{9 ,17,152},{9 ,18,23},{18 ,19,73},{9 ,20,337},{8 ,21,59},{8 ,22,314},{37 ,23,85},{32 ,24,83},{31 ,25,222},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,219},{7 ,1,103},{26 ,2,326},{13 ,3,251},{24 ,4,249},{0 ,0,-1},{27 ,6,326},{13 ,7,265},{19 ,8,258},{41 ,9,25},{12 ,10,142},{12 ,11,110},{11 ,12,200},{12 ,13,176},{17 ,14,228},{34 ,15,112},{11 ,16,351},{14 ,17,66},{12 ,18,76},{28 ,19,40},{13 ,20,94},{11 ,21,166},{11 ,22,338},{0 ,0,-1},{42 ,24,17},{43 ,25,167},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,294},{8 ,1,75},{33 ,2,304},{16 ,3,293},{26 ,4,226},{0 ,0,-1},{35 ,6,210},{19 ,7,147},{27 ,8,268},{44 ,9,293},{15 ,10,15},{16 ,11,332},{14 ,12,322},{15 ,13,81},{25 ,14,54},{36 ,15,35},{14 ,16,156},{17 ,17,116},{15 ,18,176},{39 ,19,272},{16 ,20,331},{14 ,21,78},{16 ,22,114},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,3},{9 ,1,88},{0 ,0,-1},{20 ,3,65},{28 ,4,1},{0 ,0,-1},{45 ,6,67},{25 ,7,111},{40 ,8,237},{0 ,0,-1},{19 ,10,204},{20 ,11,244},{18 ,12,286},{18 ,13,246},{29 ,14,104},{0 ,0,-1},{17 ,16,247},{22 ,17,113},{18 ,18,181},{0 ,0,-1},{21 ,20,143},{17 ,21,190},{20 ,22,30},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,348},{10 ,1,175},{0 ,0,-1},{24 ,3,170},{42 ,4,83},{0 ,0,-1},{0 ,0,-1},{31 ,7,297},{0 ,0,-1},{0 ,0,-1},{23 ,10,181},{24 ,11,288},{22 ,12,157},{22 ,13,236},{32 ,14,338},{0 ,0,-1},{21 ,16,346},{34 ,17,54},{23 ,18,304},{0 ,0,-1},{0 ,0,-1},{21 ,21,109},{24 ,22,194},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,156},{11 ,1,322},{0 ,0,-1},{39 ,3,264},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,320},{0 ,0,-1},{0 ,0,-1},{30 ,10,16},{33 ,11,141},{32 ,12,265},{30 ,13,95},{36 ,14,15},{0 ,0,-1},{43 ,16,3},{40 ,17,135},{29 ,18,243},{0 ,0,-1},{0 ,0,-1},{28 ,21,167},{31 ,22,279},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,25},{12 ,1,217},{0 ,0,-1},{41 ,3,77},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,37},{0 ,0,-1},{0 ,0,-1},{38 ,10,209},{0 ,0,-1},{35 ,12,195},{37 ,13,236},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,188},{0 ,0,-1},{0 ,0,-1},{33 ,21,101},{35 ,22,268},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,123},{15 ,1,348},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,244},{0 ,0,-1},{0 ,0,-1},{45 ,10,235},{0 ,0,-1},{38 ,12,246},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,272},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,272},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,311},{16 ,1,190},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,53},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,22},{18 ,1,47},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,176},{19 ,1,110},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,110},{21 ,1,162},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,87},{23 ,1,18},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,89},{25 ,1,279},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,280},{27 ,1,91},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,38},{29 ,1,273},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,325},{31 ,1,101},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,102},{33 ,1,56},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,171},{35 ,1,100},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,351},{37 ,1,319},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,60},{39 ,1,236},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,135},{41 ,1,123},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,164},{43 ,1,210},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,304},{45 ,1,82},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,288},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,79},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; +//--------------------------------------------------BG1_I5----------------------------------------------------------------- + + +//--------------------------------------------------BG1_I6----------------------------------------------------------------- +h_element host_h_compact1_I6 [46*19] = +{{0 ,0,0},{1 ,0,22},{2 ,0,132},{3 ,0,4},{4 ,0,24},{5 ,0,185},{6 ,0,6},{7 ,0,145},{8 ,0,172},{9 ,0,6},{10 ,1,126},{11 ,0,184},{12 ,0,6},{13 ,0,52},{14 ,0,1},{15 ,0,173},{16 ,1,88},{17 ,0,91},{18 ,1,1},{19 ,0,12},{20 ,0,6},{21 ,1,6},{22 ,0,44},{23 ,1,45},{24 ,0,9},{25 ,1,4},{26 ,0,21},{27 ,1,98},{28 ,0,4},{29 ,1,92},{30 ,0,2},{31 ,1,4},{32 ,0,6},{33 ,1,10},{34 ,0,4},{35 ,1,4},{36 ,0,6},{37 ,1,82},{38 ,0,91},{39 ,1,4},{40 ,0,10},{41 ,1,2},{42 ,0,163},{43 ,1,1},{44 ,0,4},{45 ,1,181}, +{0 ,1,0},{1 ,2,11},{2 ,1,37},{3 ,1,6},{4 ,1,204},{5 ,1,100},{6 ,6,27},{7 ,1,88},{8 ,1,2},{9 ,1,10},{10 ,2,77},{11 ,1,194},{12 ,1,20},{13 ,3,147},{14 ,12,202},{15 ,1,6},{16 ,3,198},{17 ,14,184},{18 ,12,41},{19 ,1,6},{20 ,3,12},{21 ,5,86},{22 ,12,58},{23 ,2,18},{24 ,3,125},{25 ,6,74},{26 ,2,142},{27 ,6,140},{28 ,4,1},{29 ,14,136},{30 ,10,88},{31 ,7,49},{32 ,12,126},{33 ,2,30},{34 ,7,153},{35 ,6,45},{36 ,14,200},{37 ,13,2},{38 ,9,64},{39 ,3,28},{40 ,8,84},{41 ,3,75},{42 ,4,10},{43 ,16,163},{44 ,7,6},{45 ,6,45}, +{0 ,2,0},{1 ,3,124},{2 ,2,21},{3 ,3,33},{4 ,26,0},{5 ,3,24},{6 ,10,163},{7 ,4,112},{8 ,3,131},{9 ,10,145},{10 ,4,156},{11 ,12,123},{12 ,10,203},{13 ,7,1},{14 ,15,118},{15 ,10,81},{16 ,11,160},{17 ,16,30},{18 ,13,167},{19 ,7,166},{20 ,9,15},{21 ,16,96},{22 ,13,130},{23 ,10,132},{24 ,4,191},{25 ,7,16},{26 ,4,192},{27 ,8,22},{28 ,19,40},{29 ,18,106},{30 ,13,112},{31 ,22,125},{32 ,14,63},{33 ,11,6},{34 ,15,197},{35 ,12,168},{36 ,15,177},{37 ,23,135},{38 ,10,198},{39 ,7,109},{40 ,17,12},{41 ,9,142},{42 ,24,162},{43 ,18,99},{44 ,9,142},{45 ,10,153}, +{0 ,3,0},{1 ,4,0},{2 ,4,180},{3 ,4,113},{0 ,0,-1},{5 ,12,65},{6 ,11,50},{7 ,7,153},{8 ,12,141},{9 ,11,53},{10 ,7,16},{11 ,16,16},{12 ,11,153},{13 ,20,16},{14 ,16,130},{15 ,13,182},{16 ,20,122},{17 ,17,3},{18 ,18,68},{19 ,8,184},{20 ,11,5},{21 ,20,42},{22 ,17,131},{23 ,18,100},{24 ,11,28},{25 ,14,28},{26 ,15,197},{27 ,49,0},{28 ,21,93},{29 ,25,6},{30 ,24,20},{31 ,25,194},{32 ,24,20},{33 ,21,92},{34 ,17,155},{35 ,22,185},{36 ,18,43},{37 ,59,0},{38 ,12,100},{39 ,19,188},{40 ,62,0},{41 ,18,128},{42 ,64,0},{43 ,25,98},{44 ,22,3},{45 ,67,0}, +{0 ,5,0},{1 ,5,10},{2 ,5,4},{3 ,6,49},{0 ,0,-1},{5 ,16,207},{6 ,13,48},{7 ,8,159},{8 ,16,96},{9 ,13,201},{10 ,8,12},{11 ,21,104},{12 ,13,104},{13 ,23,46},{14 ,17,1},{15 ,18,53},{16 ,22,182},{17 ,21,155},{18 ,19,148},{19 ,10,191},{20 ,22,30},{21 ,21,199},{22 ,44,0},{23 ,45,0},{24 ,22,6},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,0},{1 ,7,0},{2 ,6,149},{3 ,7,21},{0 ,0,-1},{5 ,21,161},{6 ,17,24},{7 ,14,76},{8 ,19,99},{9 ,17,4},{10 ,14,70},{11 ,22,109},{12 ,18,207},{13 ,35,0},{14 ,21,2},{15 ,25,46},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,0},{1 ,8,0},{2 ,7,48},{3 ,8,6},{0 ,0,-1},{5 ,22,72},{6 ,18,38},{7 ,29,0},{8 ,21,101},{9 ,18,164},{10 ,32,0},{11 ,23,124},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,0},{1 ,9,2},{2 ,8,38},{3 ,10,151},{0 ,0,-1},{5 ,27,0},{6 ,20,91},{0 ,0,-1},{8 ,22,35},{9 ,20,173},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,0},{1 ,11,16},{2 ,9,122},{3 ,11,83},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,116},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,0},{1 ,12,60},{2 ,10,195},{3 ,12,154},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,0},{1 ,14,0},{2 ,13,155},{3 ,13,87},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,0},{1 ,15,6},{2 ,14,28},{3 ,14,5},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,0},{1 ,16,30},{2 ,15,85},{3 ,16,92},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,0},{1 ,17,0},{2 ,17,47},{3 ,17,173},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,0},{1 ,19,168},{2 ,18,179},{3 ,18,120},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,0},{1 ,21,31},{2 ,19,42},{3 ,20,2},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,0},{1 ,22,105},{2 ,20,66},{3 ,21,142},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,22,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +}; + + +h_element host_h_compact2_I6 [68*30] = +{{0 ,0,0},{0 ,1,0},{0 ,2,0},{0 ,3,0},{1 ,4,0},{0 ,5,0},{0 ,6,0},{1 ,7,0},{1 ,8,0},{0 ,9,0},{0 ,10,0},{0 ,11,0},{0 ,12,0},{0 ,13,0},{1 ,14,0},{0 ,15,0},{0 ,16,0},{1 ,17,0},{0 ,18,0},{0 ,19,0},{0 ,20,0},{0 ,21,0},{0 ,22,0},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,22},{2 ,1,37},{1 ,2,11},{1 ,3,124},{2 ,4,180},{1 ,5,10},{2 ,6,149},{2 ,7,48},{2 ,8,38},{1 ,9,2},{2 ,10,195},{1 ,11,16},{1 ,12,60},{2 ,13,155},{2 ,14,28},{1 ,15,6},{1 ,16,30},{2 ,17,47},{2 ,18,179},{1 ,19,168},{2 ,20,66},{1 ,21,31},{1 ,22,105},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,132},{3 ,1,6},{2 ,2,21},{3 ,3,33},{3 ,4,113},{2 ,5,4},{3 ,6,49},{3 ,7,21},{3 ,8,6},{2 ,9,122},{3 ,10,151},{3 ,11,83},{3 ,12,154},{3 ,13,87},{3 ,14,5},{2 ,15,85},{3 ,16,92},{3 ,17,173},{3 ,18,120},{2 ,19,42},{3 ,20,2},{3 ,21,142},{3 ,22,0},{11 ,23,124},{8 ,24,116},{15 ,25,46},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,4},{4 ,1,204},{10 ,2,77},{5 ,3,24},{7 ,4,112},{21 ,5,86},{6 ,6,27},{7 ,7,153},{7 ,8,159},{20 ,9,15},{6 ,10,163},{6 ,11,50},{5 ,12,65},{6 ,13,48},{7 ,14,76},{14 ,15,118},{5 ,16,207},{6 ,17,24},{6 ,18,38},{8 ,19,99},{6 ,20,91},{5 ,21,161},{5 ,22,72},{13 ,23,46},{30 ,24,20},{29 ,25,6},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,24},{5 ,1,100},{23 ,2,18},{8 ,3,131},{10 ,4,156},{0 ,0,-1},{25 ,6,74},{10 ,7,16},{10 ,8,12},{38 ,9,64},{9 ,10,145},{9 ,11,53},{8 ,12,141},{9 ,13,201},{10 ,14,70},{26 ,15,197},{8 ,16,96},{9 ,17,4},{9 ,18,164},{18 ,19,148},{9 ,20,173},{8 ,21,101},{8 ,22,35},{37 ,23,135},{32 ,24,20},{31 ,25,194},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,185},{7 ,1,88},{26 ,2,142},{13 ,3,147},{24 ,4,191},{0 ,0,-1},{27 ,6,140},{13 ,7,1},{19 ,8,184},{41 ,9,142},{12 ,10,203},{12 ,11,153},{11 ,12,123},{12 ,13,104},{17 ,14,184},{34 ,15,197},{11 ,16,16},{14 ,17,1},{12 ,18,207},{28 ,19,40},{13 ,20,16},{11 ,21,104},{11 ,22,109},{0 ,0,-1},{42 ,24,162},{43 ,25,98},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,6},{8 ,1,2},{33 ,2,30},{16 ,3,198},{26 ,4,192},{0 ,0,-1},{35 ,6,45},{19 ,7,166},{27 ,8,22},{44 ,9,142},{15 ,10,81},{16 ,11,160},{14 ,12,202},{15 ,13,182},{25 ,14,28},{36 ,15,177},{14 ,16,130},{17 ,17,3},{15 ,18,53},{39 ,19,188},{16 ,20,122},{14 ,21,2},{16 ,22,182},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,145},{9 ,1,10},{0 ,0,-1},{20 ,3,12},{28 ,4,1},{0 ,0,-1},{45 ,6,45},{25 ,7,16},{40 ,8,84},{0 ,0,-1},{19 ,10,191},{20 ,11,5},{18 ,12,41},{18 ,13,167},{29 ,14,136},{0 ,0,-1},{17 ,16,30},{22 ,17,131},{18 ,18,68},{0 ,0,-1},{21 ,20,42},{17 ,21,155},{20 ,22,30},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,172},{10 ,1,126},{0 ,0,-1},{24 ,3,125},{42 ,4,10},{0 ,0,-1},{0 ,0,-1},{31 ,7,49},{0 ,0,-1},{0 ,0,-1},{23 ,10,132},{24 ,11,28},{22 ,12,58},{22 ,13,130},{32 ,14,63},{0 ,0,-1},{21 ,16,96},{34 ,17,155},{23 ,18,100},{0 ,0,-1},{0 ,0,-1},{21 ,21,199},{24 ,22,6},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,6},{11 ,1,194},{0 ,0,-1},{39 ,3,28},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,153},{0 ,0,-1},{0 ,0,-1},{30 ,10,88},{33 ,11,6},{32 ,12,126},{30 ,13,112},{36 ,14,200},{0 ,0,-1},{43 ,16,163},{40 ,17,12},{29 ,18,106},{0 ,0,-1},{0 ,0,-1},{28 ,21,93},{31 ,22,125},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,184},{12 ,1,20},{0 ,0,-1},{41 ,3,75},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,109},{0 ,0,-1},{0 ,0,-1},{38 ,10,198},{0 ,0,-1},{35 ,12,168},{37 ,13,2},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,43},{0 ,0,-1},{0 ,0,-1},{33 ,21,92},{35 ,22,185},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,6},{15 ,1,6},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,6},{0 ,0,-1},{0 ,0,-1},{45 ,10,153},{0 ,0,-1},{38 ,12,100},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,128},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,3},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,52},{16 ,1,88},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,99},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,1},{18 ,1,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,173},{19 ,1,6},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,91},{21 ,1,6},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,12},{23 ,1,45},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,6},{25 ,1,4},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,44},{27 ,1,98},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,9},{29 ,1,92},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,21},{31 ,1,4},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,4},{33 ,1,10},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,2},{35 ,1,4},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,6},{37 ,1,82},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,4},{39 ,1,4},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,6},{41 ,1,2},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,91},{43 ,1,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,10},{45 ,1,181},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,163},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,4},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; + +//--------------------------------------------------BG1_I6----------------------------------------------------------------- + + +//--------------------------------------------------BG1_I7----------------------------------------------------------------- +h_element host_h_compact1_I7 [46*19] = +{{0 ,0,135},{1 ,0,96},{2 ,0,189},{3 ,0,128},{4 ,0,64},{5 ,0,2},{6 ,0,199},{7 ,0,77},{8 ,0,181},{9 ,0,169},{10 ,1,116},{11 ,0,45},{12 ,0,186},{13 ,0,220},{14 ,0,124},{15 ,0,39},{16 ,1,78},{17 ,0,183},{18 ,1,183},{19 ,0,179},{20 ,0,77},{21 ,1,197},{22 ,0,25},{23 ,1,185},{24 ,0,32},{25 ,1,27},{26 ,0,163},{27 ,1,165},{28 ,0,32},{29 ,1,232},{30 ,0,170},{31 ,1,73},{32 ,0,103},{33 ,1,199},{34 ,0,161},{35 ,1,231},{36 ,0,11},{37 ,1,59},{38 ,0,121},{39 ,1,115},{40 ,0,4},{41 ,1,53},{42 ,0,222},{43 ,1,22},{44 ,0,191},{45 ,1,177}, +{0 ,1,227},{1 ,2,236},{2 ,1,4},{3 ,1,23},{4 ,1,211},{5 ,1,171},{6 ,6,22},{7 ,1,146},{8 ,1,105},{9 ,1,12},{10 ,2,151},{11 ,1,115},{12 ,1,215},{13 ,3,185},{14 ,12,144},{15 ,1,138},{16 ,3,152},{17 ,14,112},{18 ,12,215},{19 ,1,108},{20 ,3,187},{21 ,5,122},{22 ,12,47},{23 ,2,127},{24 ,3,178},{25 ,6,141},{26 ,2,131},{27 ,6,232},{28 ,4,43},{29 ,14,32},{30 ,10,199},{31 ,7,149},{32 ,12,110},{33 ,2,132},{34 ,7,237},{35 ,6,174},{36 ,14,207},{37 ,13,204},{38 ,9,90},{39 ,3,188},{40 ,8,103},{41 ,3,189},{42 ,4,170},{43 ,16,127},{44 ,7,211},{45 ,6,114}, +{0 ,2,126},{1 ,3,136},{2 ,2,225},{3 ,3,162},{4 ,26,0},{5 ,3,47},{6 ,10,23},{7 ,4,209},{8 ,3,141},{9 ,10,206},{10 ,4,70},{11 ,12,134},{12 ,10,124},{13 ,7,154},{14 ,15,182},{15 ,10,220},{16 ,11,84},{17 ,16,106},{18 ,13,180},{19 ,7,159},{20 ,9,203},{21 ,16,215},{22 ,13,126},{23 ,10,117},{24 ,4,2},{25 ,7,11},{26 ,4,169},{27 ,8,9},{28 ,19,200},{29 ,18,118},{30 ,13,26},{31 ,22,175},{32 ,14,151},{33 ,11,172},{34 ,15,142},{35 ,12,145},{36 ,15,42},{37 ,23,161},{38 ,10,26},{39 ,7,168},{40 ,17,30},{41 ,9,215},{42 ,24,71},{43 ,18,49},{44 ,9,187},{45 ,10,93}, +{0 ,3,134},{1 ,4,221},{2 ,4,151},{3 ,4,220},{0 ,0,-1},{5 ,12,143},{6 ,11,100},{7 ,7,32},{8 ,12,223},{9 ,11,221},{10 ,7,230},{11 ,16,1},{12 ,11,180},{13 ,20,178},{14 ,16,95},{15 ,13,173},{16 ,20,5},{17 ,17,219},{18 ,18,143},{19 ,8,138},{20 ,11,167},{21 ,20,65},{22 ,17,178},{23 ,18,199},{24 ,11,156},{25 ,14,181},{26 ,15,98},{27 ,49,0},{28 ,21,205},{29 ,25,103},{30 ,24,105},{31 ,25,108},{32 ,24,211},{33 ,21,65},{34 ,17,180},{35 ,22,100},{36 ,18,100},{37 ,59,0},{38 ,12,140},{39 ,19,52},{40 ,62,0},{41 ,18,24},{42 ,64,0},{43 ,25,125},{44 ,22,148},{45 ,67,0}, +{0 ,5,84},{1 ,5,128},{2 ,5,236},{3 ,6,43},{0 ,0,-1},{5 ,16,210},{6 ,13,92},{7 ,8,166},{8 ,16,177},{9 ,13,17},{10 ,8,115},{11 ,21,152},{12 ,13,98},{13 ,23,150},{14 ,17,72},{15 ,18,142},{16 ,22,205},{17 ,21,129},{18 ,19,14},{19 ,10,196},{20 ,22,130},{21 ,21,216},{22 ,44,0},{23 ,45,0},{24 ,22,58},{25 ,47,0},{26 ,48,0},{0 ,0,-1},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{0 ,0,-1},{38 ,60,0},{39 ,61,0},{0 ,0,-1},{41 ,63,0},{0 ,0,-1},{43 ,65,0},{44 ,66,0},{0 ,0,-1}, +{0 ,6,83},{1 ,7,92},{2 ,6,117},{3 ,7,186},{0 ,0,-1},{5 ,21,180},{6 ,17,207},{7 ,14,18},{8 ,19,145},{9 ,17,212},{10 ,14,84},{11 ,22,165},{12 ,18,80},{13 ,35,0},{14 ,21,76},{15 ,25,49},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{0 ,0,-1},{0 ,0,-1},{24 ,46,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,9,53},{1 ,8,172},{2 ,7,179},{3 ,8,96},{0 ,0,-1},{5 ,22,180},{6 ,18,52},{7 ,29,0},{8 ,21,199},{9 ,18,92},{10 ,32,0},{11 ,23,107},{12 ,34,0},{0 ,0,-1},{14 ,36,0},{15 ,37,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,10,225},{1 ,9,56},{2 ,8,92},{3 ,10,1},{0 ,0,-1},{5 ,27,0},{6 ,20,13},{0 ,0,-1},{8 ,22,153},{9 ,20,205},{0 ,0,-1},{11 ,33,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,11,205},{1 ,11,11},{2 ,9,24},{3 ,11,216},{0 ,0,-1},{0 ,0,-1},{6 ,28,0},{0 ,0,-1},{8 ,24,38},{9 ,31,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,12,128},{1 ,12,189},{2 ,10,68},{3 ,12,22},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{8 ,30,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,13,75},{1 ,14,95},{2 ,13,6},{3 ,13,24},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,15,135},{1 ,15,85},{2 ,14,101},{3 ,14,167},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,16,217},{1 ,16,153},{2 ,15,33},{3 ,16,200},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,18,220},{1 ,17,87},{2 ,17,96},{3 ,17,32},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,19,90},{1 ,19,163},{2 ,18,125},{3 ,18,235},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,20,105},{1 ,21,216},{2 ,19,67},{3 ,20,172},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,21,137},{1 ,22,0},{2 ,20,230},{3 ,21,219},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,22,1},{1 ,23,0},{2 ,24,0},{3 ,22,1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{0 ,23,0},{1 ,24,0},{2 ,25,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +}; + + +h_element host_h_compact2_I7 [68*30] = +{{0 ,0,135},{0 ,1,227},{0 ,2,126},{0 ,3,134},{1 ,4,221},{0 ,5,84},{0 ,6,83},{1 ,7,92},{1 ,8,172},{0 ,9,53},{0 ,10,225},{0 ,11,205},{0 ,12,128},{0 ,13,75},{1 ,14,95},{0 ,15,135},{0 ,16,217},{1 ,17,87},{0 ,18,220},{0 ,19,90},{0 ,20,105},{0 ,21,137},{0 ,22,1},{0 ,23,0},{1 ,24,0},{2 ,25,0},{4 ,26,0},{5 ,27,0},{6 ,28,0},{7 ,29,0},{8 ,30,0},{9 ,31,0},{10 ,32,0},{11 ,33,0},{12 ,34,0},{13 ,35,0},{14 ,36,0},{15 ,37,0},{16 ,38,0},{17 ,39,0},{18 ,40,0},{19 ,41,0},{20 ,42,0},{21 ,43,0},{22 ,44,0},{23 ,45,0},{24 ,46,0},{25 ,47,0},{26 ,48,0},{27 ,49,0},{28 ,50,0},{29 ,51,0},{30 ,52,0},{31 ,53,0},{32 ,54,0},{33 ,55,0},{34 ,56,0},{35 ,57,0},{36 ,58,0},{37 ,59,0},{38 ,60,0},{39 ,61,0},{40 ,62,0},{41 ,63,0},{42 ,64,0},{43 ,65,0},{44 ,66,0},{45 ,67,0}, +{1 ,0,96},{2 ,1,4},{1 ,2,236},{1 ,3,136},{2 ,4,151},{1 ,5,128},{2 ,6,117},{2 ,7,179},{2 ,8,92},{1 ,9,56},{2 ,10,68},{1 ,11,11},{1 ,12,189},{2 ,13,6},{2 ,14,101},{1 ,15,85},{1 ,16,153},{2 ,17,96},{2 ,18,125},{1 ,19,163},{2 ,20,230},{1 ,21,216},{1 ,22,0},{1 ,23,0},{2 ,24,0},{3 ,25,0},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{2 ,0,189},{3 ,1,23},{2 ,2,225},{3 ,3,162},{3 ,4,220},{2 ,5,236},{3 ,6,43},{3 ,7,186},{3 ,8,96},{2 ,9,24},{3 ,10,1},{3 ,11,216},{3 ,12,22},{3 ,13,24},{3 ,14,167},{2 ,15,33},{3 ,16,200},{3 ,17,32},{3 ,18,235},{2 ,19,67},{3 ,20,172},{3 ,21,219},{3 ,22,1},{11 ,23,107},{8 ,24,38},{15 ,25,49},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{3 ,0,128},{4 ,1,211},{10 ,2,151},{5 ,3,47},{7 ,4,209},{21 ,5,122},{6 ,6,22},{7 ,7,32},{7 ,8,166},{20 ,9,203},{6 ,10,23},{6 ,11,100},{5 ,12,143},{6 ,13,92},{7 ,14,18},{14 ,15,182},{5 ,16,210},{6 ,17,207},{6 ,18,52},{8 ,19,145},{6 ,20,13},{5 ,21,180},{5 ,22,180},{13 ,23,150},{30 ,24,105},{29 ,25,103},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{4 ,0,64},{5 ,1,171},{23 ,2,127},{8 ,3,141},{10 ,4,70},{0 ,0,-1},{25 ,6,141},{10 ,7,230},{10 ,8,115},{38 ,9,90},{9 ,10,206},{9 ,11,221},{8 ,12,223},{9 ,13,17},{10 ,14,84},{26 ,15,98},{8 ,16,177},{9 ,17,212},{9 ,18,92},{18 ,19,14},{9 ,20,205},{8 ,21,199},{8 ,22,153},{37 ,23,161},{32 ,24,211},{31 ,25,108},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{5 ,0,2},{7 ,1,146},{26 ,2,131},{13 ,3,185},{24 ,4,2},{0 ,0,-1},{27 ,6,232},{13 ,7,154},{19 ,8,138},{41 ,9,215},{12 ,10,124},{12 ,11,180},{11 ,12,134},{12 ,13,98},{17 ,14,112},{34 ,15,142},{11 ,16,1},{14 ,17,72},{12 ,18,80},{28 ,19,200},{13 ,20,178},{11 ,21,152},{11 ,22,165},{0 ,0,-1},{42 ,24,71},{43 ,25,125},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{6 ,0,199},{8 ,1,105},{33 ,2,132},{16 ,3,152},{26 ,4,169},{0 ,0,-1},{35 ,6,174},{19 ,7,159},{27 ,8,9},{44 ,9,187},{15 ,10,220},{16 ,11,84},{14 ,12,144},{15 ,13,173},{25 ,14,181},{36 ,15,42},{14 ,16,95},{17 ,17,219},{15 ,18,142},{39 ,19,52},{16 ,20,5},{14 ,21,76},{16 ,22,205},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{7 ,0,77},{9 ,1,12},{0 ,0,-1},{20 ,3,187},{28 ,4,43},{0 ,0,-1},{45 ,6,114},{25 ,7,11},{40 ,8,103},{0 ,0,-1},{19 ,10,196},{20 ,11,167},{18 ,12,215},{18 ,13,180},{29 ,14,32},{0 ,0,-1},{17 ,16,106},{22 ,17,178},{18 ,18,143},{0 ,0,-1},{21 ,20,65},{17 ,21,129},{20 ,22,130},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{8 ,0,181},{10 ,1,116},{0 ,0,-1},{24 ,3,178},{42 ,4,170},{0 ,0,-1},{0 ,0,-1},{31 ,7,149},{0 ,0,-1},{0 ,0,-1},{23 ,10,117},{24 ,11,156},{22 ,12,47},{22 ,13,126},{32 ,14,151},{0 ,0,-1},{21 ,16,215},{34 ,17,180},{23 ,18,199},{0 ,0,-1},{0 ,0,-1},{21 ,21,216},{24 ,22,58},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{9 ,0,169},{11 ,1,115},{0 ,0,-1},{39 ,3,188},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{34 ,7,237},{0 ,0,-1},{0 ,0,-1},{30 ,10,199},{33 ,11,172},{32 ,12,110},{30 ,13,26},{36 ,14,207},{0 ,0,-1},{43 ,16,127},{40 ,17,30},{29 ,18,118},{0 ,0,-1},{0 ,0,-1},{28 ,21,205},{31 ,22,175},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{11 ,0,45},{12 ,1,215},{0 ,0,-1},{41 ,3,189},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{39 ,7,168},{0 ,0,-1},{0 ,0,-1},{38 ,10,26},{0 ,0,-1},{35 ,12,145},{37 ,13,204},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{36 ,18,100},{0 ,0,-1},{0 ,0,-1},{33 ,21,65},{35 ,22,100},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{12 ,0,186},{15 ,1,138},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,7,211},{0 ,0,-1},{0 ,0,-1},{45 ,10,93},{0 ,0,-1},{38 ,12,140},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{41 ,18,24},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{44 ,22,148},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{13 ,0,220},{16 ,1,78},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{43 ,18,49},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{14 ,0,124},{18 ,1,183},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{15 ,0,39},{19 ,1,108},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{17 ,0,183},{21 ,1,197},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{19 ,0,179},{23 ,1,185},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{20 ,0,77},{25 ,1,27},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{22 ,0,25},{27 ,1,165},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{24 ,0,32},{29 ,1,232},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{26 ,0,163},{31 ,1,73},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{28 ,0,32},{33 ,1,199},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{30 ,0,170},{35 ,1,231},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{32 ,0,103},{37 ,1,59},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{34 ,0,161},{39 ,1,115},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{36 ,0,11},{41 ,1,53},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{38 ,0,121},{43 ,1,22},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{40 ,0,4},{45 ,1,177},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{42 ,0,222},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1}, +{44 ,0,191},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1},{0 ,0,-1} +}; \ No newline at end of file diff --git a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu index 161b3624d3..931d500338 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu +++ b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.cu @@ -32,7 +32,7 @@ #include "bgs/BG2_I6" #include "bgs/BG2_I7" -#define MAX_ITERATION 5 +#define MAX_ITERATION 2 #define MC 1 #define cudaCheck(ans) { cudaAssert((ans), __FILE__, __LINE__); } @@ -49,13 +49,21 @@ typedef struct{ char y; short value; } h_element; +#include "bgs/BG1_compact_in_C.h" +__device__ char dev_const_llr[68*384]; +__device__ char dev_dt [46*68*384]; +__device__ char dev_llr[68*384]; +__device__ unsigned char dev_tmp[68*384]; h_element h_compact1 [46*19] = {}; h_element h_compact2 [68*30] = {}; -__device__ __constant__ h_element dev_h_compact1[46*19]; // used in kernel 1 -__device__ __constant__ h_element dev_h_compact2[68*30]; // used in kernel 2 +__device__ h_element dev_h_compact1[46*19]; // used in kernel 1 +__device__ h_element dev_h_compact2[68*30]; // used in kernel 2 + +// __device__ __constant__ h_element dev_h_compact1[46*19]; // used in kernel 1 +// __device__ __constant__ h_element dev_h_compact2[68*30]; // used in kernel 2 // row and col element count __device__ __constant__ char h_ele_row_bg1_count[46] = { @@ -92,9 +100,93 @@ __global__ void warmup() // warm up gpu for time measurement } +extern "C" +void warmup_for_GPU(){ + + warmup<<<20,1024 >>>(); + +} + +extern "C" +void set_compact_BG(int Zc,short BG){ + + int row,col; + if(BG == 1){ + row = 46; + col = 68; + } + else{ + row = 42; + col = 52; + } + int compact_row = 30; + int compact_col = 19; + if(BG==2){compact_row = 10, compact_col = 23;} + int memorySize_h_compact1 = row * compact_col * sizeof(h_element); + int memorySize_h_compact2 = compact_row * col * sizeof(h_element); + int lift_index = 0; + short lift_set[][9] = { + {2,4,8,16,32,64,128,256}, + {3,6,12,24,48,96,192,384}, + {5,10,20,40,80,160,320}, + {7,14,28,56,112,224}, + {9,18,36,72,144,288}, + {11,22,44,88,176,352}, + {13,26,52,104,208}, + {15,30,60,120,240}, + {0} + }; + + for(int i = 0; lift_set[i][0] != 0; i++){ + for(int j = 0; lift_set[i][j] != 0; j++){ + if(Zc == lift_set[i][j]){ + lift_index = i; + break; + } + } + } + printf("\nZc = %d BG = %d\n",Zc,BG); + switch(lift_index){ + case 0: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I0, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I0, memorySize_h_compact2) ); + break; + case 1: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I1, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I1, memorySize_h_compact2) ); + break; + case 2: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I2, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I2, memorySize_h_compact2) ); + break; + case 3: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I3, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I3, memorySize_h_compact2) ); + break; + case 4: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I4, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I4, memorySize_h_compact2) ); + break; + case 5: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I5, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I5, memorySize_h_compact2) ); + break; + case 6: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I6, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I6, memorySize_h_compact2) ); + break; + case 7: + cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, host_h_compact1_I7, memorySize_h_compact1) ); + cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, host_h_compact2_I7, memorySize_h_compact2) ); + break; + } + + // return 0; +} + // Kernel 1 -__global__ void ldpc_cnp_kernel_1st_iter(char * dev_llr, char * dev_dt, int BG, int row, int col, int Zc) +__global__ void ldpc_cnp_kernel_1st_iter(/*char * dev_llr,*/ int BG, int row, int col, int Zc) { // if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp %d\n", threadIdx.x); int iMCW = blockIdx.y; // codeword id @@ -153,7 +245,7 @@ __global__ void ldpc_cnp_kernel_1st_iter(char * dev_llr, char * dev_dt, int BG, for(int i = 0; i < s; i++){ // v0: Best performance so far. 0.75f is the value of alpha. sq = 1 - 2 * ((Q_sign >> i) & 0x01); - R_temp = 0.8 * sign * sq * (i != idx_min ? rmin1 : rmin2); + R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); // write results to global memory h_element_t = dev_h_compact1[i*row+iBlkRow]; int addr_temp = offsetR + h_element_t.y * row * Zc; @@ -163,7 +255,7 @@ __global__ void ldpc_cnp_kernel_1st_iter(char * dev_llr, char * dev_dt, int BG, } // Kernel_1 -__global__ void ldpc_cnp_kernel(char * dev_llr, char * dev_dt, int BG, int row, int col, int Zc) +__global__ void ldpc_cnp_kernel(/*char * dev_llr, char * dev_dt,*/ int BG, int row, int col, int Zc) { // if(blockIdx.x == 0 && threadIdx.x == 1) printf("cnp\n"); int iMCW = blockIdx.y; @@ -223,7 +315,7 @@ __global__ void ldpc_cnp_kernel(char * dev_llr, char * dev_dt, int BG, int row, // The 2nd recursion for(int i = 0; i < s; i ++){ sq = 1 - 2 * ((Q_sign >> i) & 0x01); - R_temp = 0.8 * sign * sq * (i != idx_min ? rmin1 : rmin2); + R_temp = 0.75f * sign * sq * (i != idx_min ? rmin1 : rmin2); // write results to global memory @@ -236,7 +328,7 @@ __global__ void ldpc_cnp_kernel(char * dev_llr, char * dev_dt, int BG, int row, // Kernel 2: VNP processing __global__ void -ldpc_vnp_kernel_normal(char * dev_llr, char * dev_dt, char * dev_const_llr, int BG, int row, int col, int Zc) +ldpc_vnp_kernel_normal(/*char * dev_llr, char * dev_dt, char * dev_const_llr,*/ int BG, int row, int col, int Zc) { int iMCW = blockIdx.y; int iBlkCol = blockIdx.x; @@ -276,7 +368,7 @@ ldpc_vnp_kernel_normal(char * dev_llr, char * dev_dt, char * dev_const_llr, int } -__global__ void pack_decoded_bit(char *dev, unsigned char *host, int col, int Zc) +__global__ void pack_decoded_bit(/*char *dev, unsigned char *host,*/ int col, int Zc) { __shared__ unsigned char tmp[128]; int iMCW = blockIdx.y; @@ -284,15 +376,15 @@ __global__ void pack_decoded_bit(char *dev, unsigned char *host, int col, int Zc int btid = threadIdx.x; tmp[btid] = 0; - if(dev[tid] < 0){ + if(dev_llr[tid] < 0){ tmp[btid] = 1 << (7-(btid&7)); } __syncthreads(); if(threadIdx.x < 16){ - host[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] = 0; + dev_tmp[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] = 0; for(int i = 0; i < 8; i++){ - host[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] += tmp[threadIdx.x*8+i]; + dev_tmp[iMCW * col*Zc + blockIdx.x*16+threadIdx.x] += tmp[threadIdx.x*8+i]; } } } @@ -369,18 +461,11 @@ void read_BG(int BG, int *h, int row, int col) */ } - extern "C" -int32_t nrLDPC_decoder_LYC(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, int block_length, time_stats_t *time_decoder) -{ - // alloc mem - //unsigned char *decision = (unsigned char*)p_out; - - uint16_t Zc = p_decParams->Z; - uint8_t BG = p_decParams->BG; - uint8_t numMaxIter = p_decParams->numMaxIter; - e_nrLDPC_outMode outMode = p_decParams->outMode; +void init_LLR_DMA_for_CUDA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, int block_length){ + uint16_t Zc = p_decParams->Z; + uint8_t BG = p_decParams->BG; uint8_t row,col; if(BG == 1){ row = 46; @@ -390,96 +475,41 @@ int32_t nrLDPC_decoder_LYC(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8 row = 42; col = 52; } - int compact_row = 30, compact_col = 19, lift_index=0;; - if(BG==2){compact_row = 10, compact_col = 23;} + unsigned char *hard_decision = (unsigned char*)p_out; + int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; + cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); + cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); + cudaDeviceSynchronize(); - short lift_set[][9] = { - {2,4,8,16,32,64,128,256}, - {3,6,12,24,48,96,192,384}, - {5,10,20,40,80,160,320}, - {7,14,28,56,112,224}, - {9,18,36,72,144,288}, - {11,22,44,88,176,352}, - {13,26,52,104,208}, - {15,30,60,120,240}, - {0} - }; - - for(int i = 0; lift_set[i][0] != 0; i++){ - for(int j = 0; lift_set[i][j] != 0; j++){ - if(Zc == lift_set[i][j]){ - lift_index = i; - break; - } - } +} + +extern "C" +int32_t nrLDPC_decoder_LYC(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, int block_length, time_stats_t *time_decoder) +{ + + + uint16_t Zc = p_decParams->Z; + uint8_t BG = p_decParams->BG; + uint8_t numMaxIter = p_decParams->numMaxIter; + e_nrLDPC_outMode outMode = p_decParams->outMode; + cudaError_t cudaStatus; + uint8_t row,col; + if(BG == 1){ + row = 46; + col = 68; } - - int *h = NULL; - switch(lift_index){ - case 0: - h = (BG == 1)? h_base_0:h_base_8; - break; - case 1: - h = (BG == 1)? h_base_1:h_base_9; - break; - case 2: - h = (BG == 1)? h_base_2:h_base_10; - break; - case 3: - h = (BG == 1)? h_base_3:h_base_11; - break; - case 4: - h = (BG == 1)? h_base_4:h_base_12; - break; - case 5: - h = (BG == 1)? h_base_5:h_base_13; - break; - case 6: - h = (BG == 1)? h_base_6:h_base_14; - break; - case 7: - h = (BG == 1)? h_base_7:h_base_15; - break; + else{ + row = 42; + col = 52; } - /* pack BG in compact graph */ - read_BG(BG, h, row, col); - - - int memorySize_h_compact1 = row * compact_col * sizeof(h_element); - int memorySize_h_compact2 = compact_row * col * sizeof(h_element); -// cpu - int memorySize_hard_decision = col * Zc * sizeof(unsigned char) * MC; - - // alloc memory unsigned char *hard_decision = (unsigned char*)p_out; - // gpu int memorySize_llr_cuda = col * Zc * sizeof(char) * MC; - int memorySize_dt_cuda = row * Zc * col * sizeof(char) * MC; - - -// alloc memory - char *dev_llr; - char *dev_dt; - char *dev_const_llr; - unsigned char *dev_tmp; + cudaCheck( cudaMemcpyToSymbol(dev_const_llr, p_llr, memorySize_llr_cuda) ); + cudaCheck( cudaMemcpyToSymbol(dev_llr, p_llr, memorySize_llr_cuda) ); - cudaCheck( cudaMalloc((void **)&dev_tmp, memorySize_hard_decision) ); - cudaCheck( cudaMalloc((void **)&dev_llr, memorySize_llr_cuda) ); - cudaCheck( cudaMalloc((void **)&dev_const_llr, memorySize_llr_cuda) ); - cudaCheck( cudaMalloc((void **)&dev_dt, memorySize_dt_cuda) ); - -// memcpy host to device - - cudaCheck( cudaMemcpyToSymbol(dev_h_compact1, h_compact1, memorySize_h_compact1) ); - cudaCheck( cudaMemcpyToSymbol(dev_h_compact2, h_compact2, memorySize_h_compact2) ); - cudaCheck( cudaMemcpy((void*)dev_const_llr, p_llr, memorySize_llr_cuda, cudaMemcpyHostToDevice) ); -start_meas(time_decoder); - cudaCheck( cudaMemcpy((void*)dev_llr, p_llr, memorySize_llr_cuda, cudaMemcpyHostToDevice) ); - - // Define CUDA kernel dimension int blockSizeX = Zc; dim3 dimGridKernel1(row, MC, 1); // dim of the thread blocks @@ -488,61 +518,35 @@ start_meas(time_decoder); dim3 dimGridKernel2(col, MC, 1); dim3 dimBlockKernel2(blockSizeX, 1, 1); cudaDeviceSynchronize(); - - cudaEvent_t start, end; - float time; - warmup<<>>(); - warmup<<>>(); - - - cudaEventCreate(&start); - cudaEventCreate(&end); - cudaEventRecord(start, 0); - -// cudaProfilerStart(); - // lauch kernel + for(int ii = 0; ii < MAX_ITERATION; ii++){ // first kernel if(ii == 0){ ldpc_cnp_kernel_1st_iter <<>> - (dev_llr, dev_dt, BG, row, col, Zc); + (/*dev_llr,*/ BG, row, col, Zc); }else{ ldpc_cnp_kernel <<>> - (dev_llr, dev_dt, BG, row, col, Zc); + (/*dev_llr,*/ BG, row, col, Zc); } - // second kernel - - ldpc_vnp_kernel_normal - <<>> - (dev_llr, dev_dt, dev_const_llr, BG, row, col, Zc); - + ldpc_vnp_kernel_normal + <<>> + // (dev_llr, dev_const_llr,BG, row, col, Zc); + (BG, row, col, Zc); } + int pack = (block_length/128)+1; dim3 pack_block(pack, MC, 1); - pack_decoded_bit<<>>(dev_llr, dev_tmp, col, Zc); - - - cudaEventRecord(end, 0); - cudaEventSynchronize(end); - cudaEventElapsedTime(&time, start, end); + pack_decoded_bit<<>>(/*dev_llr,*/ /*dev_tmp,*/ col, Zc); - - //cudaCheck( cudaMemcpy((*)hard_decision, (const void*)dev_tmp, memorySize_hard_decision, cudaMemcpyDeviceToHost) ); - cudaCheck( cudaMemcpy((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char), cudaMemcpyDeviceToHost) ); + cudaCheck( cudaMemcpyFromSymbol((void*)hard_decision, (const void*)dev_tmp, (block_length/8)*sizeof(unsigned char)) ); cudaDeviceSynchronize(); -stop_meas(time_decoder); - cudaCheck( cudaFree(dev_llr) ); - cudaCheck( cudaFree(dev_dt) ); - cudaCheck( cudaFree(dev_const_llr) ); - cudaCheck( cudaFree(dev_tmp) ); - - //free(hard_decision); + return MAX_ITERATION; } diff --git a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.h b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.h index 0e78f988ba..c290cedf7d 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.h +++ b/openair1/PHY/CODING/nrLDPC_decoder_LYC/nrLDPC_decoder_LYC.h @@ -23,4 +23,12 @@ int32_t nrLDPC_decoder_LYC(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, int block_length, time_stats_t *time_decoder); + +void init_LLR_DMA_for_CUDA(t_nrLDPC_dec_params* p_decParams, int8_t* p_llr, int8_t* p_out, int block_length); + +void warmup_for_GPU(void); + +void set_compact_BG(int Zc, short BG); + + #endif diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index 5294e79b9f..a16a8d100f 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -236,13 +236,12 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) } */ - int j2=0; fp=f; switch (Qm) { case 2: e0=e; e1=e0+EQm; - for (int j = 0; j< EQm; j++,j2+=2){ + for (int j = 0, j2 = 0; j< EQm; j++,j2+=2){ fp=&f[j2]; fp[0] = e0[j]; fp[1] = e1[j]; @@ -253,7 +252,7 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) e1=e0+EQm; e2=e1+EQm; e3=e2+EQm; - for (int j = 0; j< EQm; j++,j2+=4){ + for (int j = 0, j2 = 0; j< EQm; j++,j2+=4){ fp=&f[j2]; fp[0] = e0[j]; fp[1] = e1[j]; @@ -287,7 +286,7 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) e5=e4+EQm; e6=e5+EQm; e7=e6+EQm; - for (int j = 0; j< EQm; j++,j2+=8){ + for (int j = 0, j2 = 0; j< EQm; j++,j2+=8){ fp=&f[j2]; fp[0] = e0[j]; fp[1] = e1[j]; @@ -310,15 +309,67 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f) void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) { - uint32_t EQm; - - EQm = E/Qm; - - for (int j = 0; j< EQm; j++){ - for (int i = 0; i< Qm; i++){ - e[(i*EQm + j)] = f[(i+j*Qm)]; - } + int16_t *e1,*e2,*e3,*e4,*e5,*e6,*e7; + switch(Qm) { + case 2: + e1=e+(E/2); + for (int j = 0,j2=0; j< E/2; j+=2,j2+=4){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e[j+1] = f[j2+2]; + e1[j+1] = f[j2+3]; + } + break; + case 4: + e1=e+(E/4); + e2=e1+(E/4); + e3=e2+(E/4); + for (int j = 0,j2=0; j< E/4; j++,j2+=4){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e2[j] = f[j2+2]; + e3[j] = f[j2+3]; + } + break; + case 6: + e1=e+(E/6); + e2=e1+(E/6); + e3=e2+(E/6); + e4=e3+(E/6); + e5=e4+(E/6); + for (int j = 0,j2=0; j< E/6; j++,j2+=6){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e2[j] = f[j2+2]; + e3[j] = f[j2+3]; + e4[j] = f[j2+4]; + e5[j] = f[j2+5]; + } + break; + case 8: + e1=e+(E/6); + e2=e1+(E/6); + e3=e2+(E/6); + e4=e3+(E/6); + e5=e4+(E/6); + e6=e5+(E/6); + e7=e6+(E/6); + for (int j = 0,j2=0; j< E/8; j++,j2+=8){ + e[j] = f[j2]; + e1[j] = f[j2+1]; + e2[j] = f[j2+2]; + e3[j] = f[j2+3]; + e4[j] = f[j2+4]; + e5[j] = f[j2+5]; + e6[j] = f[j2+6]; + e7[j] = f[j2+7]; + } + break; + default: + AssertFatal(1==0,"Should not get here : Qm %d\n",Qm); + break; } + } diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c index 2d65521ab3..2c7e3e88eb 100644 --- a/openair1/PHY/INIT/lte_init.c +++ b/openair1/PHY/INIT/lte_init.c @@ -275,6 +275,7 @@ void phy_config_request(PHY_Config_t *phy_config) { fp->soundingrs_ul_config_common.srs_MaxUpPts = cfg->srs_config.max_up_pts.value; fp->num_MBSFN_config = 0; fp->NonMBSFN_config_flag =cfg->fembms_config.non_mbsfn_config_flag.value; + fp->FeMBMS_active = fp->NonMBSFN_config_flag; fp->NonMBSFN_config.non_mbsfn_SubframeConfig = cfg->fembms_config.non_mbsfn_subframeconfig.value; fp->NonMBSFN_config.radioframeAllocationPeriod = cfg->fembms_config.radioframe_allocation_period.value; fp->NonMBSFN_config.radioframeAllocationOffset = cfg->fembms_config.radioframe_allocation_offset.value; diff --git a/openair1/PHY/INIT/lte_init_ru.c b/openair1/PHY/INIT/lte_init_ru.c index 4783655a6c..8ad928f8a0 100644 --- a/openair1/PHY/INIT/lte_init_ru.c +++ b/openair1/PHY/INIT/lte_init_ru.c @@ -186,7 +186,6 @@ void phy_free_RU(RU_t *ru) { int i,j,p; RU_CALIBRATION *calibration = &ru->calibration; LOG_I(PHY, "Feeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx); - free_and_zero(ru->frame_parms); if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdata[i]); diff --git a/openair1/PHY/INIT/lte_init_ue.c b/openair1/PHY/INIT/lte_init_ue.c index 082db61da9..64a5992a64 100644 --- a/openair1/PHY/INIT/lte_init_ue.c +++ b/openair1/PHY/INIT/lte_init_ue.c @@ -137,7 +137,7 @@ void phy_config_sib2_ue(module_id_t Mod_id,int CC_id, if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { fp->MBSFN_config[i].fourFrames_flag = 0; fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration - LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] pattern is %d\n", i, + LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] oneFrame pattern is %d\n", i, fp->MBSFN_config[i].mbsfn_SubframeConfig); } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration fp->MBSFN_config[i].fourFrames_flag = 1; @@ -145,7 +145,7 @@ void phy_config_sib2_ue(module_id_t Mod_id,int CC_id, mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]<<16); - LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] pattern is %x\n", i, + LOG_I(PHY, "[CONFIG] LTE_MBSFN_SubframeConfig[%d] fourFrame pattern is %x\n", i, fp->MBSFN_config[i].mbsfn_SubframeConfig); } } @@ -212,7 +212,7 @@ void phy_config_sib1_fembms_ue(module_id_t Mod_id,int CC_id, LTE_DL_FRAME_PARMS *fp = &ue->frame_parms; if (nonMBSFN_SubframeConfig != NULL) { - fp->NonMBSFN_config_flag = 0; + fp->NonMBSFN_config_flag = 1; fp->NonMBSFN_config.radioframeAllocationPeriod=nonMBSFN_SubframeConfig->radioFrameAllocationPeriod_r14; fp->NonMBSFN_config.radioframeAllocationOffset=nonMBSFN_SubframeConfig->radioFrameAllocationOffset_r14; fp->NonMBSFN_config.non_mbsfn_SubframeConfig=(nonMBSFN_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | nonMBSFN_SubframeConfig->subframeAllocation_r14.buf[0]>>7); diff --git a/openair1/PHY/INIT/lte_parms.c b/openair1/PHY/INIT/lte_parms.c index 12a5646df6..f5b7a6c7e8 100644 --- a/openair1/PHY/INIT/lte_parms.c +++ b/openair1/PHY/INIT/lte_parms.c @@ -93,6 +93,11 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms, frame_parms->N_RBGS = 4; frame_parms->N_RBG = 25; + frame_parms->ofdm_symbol_size_khz_1dot25 = 2*2*6144*osf; + frame_parms->first_carrier_offset_khz_1dot25 = frame_parms->ofdm_symbol_size_khz_1dot25 - 1800*2*2; + frame_parms->nb_prefix_samples_khz_1dot25>>=(2-log2_osf); + frame_parms->nb_prefix_samples0_khz_1dot25>>=(2-log2_osf); + break; case 75: @@ -104,6 +109,12 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms, frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2; frame_parms->N_RBGS = 4; frame_parms->N_RBG = 25; + + frame_parms->ofdm_symbol_size_khz_1dot25 = 2*6144*osf; + frame_parms->first_carrier_offset_khz_1dot25 = frame_parms->ofdm_symbol_size_khz_1dot25 - 1800*2; + frame_parms->nb_prefix_samples_khz_1dot25>>=(2-log2_osf); + frame_parms->nb_prefix_samples0_khz_1dot25>>=(2-log2_osf); + break; case 50: @@ -115,6 +126,10 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms, frame_parms->nb_prefix_samples0>>=(1-log2_osf); frame_parms->N_RBGS = 3; frame_parms->N_RBG = 17; + frame_parms->ofdm_symbol_size_khz_1dot25 = 2*6144*osf; + frame_parms->first_carrier_offset_khz_1dot25 = frame_parms->ofdm_symbol_size_khz_1dot25 - 1800*2; + frame_parms->nb_prefix_samples_khz_1dot25>>=(2-log2_osf); + frame_parms->nb_prefix_samples0_khz_1dot25>>=(2-log2_osf); break; case 25: diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index e08c6d20e8..8f220f1455 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -27,6 +27,7 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "openair1/PHY/MODULATION/nr_modulation.h" /*#include "RadioResourceConfigCommonSIB.h" #include "RadioResourceConfigDedicated.h" #include "TDD-Config.h" @@ -132,6 +133,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, } } + nr_generate_modulation_table(); nr_init_pdcch_dmrs(gNB, cfg->cell_config.phy_cell_id.value); nr_init_pbch_interleaver(gNB->nr_pbch_interleaver); //PDSCH DMRS init @@ -199,6 +201,8 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, common_vars->rxdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); common_vars->rxdata[i] = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)); } + common_vars->debugBuff = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)*100); + common_vars->debugBuff_sample_offset = 0; // Channel estimates for SRS @@ -247,10 +251,11 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, pusch_vars[ULSCH_id]->ul_ch_estimates_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ptrs_phase_per_slot = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->ul_ch_estimates_time = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->rxdataF_comp = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_mag0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_magb0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_mag0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); + pusch_vars[ULSCH_id]->ul_ch_magb0 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->ul_ch_mag = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(Prx*sizeof(int32_t*) ); @@ -264,16 +269,18 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, pusch_vars[ULSCH_id]->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear( 2*sizeof(int32_t)*fp->ofdm_symbol_size ); pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2*fp->symbols_per_slot ); // max intensity in freq is 1 sc every 2 RBs pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2*fp->symbols_per_slot ); + pusch_vars[ULSCH_id]->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->symbols_per_slot); // symbols per slot pusch_vars[ULSCH_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_mag0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); - pusch_vars[ULSCH_id]->ul_ch_magb0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); + pusch_vars[ULSCH_id]->ul_ch_mag0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); + pusch_vars[ULSCH_id]->ul_ch_magb0[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); pusch_vars[ULSCH_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); pusch_vars[ULSCH_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); pusch_vars[ULSCH_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(fp->N_RB_UL*12*7*2) ); } printf("ULSCH_id %d (before llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); pusch_vars[ULSCH_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear - printf("ULSCH_id %d (after llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); + printf("ULSCH_id %d (after llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); + pusch_vars[ULSCH_id]->ul_valid_re_per_slot = (int16_t *)malloc16_clear( sizeof(int16_t)*fp->symbols_per_slot); } //ulsch_id /* for (ulsch_id=0; ulsch_idul_ch_estimates_time[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext[i]); + free_and_zero(pusch_vars[ULSCH_id]->ptrs_phase_per_slot[i]); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag0[i]); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb0[i]); @@ -349,6 +357,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_ptrs_estimates_ext); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_time); + free_and_zero(pusch_vars[ULSCH_id]->ptrs_phase_per_slot); + free_and_zero(pusch_vars[ULSCH_id]->ul_valid_re_per_slot); free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag0); free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb0); @@ -494,7 +504,11 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { compute_nr_prach_seq(short_sequence, num_sequences, rootSequenceIndex, RC.gNB[Mod_id]->X_u); // } RC.gNB[Mod_id]->configured = 1; - find_SSB_and_RO_available(Mod_id); + + find_SSB_and_RO_available(Mod_id); + + init_symbol_rotation(fp,fp->dl_CarrierFreq); + LOG_I(PHY,"gNB %d configured\n",Mod_id); } @@ -506,6 +520,15 @@ void init_nr_transport(PHY_VARS_gNB *gNB) { LOG_I(PHY, "Initialise nr transport\n"); uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value; + memset(gNB->num_pdsch_rnti, 0, sizeof(uint16_t)*80); + + for (i=0; i pdcch_pdu[i].frame=-1; + LOG_I(PHY,"Initializing UL PDCCH list for UL PDCCH %d/%d\n",i,NUMBER_OF_NR_PDCCH_MAX); + gNB->ul_pdcch_pdu[i].frame=-1; + } + for (i=0; ipucch[i] = new_gNB_pucch(); diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 8f17c992c4..648b820f07 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -123,9 +123,9 @@ int nr_phy_init_RU(RU_t *ru) { LOG_E(PHY,"[INIT] %s() RC.nb_nr_L1_inst:%d \n", __FUNCTION__, RC.nb_nr_L1_inst); int beam_count = 0; - if (ru->nb_log_antennas>1) { + if (ru->nb_tx>1) {//Enable beamforming when nb_tx > 1 for (p=0;pnb_log_antennas;p++) { - if ((fp->L_ssb >> p) & 0x01) + if ((fp->L_ssb >> (63-p)) & 0x01)//64 bit-map with the MSB @2⁶³ corresponds to SSB ssb_index 0 beam_count++; } AssertFatal(ru->nb_bfw==(beam_count*ru->nb_tx),"Number of beam weights from config file is %d while the expected number is %d",ru->nb_bfw,(beam_count*ru->nb_tx)); @@ -133,7 +133,7 @@ int nr_phy_init_RU(RU_t *ru) { int l_ind = 0; for (i=0; inb_log_antennas;p++) { - if ((fp->L_ssb >> p) & 0x01) { + if ((fp->L_ssb >> (63-p)) & 0x01) { ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*)); for (j=0; jnb_tx; j++) { ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t)); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 1729ac0d9e..39e99e6ec3 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -39,6 +39,7 @@ #include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_REFSIG/nr_refsig.h" //uint8_t dmrs1_tab_ue[8] = {0,2,3,4,6,8,9,10}; @@ -642,10 +643,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, // create shortcuts NR_DL_FRAME_PARMS *const fp = &ue->frame_parms; NR_UE_COMMON *const common_vars = &ue->common_vars; - NR_UE_PDSCH **const pdsch_vars_SI = ue->pdsch_vars_SI; - NR_UE_PDSCH **const pdsch_vars_ra = ue->pdsch_vars_ra; - NR_UE_PDSCH **const pdsch_vars_p = ue->pdsch_vars_p; - NR_UE_PDSCH **const pdsch_vars_mch = ue->pdsch_vars_MCH; NR_UE_PBCH **const pbch_vars = ue->pbch_vars; NR_UE_PRACH **const prach_vars = ue->prach_vars; int i,j,k,l,slot,symb,q; @@ -681,6 +678,8 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->bitrate[eNB_id] = 0; ue->total_received_bits[eNB_id] = 0; } + // init NR modulation lookup tables + nr_generate_modulation_table(); /////////////////////////PUSCH init///////////////////////// /////////// @@ -796,10 +795,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->pdcch_vars[th_id][eNB_id] = (NR_UE_PDCCH *)malloc16_clear(sizeof(NR_UE_PDCCH)); } - pdsch_vars_SI[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); - pdsch_vars_ra[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); - pdsch_vars_p[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); - pdsch_vars_mch[eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); prach_vars[eNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH)); pbch_vars[eNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH)); @@ -861,11 +856,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, } } - phy_init_nr_ue__PDSCH( pdsch_vars_SI[eNB_id], fp ); - phy_init_nr_ue__PDSCH( pdsch_vars_ra[eNB_id], fp ); - phy_init_nr_ue__PDSCH( pdsch_vars_p[eNB_id], fp ); - phy_init_nr_ue__PDSCH( pdsch_vars_mch[eNB_id], fp ); - // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE for (th_id=0; th_idpdcch_vars[th_id][eNB_id]->llr = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); @@ -929,10 +919,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->pdsch_vars[th_id][eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); } - pdsch_vars_SI[eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); - pdsch_vars_ra[eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); - pdsch_vars_p[eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); - if (abstraction_flag == 0) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id], fp ); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index c3fe9c54b1..6045930b17 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -308,7 +308,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, int num_tx_ant = (cfg == NULL) ? fp->Lmax : cfg->carrier_config.num_tx_ant.value; for (int p=0; pN_ssb += ((fp->L_ssb >> p) & 0x01); + fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01); return 0; @@ -389,7 +389,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_ssb = 0; for (int p=0; pLmax; p++) - fp->N_ssb += ((fp->L_ssb >> p) & 0x01); + fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01); return 0; } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c index 333a6f0866..4ad050ccea 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c @@ -22,7 +22,7 @@ /*! \file config_ue.c * \brief This includes FeMBMS UE Channel Estimation Procedures for FeMBMS 1.25KHz Carrier Spacing * \author Javier Morgade - * \date 2019 + * \date 2020 * \version 0.1 * \email: javier.morgade@ieee.org * @ingroup _phy @@ -768,8 +768,8 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue, module_id_t eNB_id, uint8_t eNB_offset, int subframe) { - int pilot_khz_1dot25[600] __attribute__((aligned(16))); - unsigned char aarx/*,aa*/; + int pilot_khz_1dot25[2*2*600] __attribute__((aligned(16))); + unsigned char aarx,aa; //unsigned int rb; int16_t ch[2]; short *pil,*rxF,*dl_ch/*,*ch0,*ch1,*ch11,*chp,*ch_prev*/; @@ -783,7 +783,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue, int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF; ch_offset = 0;//(l*(ue->frame_parms.ofdm_symbol_size)); symbol_offset = 0;//ch_offset;//phy_vars_ue->lte_frame_parms.ofdm_symbol_size*l; - AssertFatal( ue->frame_parms.N_RB_DL==25,"OFDM symbol size %d not yet supported for FeMBMS\n",ue->frame_parms.N_RB_DL); + //AssertFatal( ue->frame_parms.N_RB_DL==25,"OFDM symbol size %d not yet supported for FeMBMS\n",ue->frame_parms.N_RB_DL); if( (subframe&0x1) == 0) { f=filt24_0_khz_1dot25; @@ -823,7 +823,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue, k=3; } - if(ue->frame_parms.N_RB_DL==25) { + if(1/*ue->frame_parms.N_RB_DL==25*/) { 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); multadd_real_vector_complex_scalar(fl, @@ -843,7 +843,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue, rxF+=12; dl_ch+=16; - for(pilot_cnt=2; pilot_cnt<299; pilot_cnt+=2) { + for(pilot_cnt=2; pilot_cntframe_parms.N_RB_DL*12-1/*299*/; pilot_cnt+=2) { 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); multadd_real_vector_complex_scalar(f, @@ -866,7 +866,7 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue, rxF = (int16_t *)&rxdataF[aarx][((symbol_offset+1+k))]; //Skip DC offset - for(pilot_cnt=0; pilot_cnt<297; pilot_cnt+=2) { + for(pilot_cnt=0; pilot_cntframe_parms.N_RB_DL*12-3/*297*/; pilot_cnt+=2) { 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); multadd_real_vector_complex_scalar(f, @@ -905,6 +905,32 @@ int lte_dl_mbsfn_khz_1dot25_channel_estimation(PHY_VARS_UE *ue, } } + // do ifft of channel estimate + for (aa=0; aaframe_parms.nb_antennas_rx*ue->frame_parms.nb_antennas_tx; aa++) { + if (ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa]) { + switch (ue->frame_parms.N_RB_DL) { + case 25: + idft(IDFT_6144,(int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa][8], + (int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[0][aa], + 1); + break; + case 50: + idft(IDFT_12288,(int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa][8], + (int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[0][aa], + 1); + break; + case 100: + idft(IDFT_24576,(int16_t*) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[0][aa][8], + (int16_t*) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[0][aa], + 1); + break; + default: + break; + } + } + } + + return(0); } diff --git a/openair1/PHY/LTE_REFSIG/lte_refsig.h b/openair1/PHY/LTE_REFSIG/lte_refsig.h index 45402436f7..84a2676082 100644 --- a/openair1/PHY/LTE_REFSIG/lte_refsig.h +++ b/openair1/PHY/LTE_REFSIG/lte_refsig.h @@ -106,6 +106,16 @@ int lte_dl_mbsfn(PHY_VARS_eNB *phy_vars_eNB, int32_t *output, short amp, int subframe, unsigned char l); +/*! \brief This function generates the 1.25KHz MBSFN reference signal sequence (36-211, Sec 6.10.1.2) +@param phy_vars_eNB Pointer to eNB variables +@param output Output vector for OFDM symbol (Frequency Domain) +@param amp Q15 amplitude +*/ + +int lte_dl_mbsfn_khz_1dot25(PHY_VARS_eNB *phy_vars_eNB, int32_t *output, + short amp, + int subframe); + /*!\brief This function generates the cell-specific reference signal sequence (36-211, Sec 6.10.1.1) for channel estimation upon reception diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 14036ad43a..3eb44d98fa 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -20,12 +20,12 @@ */ /*! \file PHY/LTE_TRANSPORT/dlsch_coding.c - * \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 - * \author R. Knopp + * \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03, V14.1 2017 (includes FeMBMS support) + * \author R. Knopp, J. Morgade * \date 2011 * \version 0.1 * \company Eurecom - * \email: knopp@eurecom.fr + * \email: knopp@eurecom.fr, jaiver.morgade@ieee.org * \note * \warning */ @@ -425,3 +425,108 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return(0); } + +int dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + unsigned char *a, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch, + int frame, + uint8_t subframe, + time_stats_t *rm_stats, + time_stats_t *te_stats, + time_stats_t *i_stats) { + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; + if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { + LOG_E(PHY,"dlsch_encoding illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); + return(-1); + } + + LTE_DL_eNB_HARQ_t *hadlsch=dlsch->harq_processes[harq_pid]; + uint8_t beamforming_mode=0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); + + if(hadlsch->mimo_mode == TM7) + beamforming_mode = 7; + else if(hadlsch->mimo_mode == TM8) + beamforming_mode = 8; + else if(hadlsch->mimo_mode == TM9_10) + beamforming_mode = 9; + + unsigned int G = get_G_khz_1dot25(frame_parms,hadlsch->nb_rb, + hadlsch->rb_alloc, + hadlsch->Qm, // mod order + hadlsch->Nl, + num_pdcch_symbols, + frame,subframe,beamforming_mode); + + proc->nbEncode=0; + + // if (hadlsch->Ndi == 1) { // this is a new packet + if (hadlsch->round == 0) { // this is a new packet + // Add 24-bit crc (polynomial A) to payload + unsigned int A=hadlsch->TBS; //6228; + unsigned int crc = crc24a(a, + A)>>8; + a[A>>3] = ((uint8_t *)&crc)[2]; + a[1+(A>>3)] = ((uint8_t *)&crc)[1]; + a[2+(A>>3)] = ((uint8_t *)&crc)[0]; + // printf("CRC %x (A %d)\n",crc,A); + hadlsch->B = A+24; + // hadlsch->b = a; + memcpy(hadlsch->b,a,(A/8)+4); + + if (lte_segmentation(hadlsch->b, + hadlsch->c, + hadlsch->B, + &hadlsch->C, + &hadlsch->Cplus, + &hadlsch->Cminus, + &hadlsch->Kplus, + &hadlsch->Kminus, + &hadlsch->F)<0) + return(-1); + } + + for (int r=0, r_offset=0; rC; r++) { + + union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, proc->respEncode, TPencode); + turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); + rdata->input=hadlsch->c[r]; + rdata->Kr_bytes= ( rCminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; + rdata->filler=(r==0) ? hadlsch->F : 0; + rdata->r=r; + rdata->harq_pid=harq_pid; + rdata->dlsch=dlsch; + rdata->rm_stats=rm_stats; + rdata->te_stats=te_stats; + rdata->i_stats=i_stats; + rdata->round=hadlsch->round; + rdata->r_offset=r_offset; + rdata->G=G; + + if ( proc->threadPool->activated ) { + pushTpool(proc->threadPool,req); + proc->nbEncode++; + } else { + TPencode(rdata); + delNotifiedFIFO_elt(req); + } + + int Qm=hadlsch->Qm; + int C=hadlsch->C; + int Nl=hadlsch->Nl; + int Gp = G/Nl/Qm; + int GpmodC = Gp%C; + if (r < (C-(GpmodC))) + r_offset += Nl*Qm * (Gp/C); + else + r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); + } + + return(0); +} + + diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 475c8bd521..8c07421b7e 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -20,12 +20,12 @@ */ /*! \file PHY/LTE_TRANSPORT/dlsch_modulation.c - * \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03 - * \author R. Knopp, F. Kaltenberger + * \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03, V14.1 2017 (FeMBMS) + * \author R. Knopp, F. Kaltenberger, J. Morgade * \date 2011 * \version 0.1 * \company Eurecom - * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr + * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, javier.morgade@ieee.irg * \note * \warning */ @@ -2910,3 +2910,260 @@ int mch_modulation(int32_t **txdataF, return (re_allocated); } + +int allocate_REs_in_RB_MCH_khz_1dot25(int32_t **txdataF, + uint32_t *jj, + uint16_t re_offset, + uint32_t symbol_offset, + uint8_t *x0, + uint8_t subframe, + uint8_t mod_order, + int16_t amp, + int16_t *qam_table_s, + uint32_t *re_allocated, + uint8_t skip_dc, + LTE_DL_FRAME_PARMS *frame_parms) +{ + uint32_t tti_offset; + uint8_t re,offset; + uint8_t qam64_table_offset_re = 0; + uint8_t qam64_table_offset_im = 0; + uint8_t qam16_table_offset_re = 0; + uint8_t qam16_table_offset_im = 0; + int16_t gain_lin_QPSK;//,gain_lin_16QAM1,gain_lin_16QAM2; + int16_t re_off=re_offset; + gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15); + uint8_t first_re,last_re; + int inc; +#ifdef DEBUG_DLSCH_MODULATION + LOG_I(PHY,"allocate_re_MCH khz_1dot25 (mod %d): symbol_offset %d re_offset %d (%d), jj %d -> %d,%d, gain_lin_QPSK %d,txdataF %p\n",mod_order,symbol_offset,re_offset,skip_dc,*jj, x0[*jj], x0[1+*jj],gain_lin_QPSK,&txdataF[0][symbol_offset]); +#endif + + /*last_re=12; + first_re=0; + inc=1; + + if ((l==2)||(l==10)) { + inc=2; + first_re=1; + } else if (l==6) { + inc=2; + }*/ + last_re=144; //12*12 + if ((subframe&0x1)==0){ // n_sf mod 2 == 0: even + first_re=1; + offset=0; + }else{ + first_re=0; + offset=3; + } + inc=1; + + for (re=first_re; reofdm_symbol_size_khz_1dot25+1; + } + + tti_offset = symbol_offset + re_off + re; + + //LOG_I(PHY,"re %d (jj %d)\n",re,*jj); + *re_allocated = *re_allocated + 1; + + + switch (mod_order) { + + case 2: //QPSK + + LOG_D(PHY,"%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + ((int16_t*)&txdataF[0][tti_offset])[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i + + *jj = *jj + 1; + + ((int16_t*)&txdataF[0][tti_offset])[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} + + *jj = *jj + 1; + + LOG_D(PHY,"subframe%d alloc[%d][%d][%d](%d,%d)\n",subframe,tti_offset,symbol_offset,tti_offset-symbol_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]); + break; + + + case 4: //16QAM + + qam16_table_offset_re = 0; + qam16_table_offset_im = 0; + + if (x0[*jj] == 1) + qam16_table_offset_re+=2; + + *jj=*jj+1; + + if (x0[*jj] == 1) + qam16_table_offset_im+=2; + + *jj=*jj+1; + + + if (x0[*jj] == 1) + qam16_table_offset_re+=1; + + *jj=*jj+1; + + if (x0[*jj] == 1) + qam16_table_offset_im+=1; + + *jj=*jj+1; + + + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s[qam16_table_offset_re];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15); + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s[qam16_table_offset_im];//(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15); + + break; + + case 6: //64QAM + + qam64_table_offset_re = 0; + qam64_table_offset_im = 0; + + if (x0[*jj] == 1) + qam64_table_offset_re+=4; + + *jj=*jj+1; + + if (x0[*jj] == 1) + qam64_table_offset_im+=4; + + *jj=*jj+1; + + if (x0[*jj] == 1) + qam64_table_offset_re+=2; + + *jj=*jj+1; + + if (x0[*jj] == 1) + qam64_table_offset_im+=2; + + *jj=*jj+1; + + if (x0[*jj] == 1) + qam64_table_offset_re+=1; + + *jj=*jj+1; + + if (x0[*jj] == 1) + qam64_table_offset_im+=1; + + *jj=*jj+1; + + ((int16_t *)&txdataF[0][tti_offset])[0]=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15); + ((int16_t *)&txdataF[0][tti_offset])[1]=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15); + + break; + + } + } + return(0); +} + +int mch_modulation_khz_1dot25(int32_t **txdataF, + int16_t amp, + uint32_t subframe_offset, + LTE_DL_FRAME_PARMS *frame_parms, + LTE_eNB_DLSCH_t *dlsch) +{ + uint8_t nsymb,nsymb_pmch; + uint32_t i,jj,re_allocated,symbol_offset; + uint16_t l,rb,re_offset; + uint8_t skip_dc=0; + uint8_t mod_order = dlsch->harq_processes[0]->Qm; + int16_t qam16_table_a[4],qam64_table_a[8];//,qam16_table_b[4],qam64_table_b[8]; + int16_t *qam_table_s; + + nsymb_pmch = 1; + nsymb = (frame_parms->Ncp == NORMAL) ? 14 : 12; + + if (mod_order == 4) + for (i=0; i<4; i++) { + qam16_table_a[i] = (int16_t)(((int32_t)qam16_table[i]*amp)>>15); + } + else if (mod_order == 6) + for (i=0; i<8; i++) { + qam64_table_a[i] = (int16_t)(((int32_t)qam64_table[i]*amp)>>15); + } + + jj=0; + re_allocated=0; + + + + + + // LOG_I(PHY,"num_pdcch_symbols %d, nsymb %d\n",num_pdcch_symbols,nsymb); + for (l=0; lfirst_carrier_offset_khz_1dot25; + symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe_offset*nsymb)); + + for (rb=0; rbN_RB_DL; rb++) { + + + if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL + + if (rb==(frame_parms->N_RB_DL>>1)) + skip_dc = 1; + else + skip_dc = 0; + + } + + if (mod_order == 4) + qam_table_s = qam16_table_a; + else if (mod_order == 6) + qam_table_s = qam64_table_a; + else + qam_table_s = NULL; + + //LOG_I(PHY,"Allocated rb %d, subframe_offset %d,amp %d\n",rb,subframe_offset,amp); + allocate_REs_in_RB_MCH_khz_1dot25(txdataF, + &jj, + re_offset, + symbol_offset, + dlsch->harq_processes[0]->eDL, + subframe_offset, + mod_order, + amp, + qam_table_s, + &re_allocated, + skip_dc, + frame_parms); + + re_offset+=144; // go to next RB 12*12 + + // check if we crossed the symbol boundary and skip DC + if (re_offset >= frame_parms->ofdm_symbol_size_khz_1dot25) { + if (skip_dc == 0) //even number of RBs (doesn't straddle DC) + re_offset=1; + else + re_offset=73; // odd number of RBs + } + } + } + +#ifdef DEBUG_DLSCH_MODULATION + LOG_I(PHY,"generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset,1/*transmission mode*/)); + LOG_I(PHY,"generate_dlsch(MCH) : jj = %d,re_allocated = %d\n",jj,re_allocated); +#endif + + return (re_allocated); +} + diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c index 37997c94b4..dfa990269e 100644 --- a/openair1/PHY/LTE_TRANSPORT/pbch.c +++ b/openair1/PHY/LTE_TRANSPORT/pbch.c @@ -20,12 +20,12 @@ */ /*! \file PHY/LTE_TRANSPORT/pbch.c -* \brief Top-level routines for generating and decoding the PBCH/BCH physical/transport channel V8.6 2009-03 -* \author R. Knopp, F. Kaltenberger +* \brief Top-level routines for generating and decoding the PBCH/BCH physical/transport channel V8.6 2009-03, V14.1 (FeMBMS) +* \author R. Knopp, F. Kaltenberger, J. Morgade * \date 2011 * \version 0.1 * \company Eurecom -* \email: knopp@eurecom.fr,florian.kaltenberger.fr +* \email: knopp@eurecom.fr,florian.kaltenberger.fr, javier.morgade@ieee.org * \note * \warning */ @@ -139,6 +139,285 @@ int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms, return(0); } +void pbch_scrambling_fembms(LTE_DL_FRAME_PARMS *frame_parms, + uint8_t *pbch_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 = frame_parms->Nid_cell + (1<<9); //this is c_init for FeMBMS in 36.211 Sec 6.6.1 + // msg("pbch_scrambling: Nid_cell = %d\n",x2); + + for (i=0; i>(i&0x1f))&1); + + } +} + +int generate_pbch_fembms(LTE_eNB_PBCH *eNB_pbch, + int32_t **txdataF, + int amp, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t *pbch_pdu, + uint8_t frame_mod4) +{ + + int i, l; + + uint32_t pbch_D,pbch_E;//,pbch_coded_bytes; + uint8_t pbch_a[PBCH_A>>3]; + uint8_t RCC; + + uint32_t nsymb = (frame_parms->Ncp==NORMAL) ? 14:12; + uint32_t pilots; +#ifdef INTERFERENCE_MITIGATION + uint32_t pilots_2; +#endif + uint32_t second_pilot = (frame_parms->Ncp==NORMAL) ? 4 : 3; + uint32_t jj=0; + uint32_t re_allocated=0; + uint32_t rb, re_offset, symbol_offset; + uint16_t amask=0; + + pbch_D = 16+PBCH_A; + + pbch_E = (frame_parms->Ncp==NORMAL) ? 1920 : 1728; //RE/RB * #RB * bits/RB (QPSK) + // pbch_E_bytes = pbch_coded_bits>>3; + + LOG_D(PHY,"%s(eNB_pbch:%p txdataF:%p amp:%d frame_parms:%p pbch_pdu:%p frame_mod4:%d)\n", __FUNCTION__, eNB_pbch, txdataF, amp, frame_parms, pbch_pdu, frame_mod4==0); + + if (frame_mod4==0) { + bzero(pbch_a,PBCH_A>>3); + bzero(eNB_pbch->pbch_e,pbch_E); + memset(eNB_pbch->pbch_d,LTE_NULL,96); + // Encode data + + // CRC attachment + // crc = (uint16_t) (crc16(pbch_pdu, pbch_crc_bits-16) >> 16); + + /* + // scramble crc with PBCH CRC mask (Table 5.3.1.1-1 of 3GPP 36.212-860) + switch (frame_parms->nb_antenna_ports_eNB) { + case 1: + crc = crc ^ (uint16_t) 0; + break; + case 2: + crc = crc ^ (uint16_t) 0xFFFF; + break; + case 4: + crc = crc ^ (uint16_t) 0xAAAA; + break; + default: + msg("[PBCH] Unknown number of TX antennas!\n"); + break; + } + */ + + // Fix byte endian of PBCH (bit 23 goes in first) + for (i=0; i<(PBCH_A>>3); i++) + pbch_a[(PBCH_A>>3)-i-1] = pbch_pdu[i]; + + // pbch_data[i] = ((char*) &crc)[0]; + // pbch_data[i+1] = ((char*) &crc)[1]; + //#ifdef DEBUG_PBCH + + for (i=0; i<(PBCH_A>>3); i++) + LOG_D(PHY,"[PBCH] pbch_data[%d] = %x\n",i,pbch_a[i]); + + //#endif + + if (frame_parms->nb_antenna_ports_eNB == 1) + amask = 0x0000; + else { + switch (frame_parms->nb_antenna_ports_eNB) { + case 1: + amask = 0x0000; + break; + + case 2: + amask = 0xffff; + break; + + case 4: + amask = 0x5555; + } + } + + ccodelte_encode(PBCH_A,2,pbch_a,eNB_pbch->pbch_d+96,amask); + + +#ifdef DEBUG_PBCH_ENCODING + + for (i=0; i<16+PBCH_A; i++) + LOG_D(PHY,"%d : (%d,%d,%d)\n",i,*(eNB_pbch->pbch_d+96+(3*i)),*(eNB_pbch->pbch_d+97+(3*i)),*(eNB_pbch->pbch_d+98+(3*i))); + +#endif //DEBUG_PBCH_ENCODING + + // Bit collection + /* + j2=0; + for (j=0;j 0) { // bit is to be transmitted + pbch_coded_data2[j2++] = pbch_coded_data[j]&1; + //Bit is repeated + if ((pbch_coded_data[j]&0x40)>0) + pbch_coded_data2[j2++] = pbch_coded_data[j]&1; + } + } + + #ifdef DEBUG_PBCH + msg("[PBCH] rate matched bits=%d, pbch_coded_bits=%d, pbch_crc_bits=%d\n",j2,pbch_coded_bits,pbch_crc_bits); + #endif + + #ifdef DEBUG_PBCH + LOG_M"pbch_encoded_output2.m","pbch_encoded_out2", + pbch_coded_data2, + pbch_coded_bits, + 1, + 4); + #endif //DEBUG_PBCH + */ +#ifdef DEBUG_PBCH_ENCODING + LOG_D(PHY,"Doing PBCH interleaving for %d coded bits, e %p\n",pbch_D,eNB_pbch->pbch_e); +#endif + RCC = sub_block_interleaving_cc(pbch_D,eNB_pbch->pbch_d+96,eNB_pbch->pbch_w); + + lte_rate_matching_cc(RCC,pbch_E,eNB_pbch->pbch_w,eNB_pbch->pbch_e); + +#ifdef DEBUG_PBCH_ENCODING + LOG_D(PHY,"PBCH_e:\n"); + + for (i=0; ipbch_e+i)); + + LOG_D(PHY,"\n"); +#endif + + + +#ifdef DEBUG_PBCH + if (frame_mod4==0) { + LOG_M("pbch_e.m","pbch_e", + eNB_pbch->pbch_e, + pbch_E, + 1, + 4); + + for (i=0; i<16; i++) + printf("e[%d] %d\n",i,eNB_pbch->pbch_e[i]); + } +#endif //DEBUG_PBCH + // scrambling + + pbch_scrambling_fembms(frame_parms, + eNB_pbch->pbch_e, + pbch_E); +#ifdef DEBUG_PBCH + if (frame_mod4==0) { + LOG_M("pbch_e_s.m","pbch_e_s", + eNB_pbch->pbch_e, + pbch_E, + 1, + 4); + + for (i=0; i<16; i++) + printf("e_s[%d] %d\n",i,eNB_pbch->pbch_e[i]); + } +#endif //DEBUG_PBCH + } // frame_mod4==0 + + // modulation and mapping (slot 1, symbols 0..3) + for (l=(nsymb>>1); l<(nsymb>>1)+4; l++) { + + pilots=0; +#ifdef INTERFERENCE_MITIGATION + pilots_2 = 0; +#endif + + if ((l==0) || (l==(nsymb>>1))) { + pilots=1; +#ifdef INTERFERENCE_MITIGATION + pilots_2=1; +#endif + } + + if ((l==1) || (l==(nsymb>>1)+1)) { + pilots=1; + } + + if ((l==second_pilot)||(l==(second_pilot+(nsymb>>1)))) { + pilots=1; + } + +#ifdef DEBUG_PBCH + LOG_D(PHY,"[PBCH] l=%d, pilots=%d\n",l,pilots); +#endif + + + re_offset = frame_parms->ofdm_symbol_size-3*12; + symbol_offset = frame_parms->ofdm_symbol_size*l; + + for (rb=0; rb<6; rb++) { + +#ifdef DEBUG_PBCH + LOG_D(PHY,"RB %d, jj %d, re_offset %d, symbol_offset %d, pilots %d, nushift %d\n",rb,jj,re_offset, symbol_offset, pilots,frame_parms->nushift); +#endif + allocate_pbch_REs_in_RB(frame_parms, + txdataF, + &jj, + re_offset, + symbol_offset, + &eNB_pbch->pbch_e[frame_mod4*(pbch_E>>2)], + pilots, +#ifdef INTERFERENCE_MITIGATION + (pilots_2==1)?(amp/3):amp, +#else + amp, +#endif + &re_allocated); + + re_offset+=12; // go to next RB + + // check if we crossed the symbol boundary and skip DC + + if (re_offset >= frame_parms->ofdm_symbol_size) + re_offset=1; + } + + // } + } + +#ifdef DEBUG_PBCH + printf("[PBCH] txdataF=\n"); + + for (i=0; iofdm_symbol_size; i++) { + printf("%d=>(%d,%d)",i,((short*)&txdataF[0][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[0], + ((short*)&txdataF[0][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[1]); + + if (frame_parms->nb_antenna_ports_eNB!=1) { + printf("(%d,%d)\n",((short*)&txdataF[1][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[0], + ((short*)&txdataF[1][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[1]); + } else { + printf("\n"); + } + } + +#endif + + + return(0); +} + void pbch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, uint8_t *pbch_e, uint32_t length) diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c index 475102b57c..47ef6428cb 100644 --- a/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c +++ b/openair1/PHY/LTE_TRANSPORT/pilots_mbsfn.c @@ -20,12 +20,12 @@ */ /*! \file PHY/LTE_TRANSPORT/pilots_mbsfn.c -* \brief Top-level routines for generating DL mbsfn reference signals -* \authors S. Paranche, R. Knopp +* \brief Top-level routines for generating DL mbsfn reference signals / DL mbsfn reference signals for FeMBMS +* \authors S. Paranche, R. Knopp, J. Morgade * \date 2012 * \version 0.1 * \company Eurecom -* \email: knopp@eurecom.fr +* \email: knopp@eurecom.fr, javier.morgade@ieee.org * \note * \warning */ @@ -85,3 +85,31 @@ int generate_mbsfn_pilot(PHY_VARS_eNB *eNB, } +int generate_mbsfn_pilot_khz_1dot25(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int32_t **txdataF, + int16_t amp) + +{ + + LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; + uint32_t subframe_offset,Nsymb; + int subframe = proc->subframe_tx; + + + if (subframe<0 || subframe>= 10) { + LOG_E(PHY,"generate_mbsfn_pilots_subframe: subframe not in range (%d)\n",subframe); + return(-1); + } + + Nsymb = (frame_parms->Ncp==NORMAL) ? 7 : 6; + + subframe_offset = subframe*frame_parms->ofdm_symbol_size*Nsymb<<1; + + lte_dl_mbsfn_khz_1dot25(eNB, + &txdataF[0][subframe_offset+0], + amp,subframe); + + return(0); +} + diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 90e2836b1e..7b508239a9 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -128,3 +128,53 @@ void generate_mch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a) } +void generate_mch_khz_1dot25(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a) +{ + + int G; + int subframe = proc->subframe_tx; + int frame = proc->frame_tx; + //int bits; + + G = get_G_khz_1dot25(&eNB->frame_parms, + eNB->frame_parms.N_RB_DL, + eNB->dlsch_MCH->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1, + 2,proc->frame_tx,subframe,0); + + //FeMBMS + eNB->dlsch_MCH->harq_processes[0]->Qm = get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs); + + + generate_mbsfn_pilot_khz_1dot25(eNB,proc, + eNB->common_vars.txdataF, + AMP); + + + AssertFatal(dlsch_encoding_fembms_pmch(eNB, + proc, + // a, + eNB->dlsch_MCH->harq_processes[0]->pdu, + 1, + eNB->dlsch_MCH, + proc->frame_tx, + subframe, + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_interleaving_stats)==0, + "problem in dlsch_encoding"); + + + /*for(bits=0;bitsdlsch_MCH->harq_processes[0]->e[bits]); + printf("\n");*/ + + dlsch_scrambling(&eNB->frame_parms,1,eNB->dlsch_MCH,0,G,0,frame,subframe<<1); + + mch_modulation_khz_1dot25(eNB->common_vars.txdataF, + AMP, + subframe, + &eNB->frame_parms, + eNB->dlsch_MCH); +} + diff --git a/openair1/PHY/LTE_TRANSPORT/pmch_common.c b/openair1/PHY/LTE_TRANSPORT/pmch_common.c index 03bf5a378b..8d65dd2744 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch_common.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch_common.c @@ -37,23 +37,84 @@ int is_fembms_cas_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms) { - uint32_t period; + //uint32_t period; - if(frame_parms->NonMBSFN_config_flag ) { - period = 4<NonMBSFN_config.radioframeAllocationPeriod; + //if(frame_parms->NonMBSFN_config_flag ) { + // period = 4<NonMBSFN_config.radioframeAllocationPeriod; - if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) { + // if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) { + // switch (subframe) { + // case 0: + // return(1); //This should be CAS + // break; + // } + // } + //} + if(frame_parms->NonMBSFN_config_flag || frame_parms->FeMBMS_active){ + if ((frame&3)==0) { switch (subframe) { case 0: - return(1); //This should be CAS - break; + return(1); //This should be CAS + break; } - } + } + } return (0); } +int is_fembms_nonMBSFN_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms){ + uint32_t period; + if(frame_parms->NonMBSFN_config_flag ) { + period = 4<NonMBSFN_config.radioframeAllocationPeriod; + if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) { + switch (subframe) { + case 0: + return(1); //This should be CAS + break; + case 1: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x100) > 0) + return(1); + break; + case 2: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x80) > 0) + return(1); + break; + case 3: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x40) > 0) + return(1); + break; + case 4: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x20) > 0) + return(1); + break; + case 5: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x10) > 0) + return(1); + break; + case 6: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x8) > 0) + return(1); + break; + case 7: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x4) > 0) + return(1); + break; + case 8: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x2) > 0) + return(1); + break; + case 9: + if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x1) > 0) + return(1); + break; + } + } + } + return (0); +} + int is_fembms_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms) { uint32_t period; @@ -62,63 +123,67 @@ int is_fembms_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *fr if ((frame % period) == frame_parms->NonMBSFN_config.radioframeAllocationOffset) { switch (subframe) { + case 0: + return(0); + break; case 1: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x100) > 0) - return(1); + return(0); break; case 2: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x80) > 0) - return(1); + return(0); break; case 3: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x40) > 0) - return(1); + return(0); break; case 4: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x20) > 0) - return(1); + return(0); break; case 5: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x10) > 0) - return(1); + return(0); break; case 6: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x8) > 0) - return(1); + return(0); break; case 7: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x4) > 0) - return(1); + return(0); break; case 8: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x2) > 0) - return(1); + return(0); break; case 9: if ((frame_parms->NonMBSFN_config.non_mbsfn_SubframeConfig & 0x1) > 0) - return(1); + return(0); break; } - } else { //Then regular MBSFN FeMBMS subframe + } else if((frame_parms->FeMBMS_active == 1 || frame_parms->NonMBSFN_config_flag == 1 ) && !is_fembms_cas_subframe(frame,subframe,frame_parms) ) { //Then regular MBSFN FeMBMS subframe return(1); } + return(1); } return(0); diff --git a/openair1/PHY/LTE_TRANSPORT/transport_common.h b/openair1/PHY/LTE_TRANSPORT/transport_common.h index 321789d54b..ab2921c2b9 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_common.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_common.h @@ -67,6 +67,7 @@ #if !defined(SI_RNTI) #define SI_RNTI (rnti_t)0xffff + #define SI_RNTI_MBMS (rnti_t)0xfff9 #endif #if !defined(M_RNTI) #define M_RNTI (rnti_t)0xfffd diff --git a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h index e4f5d9a17f..1944f06fab 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h @@ -270,6 +270,9 @@ int is_pmch_subframe(frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parm */ int is_fembms_cas_subframe(frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms); +int is_fembms_nonMBSFN_subframe (frame_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms); + + /*! \brief Return the status of MBSFN in this frame/subframe @param frame Frame index diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index 3988923bb9..4ce113f78e 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -123,6 +123,42 @@ int32_t dlsch_encoding(PHY_VARS_eNB *eNB, time_stats_t *te_stats, time_stats_t *i_stats); +/** \fn dlsch_encoding(PHY_VARS_eNB *eNB, + uint8_t *input_buffer, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch, + int frame, + uint8_t subframe) + \brief This function performs a subset of the bit-coding functions for LTE as described in 36-212, Release 8.Support is limited to turbo-coded channels (DLSCH/ULSCH). The implemented functions are: + - CRC computation and addition + - Code block segmentation and sub-block CRC addition + - Channel coding (Turbo coding) + - Rate matching (sub-block interleaving, bit collection, selection and transmission + - Code block concatenation + @param eNB Pointer to eNB PHY context + @param input_buffer Pointer to input buffer for sub-frame + @param frame_parms Pointer to frame descriptor structure + @param num_pdcch_symbols Number of PDCCH symbols in this subframe + @param dlsch Pointer to dlsch to be encoded + @param frame Frame number + @param subframe Subframe number + @param rm_stats Time statistics for rate-matching + @param te_stats Time statistics for turbo-encoding + @param i_stats Time statistics for interleaving + @returns status +*/ +int32_t dlsch_encoding_fembms_pmch(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + uint8_t *a, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch, + int frame, + uint8_t subframe, + time_stats_t *rm_stats, + time_stats_t *te_stats, + time_stats_t *i_stats); + @@ -269,6 +305,30 @@ int mch_modulation(int32_t **txdataF, LTE_DL_FRAME_PARMS *frame_parms, LTE_eNB_DLSCH_t *dlsch); +/* + \brief This function is the top-level routine for generation of the sub-frame signal (frequency-domain) for MCH. + @param txdataF Table of pointers for frequency-domain TX signals + @param amp Amplitude of signal + @param subframe_offset Offset of this subframe in units of subframes (usually 0) + @param frame_parms Pointer to frame descriptor + @param dlsch Pointer to DLSCH descriptor for this allocation +*/ +int mch_modulation_khz_1dot25(int32_t **txdataF, + int16_t amp, + uint32_t subframe_offset, + LTE_DL_FRAME_PARMS *frame_parms, + LTE_eNB_DLSCH_t *dlsch); + + +/** \brief Top-level generation function for eNB TX of MBSFN + @param phy_vars_eNB Pointer to eNB variables + @param a Pointer to transport block + @param abstraction_flag + +*/ +void generate_mch_khz_1dot25(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc,uint8_t *a); + + /** \brief Top-level generation function for eNB TX of MBSFN @param phy_vars_eNB Pointer to eNB variables @param a Pointer to transport block @@ -318,6 +378,12 @@ int32_t generate_pilots_slot(PHY_VARS_eNB *phy_vars_eNB, uint16_t slot, int first_pilot_only); +int32_t generate_mbsfn_pilot_khz_1dot25(PHY_VARS_eNB *phy_vars_eNB, + L1_rxtx_proc_t *proc, + int32_t **txdataF, + int16_t amp); + + int32_t generate_mbsfn_pilot(PHY_VARS_eNB *phy_vars_eNB, L1_rxtx_proc_t *proc, int32_t **txdataF, @@ -350,6 +416,13 @@ int32_t generate_pbch(LTE_eNB_PBCH *eNB_pbch, uint8_t *pbch_pdu, uint8_t frame_mod4); +int32_t generate_pbch_fembms(LTE_eNB_PBCH *eNB_pbch, + int32_t **txdataF, + int32_t amp, + LTE_DL_FRAME_PARMS *frame_parms, + uint8_t *pbch_pdu, + uint8_t frame_mod16); + diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index e4083863f0..ab7c2b9091 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c @@ -55,7 +55,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 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/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c index 79e220ac37..b1f419b172 100644 --- a/openair1/PHY/MODULATION/beamforming.c +++ b/openair1/PHY/MODULATION/beamforming.c @@ -155,7 +155,7 @@ int nr_beam_precoding(int32_t **txdataF, memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size)); for (p=0; pL_ssb >> p) & 0x01) { + if ((frame_parms->L_ssb >> (63-p)) & 0x01) { multadd_cpx_vector((int16_t*)&txdataF[p][symbol*frame_parms->ofdm_symbol_size], (int16_t*)beam_weights[p][aa], (int16_t*)&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size], diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index dbfe93adee..652421f77c 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -20,36 +20,138 @@ */ #include "nr_modulation.h" - -extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; +#include "PHY/NR_REFSIG/nr_mod_table.h" void nr_modulation(uint32_t *in, uint32_t length, uint16_t mod_order, int16_t *out) { - uint16_t offset; - uint8_t idx, b_idx; - - offset = (mod_order==2)? NR_MOD_TABLE_QPSK_OFFSET : (mod_order==4)? NR_MOD_TABLE_QAM16_OFFSET : \ - (mod_order==6)? NR_MOD_TABLE_QAM64_OFFSET: (mod_order==8)? NR_MOD_TABLE_QAM256_OFFSET : 0; + uint16_t mask = ((1<>b_idx)&1)<<(mod_order-j-1); - } + switch (mod_order) { - out[i<<1] = nr_mod_table[(offset+idx)<<1]; - out[(i<<1)+1] = nr_mod_table[((offset+idx)<<1)+1]; +#if defined(__SSE2__) + case 2: + nr_mod_table128 = (__m128i*) nr_qpsk_byte_mod_table; + out128 = (__m128i*) out; + for (i=0; i>((i*2)&0x7)) & mask); + out32[i] = nr_mod_table32[idx]; + i++; + } + return; +#else + case 2: + nr_mod_table32 = (int32_t*) nr_qpsk_mod_table; + for (i=0; i>((i*2)&0x1f)) & mask); + out32[i] = nr_mod_table32[idx]; + } + return; +#endif + + case 4: + out64 = (int64_t*) out; + for (i=0; i>((i*4)&0x7)) & mask); + out32[i] = nr_16qam_mod_table[idx]; + i++; + } + return; + + case 6: + j = 0; + for (i=0; i>12)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x>>24)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x>>36)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x>>48)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x2 = (x>>60); + x = in64[i*3+1]; + x2 |= x<<4; + x1 = x2&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>12)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>24)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>36)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>48)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x2 = ((x>>56)&0xf0) | (x2>>60); + x = in64[i*3+2]; + x2 |= x<<8; + x1 = x2&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>12)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>24)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>36)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x2>>48)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x2 = ((x>>52)&0xff0) | (x2>>60); + out64[j++] = nr_64qam_mod_table[x2]; + } + i *= 24; + bit_cnt = i * 8; + while (bit_cnt < length) { + x = *((uint32_t*)(in_bytes+i)); + x1 = x&4095; + out64[j++] = nr_64qam_mod_table[x1]; + x1 = (x>>12)&4095; + out64[j++] = nr_64qam_mod_table[x1]; + i += 3; + bit_cnt += 24; + } + return; + + case 8: + nr_mod_table32 = (int32_t*) nr_256qam_mod_table; + for (i=0; isymbols_per_slot * fp->slots_per_frame/10; + const double Tc=(1/480e3/4096); + const double Nu=2048*64*.5; + const double f0= (double)CarrierFreq; + const double Ncp0=16*64 + (144*64*.5); + const double Ncp1=(144*64*.5); + double tl=0,poff,exp_re,exp_im; + double Ncp,Ncpm1=Ncp0; + + poff = 2*M_PI*((Ncp0*Tc))*f0; + exp_re = cos(poff); + exp_im = sin(-poff); + fp->symbol_rotation[0]=(int16_t)floor(exp_re*32767); + fp->symbol_rotation[1]=(int16_t)floor(exp_im*32767); + LOG_I(PHY,"Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n",f0,nsymb); + LOG_I(PHY,"Symbol rotation %d/%d => (%d,%d)\n",0,nsymb,fp->symbol_rotation[0],fp->symbol_rotation[1]); + for (int l=1;lnumerology_index))) Ncp=Ncp0; + else Ncp=Ncp1; + tl += (Nu+Ncpm1)*Tc; + poff = 2*M_PI*(tl + (Ncp*Tc))*f0; + exp_re = cos(poff); + exp_im = sin(-poff); + fp->symbol_rotation[l<<1]=(int16_t)floor(exp_re*32767); + fp->symbol_rotation[1+(l<<1)]=(int16_t)floor(exp_im*32767); + LOG_I(PHY,"Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",l,nsymb,tl,fp->symbol_rotation[l<<1],fp->symbol_rotation[1+(l<<1)], + (poff/2/M_PI)-floor(poff/2/M_PI)); + Ncpm1=Ncp; + } +} diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 706b4dc113..31d8754768 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -103,4 +103,13 @@ int nr_beam_precoding(int32_t **txdataF, int nb_antenna_ports ); +void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, + int16_t* txdata, + int slot, + int first_symbol, + int nsymb, + int length); + +void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq); + #endif diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 855e649cc5..92aea419af 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -27,6 +27,7 @@ This section deals with basic functions for OFDM Modulation. + */ #include "PHY/defs_eNB.h" @@ -47,6 +48,7 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA PHY_ofdm_mod(txdataF, // input txdata, // output frame_parms->ofdm_symbol_size, + 1, // number of symbols frame_parms->nb_prefix_samples0, // number of prefix samples CYCLIC_PREFIX); @@ -88,7 +90,7 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input if(nb_symbols == 0) return; - short temp[4096*4] __attribute__((aligned(32))); + short temp[2*2*6144*4] __attribute__((aligned(32))); unsigned short i,j; short k; @@ -125,9 +127,23 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input case 3072: idftsize = IDFT_3072; break; + case 4096: idftsize = IDFT_4096; break; + + case 6144: + idftsize= IDFT_6144; + break; + + case 12288: + idftsize= IDFT_12288; + break; + + case 24576: + idftsize= IDFT_24576; + break; + default: idftsize = IDFT_512; break; @@ -177,7 +193,7 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input /*for (j=0; jslots_per_subframe)*fp->symbols_per_slot; - int aa, l, slot_offset, slot_offsetF; - int32_t **txdataF = eNB_common_vars->txdataF; - int32_t **txdataF_BF = common->txdataF_BF; - int32_t **txdata = common->txdata; - - slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); - slot_offsetF = (next_slot)*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==EXTENDED) ? 6 : 7); - //printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc()); - for (l=0; lsymbols_per_tti>>1; l++) { - - for (aa=0; aanb_antennas_tx; aa++) { - - //printf("do_OFDM_mod_l, slot=%d, l=%d, NUMBER_OF_OFDM_CARRIERS=%d,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES=%d\n",next_slot, l,NUMBER_OF_OFDM_CARRIERS,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,1); - if (do_precoding==1) beam_precoding(txdataF,txdataF_BF,frame_parms,eNB_common_vars->beam_weights,next_slot,l,aa); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,0); - - //PMCH case not implemented... - - if (frame_parms->Ncp == EXTENDED) - PHY_ofdm_mod((do_precoding == 1)?txdataF_BF[aa]:&txdataF[aa][slot_offsetF+l*frame_parms->ofdm_symbol_size], // input - &txdata[aa][slot_offset+l*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES], // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); - else { - if (l==0) { - PHY_ofdm_mod((do_precoding==1)?txdataF_BF[aa]:&txdataF[aa][slot_offsetF+l*frame_parms->ofdm_symbol_size], // input - &txdata[aa][slot_offset], // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples0, // number of prefix samples - CYCLIC_PREFIX); - - } else { - PHY_ofdm_mod((do_precoding==1)?txdataF_BF[aa]:&txdataF[aa][slot_offsetF+l*frame_parms->ofdm_symbol_size], // input - &txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES], // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); - - //printf("txdata[%d][%d]=%d\n",aa,slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,txdata[aa][slot_offset+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(l-1)*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES]); - - } - } - } + for (int sidx=0;sidxsymbol_rotation[2*(sidx+first_symbol+symb_offset)],fp->symbol_rotation[1+2*(sidx+first_symbol+symb_offset)]); + rotate_cpx_vector(trxdata+(sidx*length*2), + &fp->symbol_rotation[2*(sidx+first_symbol+symb_offset)], + trxdata+(sidx*length*2), + length, + 15); } - } -*/ + diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index cf0a50a018..2ffdb013a5 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -133,8 +133,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 %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\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); + /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); #endif abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; @@ -198,12 +198,22 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, } - #ifdef DEBUG_FEP - // if (ue->frame <100) - printf("slot_fep: frame %d: symbol %d rx_offset %u\n", ue->proc.proc_rxtx[(Ns)&1].frame_rx, symbol, rx_offset); - #endif +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: symbol %d rx_offset %u\n", symbol, rx_offset); +#endif + + int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + (int16_t*)&rot2, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + frame_parms->ofdm_symbol_size, + 15); + } - + #ifdef DEBUG_FEP printf("slot_fep: done\n"); @@ -308,8 +318,8 @@ int nr_slot_fep_init_sync(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 %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\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); + /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); #endif abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; @@ -373,10 +383,22 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, } - #ifdef DEBUG_FEP - // if (ue->frame <100) - printf("slot_fep: frame %d: symbol %d rx_offset %u\n", ue->proc.proc_rxtx[(Ns)&1].frame_rx, symbol, rx_offset); - #endif + int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, + symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); +#endif + + rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + (int16_t*)&rot2, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + frame_parms->ofdm_symbol_size, + 15); + } @@ -450,11 +472,11 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; if(sample_offset>rxdata_offset) { - memcpy((void *)tmp_dft_in, + memcpy1((void *)tmp_dft_in, (void *) &rxdata[frame_parms->samples_per_frame-sample_offset+rxdata_offset], (sample_offset-rxdata_offset)*sizeof(int)); - memcpy((void *)&tmp_dft_in[sample_offset-rxdata_offset], + memcpy1((void *)&tmp_dft_in[sample_offset-rxdata_offset], (void *) &rxdata[0], (frame_parms->ofdm_symbol_size-sample_offset+rxdata_offset)*sizeof(int)); @@ -468,5 +490,14 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, // clear DC carrier from OFDM symbols rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; + int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + uint32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",Ns,symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); + rotate_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], + (int16_t*)&rot2, + (int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], + frame_parms->ofdm_symbol_size, + 15); return(0); } diff --git a/openair1/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c similarity index 63% rename from openair1/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c rename to openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 9c4d1fcc93..ec55eabf31 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file PHY/NR_ESTIMATION/nr_adjust_sync_gNB.c +/*! \file PHY/NR_ESTIMATION/nr_measurements_gNB.c * \brief TA estimation for TA updates * \author Ahmed Hussein * \date 2019 @@ -69,3 +69,37 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) return max_pos - sync_pos; } + +void gNB_I0_measurements(PHY_VARS_gNB *gNB) { + + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + NR_gNB_COMMON *common_vars = &gNB->common_vars; + PHY_MEASUREMENTS_gNB *measurements = &gNB->measurements; + uint32_t *rb_mask = gNB->rb_mask_ul; + int symbol = gNB->ulmask_symb; + int rb, offset, nb_rb; + uint32_t n0_power_tot, n0_subband_power_temp=0; + int32_t *ul_ch; + + if (symbol>-1) { + n0_power_tot = 0; + for (int aarx=0; aarxnb_antennas_rx; aarx++) { + nb_rb = 0; + for (rb=0; rbN_RB_UL; rb++) { + if ((rb_mask[rb>>5]&(1<<(rb&31))) == 0) { // check that rb was not used in this subframe + nb_rb++; + offset = (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; + offset += (symbol*frame_parms->ofdm_symbol_size); + ul_ch = &common_vars->rxdataF[aarx][offset]; + //TODO what about DC? + n0_subband_power_temp += signal_energy_nodc(ul_ch,12); + } + } + measurements->n0_power[aarx] = n0_subband_power_temp/nb_rb; + measurements->n0_power_dB[aarx] = dB_fixed(measurements->n0_power[aarx]); + n0_power_tot += measurements->n0_power[aarx]; + } + measurements->n0_power_tot_dB = dB_fixed(n0_power_tot); + } +} + diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 3f7c7817f7..b6388fb903 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -25,15 +25,20 @@ #include "nr_ul_estimation.h" #include "PHY/sse_intrin.h" #include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_REFSIG/ptrs_nr.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_ESTIMATION/filt16a_32.h" //#define DEBUG_CH //#define DEBUG_PUSCH +#define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y))) + int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned char Ns, unsigned short p, unsigned char symbol, + int ul_id, unsigned short bwp_start_subcarrier, nfapi_nr_pusch_pdu_t *pusch_pdu) { @@ -43,8 +48,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned int pilot_cnt,re_cnt; int16_t ch[2],ch_r[2],ch_l[2],*pil,*rxF,*ul_ch; int16_t *fl,*fm,*fr,*fml,*fmr,*fmm,*fdcl,*fdcr,*fdclh,*fdcrh; - int ch_offset,symbol_offset, UE_id = 0; - int32_t **ul_ch_estimates_time = gNB->pusch_vars[UE_id]->ul_ch_estimates_time; + int ch_offset,symbol_offset ; + int32_t **ul_ch_estimates_time = gNB->pusch_vars[ul_id]->ul_ch_estimates_time; __m128i *ul_ch_128; #ifdef DEBUG_CH @@ -55,7 +60,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1]; uint8_t nushift; - int **ul_ch_estimates = gNB->pusch_vars[UE_id]->ul_ch_estimates; + int **ul_ch_estimates = gNB->pusch_vars[ul_id]->ul_ch_estimates; int **rxdataF = gNB->common_vars.rxdataF; nushift = (p>>1)&1; @@ -122,7 +127,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type); //------------------------------------------------// - +#ifdef DEBUG_PUSCH + for (int i=0;i<(6*nb_rb_pusch);i++) + printf("%d+j*(%d)\n",((int16_t*)pilot)[2*i],((int16_t*)pilot)[1+(2*i)]); +#endif for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { pil = (int16_t *)&pilot[0]; @@ -134,7 +142,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #ifdef DEBUG_PUSCH printf("symbol_offset %d, nushift %d\n",symbol_offset,nushift); printf("ch est pilot addr %p RB_DL %d\n",&pilot[0], gNB->frame_parms.N_RB_UL); - printf("bwp_start_subcarrier %d, k %d, first_carrier %d\n",bwp_start_subcarrier,k,gNB->frame_parms.first_carrier_offset); + printf("bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n",bwp_start_subcarrier,k,gNB->frame_parms.first_carrier_offset,nb_rb_pusch); printf("rxF addr %p p %d\n", rxF,p); printf("ul_ch addr %p nushift %d\n",ul_ch,nushift); #endif @@ -148,8 +156,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #ifdef DEBUG_PUSCH 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]); - printf("data 0 : rxF - > (%d,%d)\n",rxF[2],rxF[3]); + printf("pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data 0 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fl, @@ -166,8 +174,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - 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]); - printf("data 1 : rxF - > (%d,%d)\n",rxF[2],rxF[3]); + printf("pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data 1 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fml, ch, @@ -182,8 +190,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - 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]); - printf("data 2 : rxF - > (%d,%d)\n",rxF[2],rxF[3]); + printf("pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data 2 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fmm, ch, @@ -204,8 +212,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fml, ch, @@ -220,8 +228,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot %u : 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]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt+1,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+1,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fmm, ch, @@ -242,8 +250,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, 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_PUSCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fm, ch, @@ -261,8 +269,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot %u: rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt+1,rxF[2],rxF[3]); + printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+1,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fmr, ch, @@ -277,8 +285,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, 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_PUSCH - printf("pilot %u: 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]); - printf("data %u : rxF - > (%d,%d)\n",pilot_cnt+2,rxF[2],rxF[3]); + printf("pilot %u: rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); + printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+2,rxF[2],rxF[3],dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fr, ch, @@ -338,7 +346,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, 8); } } -#ifdef DEBUG_PDSCH +#ifdef DEBUG_PUSCH ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; for(uint16_t idxP=0; idxPframe_parms; + int16_t *phase_per_symbol; + + uint8_t L_ptrs = 0; + uint8_t right_side_ref = 0; + uint8_t left_side_ref = 0; + uint8_t nb_dmrs_in_slot = 0; + + //#define DEBUG_UL_PTRS 1 + /* First symbol calculate PTRS symbol index for slot & set the variables */ + if(symbol == rel15_ul->start_symbol_index) + { + gNB->pusch_vars[ulsch_id]->ptrs_symbols = 0; + L_ptrs = 1<<(rel15_ul->pusch_ptrs.ptrs_time_density); + set_ptrs_symb_idx(&gNB->pusch_vars[ulsch_id]->ptrs_symbols, + rel15_ul->nr_of_symbols, + rel15_ul->start_symbol_index, + L_ptrs, + rel15_ul->ul_dmrs_symb_pos); + }/* First symbol check */ + + /* loop over antennas */ + for (int aarx=0; aarx< frame_parms->nb_antennas_rx; aarx++) + { + phase_per_symbol = (int16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; + /* set the previous estimations to zero at first symbol */ + if(symbol == rel15_ul->start_symbol_index) + { + memset(phase_per_symbol,0,sizeof(int32_t)*frame_parms->symbols_per_slot); + } + /* if not PTRS symbol set current ptrs symbol index to zero*/ + gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = 0; + gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol = 0; + /* Check if current symbol contains PTRS */ + if(is_ptrs_symbol(symbol, gNB->pusch_vars[ulsch_id]->ptrs_symbols)) + { + gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = symbol; + /*------------------------------------------------------------------------------------------------------- */ + /* 1) Estimate phase noise per PTRS symbol */ + /*------------------------------------------------------------------------------------------------------- */ + nr_pusch_phase_estimation(frame_parms, + rel15_ul, + (int16_t *)&gNB->pusch_vars[ulsch_id]->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch], + nr_tti_rx, + symbol, + (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)], + gNB->nr_gold_pusch_dmrs[rel15_ul->scid], + &phase_per_symbol[2* symbol], + &gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol); + } + /* DMRS Symbol channel estimates extraction */ + else if(dmrs_symbol_flag) + { + phase_per_symbol[2* symbol]= (int16_t)((1<<15)-1); // 32767 + phase_per_symbol[2* symbol +1]= 0;// no angle + } + /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ + if(symbol == (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols -1)) + { + nb_dmrs_in_slot = get_dmrs_symbols_in_slot(rel15_ul->ul_dmrs_symb_pos,(rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols)); + for(uint8_t dmrs_sym = 0; dmrs_sym < nb_dmrs_in_slot; dmrs_sym ++) + { + if(dmrs_sym == 0) + { + /* get first DMRS position */ + left_side_ref = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols)); + /* get first DMRS position is not at start symbol position then we need to extrapolate left side */ + if(left_side_ref > rel15_ul->start_symbol_index) + { + left_side_ref = rel15_ul->start_symbol_index; + } + } + /* get the next symbol from left_side_ref value */ + right_side_ref = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, left_side_ref+1, (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols)); + /* if no symbol found then interpolate till end of slot*/ + if(right_side_ref == 0) + { + right_side_ref = (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); + } + /*------------------------------------------------------------------------------------------------------- */ + /* 2) Interpolate PTRS estimated value in TD */ + /*------------------------------------------------------------------------------------------------------- */ + nr_pusch_phase_interpolation(phase_per_symbol,left_side_ref,right_side_ref); + /* set left to last dmrs */ + left_side_ref = right_side_ref; + } /*loop over dmrs positions */ + +#ifdef DEBUG_UL_PTRS + LOG_M("ptrsEst.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); + LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp", + &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size], + rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1); +#endif + + /*------------------------------------------------------------------------------------------------------- */ + /* 3) Compensated DMRS based estimated signal with PTRS estimation */ + /*--------------------------------------------------------------------------------------------------------*/ + for(uint8_t i =rel15_ul->start_symbol_index; i< (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);i++) + { +#ifdef DEBUG_UL_PTRS + printf("PTRS: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); +#endif + rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + &phase_per_symbol[2* i], + (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + (rel15_ul->rb_size * NR_NB_SC_PER_RB), + 15); + }// symbol loop + }//interpolation and compensation + }// Antenna loop +} + +/******************************************************************* + * + * NAME : nr_pusch_phase_estimation + * + * PARAMETERS : frame_parms : UL frame parameters + * rel15_ul : UL PDU Structure + * Ns : + * Symbol : OFDM symbol index + * rxF : Channel compensated signal + * ptrs_gold_seq: Gold sequence for PTRS regeneration + * error_est : Estimated error output vector [Re Im] + * RETURN : nothing + * + * DESCRIPTION : + * perform phase estimation from regenerated PTRS SC and channel compensated + * signal + *********************************************************************/ +void nr_pusch_phase_estimation(NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t *rel15_ul, + int16_t *ptrs_ch_p, + unsigned char Ns, + unsigned char symbol, + int16_t *rxF_comp, + uint32_t ***ptrs_gold_seq, + int16_t *error_est, + uint16_t *ptrs_sc) +{ + uint8_t is_ptrs_re = 0; + uint16_t re_cnt = 0; + uint16_t cnt = 0; + unsigned short nb_re_pusch = NR_NB_SC_PER_RB * rel15_ul->rb_size; + uint8_t K_ptrs = rel15_ul->pusch_ptrs.ptrs_freq_density; + uint16_t sc_per_symbol = (rel15_ul->rb_size + K_ptrs - 1)/K_ptrs; + int16_t *ptrs_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); + int16_t *dmrs_comp_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); + double abs = 0.0; + double real = 0.0; + double imag = 0.0; +#ifdef DEBUG_UL_PTRS + double alpha = 0; +#endif + /* generate PTRS RE for the symbol */ + nr_gen_ref_conj_symbols(ptrs_gold_seq[Ns][symbol],sc_per_symbol*2,ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK + + /* loop over all sub carriers to get compensated RE on ptrs symbols*/ + for (int re = 0; re < nb_re_pusch; re++) + { + is_ptrs_re = is_ptrs_subcarrier(re, + rel15_ul->rnti, + 0, + rel15_ul->dmrs_config_type, + K_ptrs, + rel15_ul->rb_size, + rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset, + 0,// start_re is 0 here + frame_parms->ofdm_symbol_size); + if(is_ptrs_re) + { + dmrs_comp_p[re_cnt*2] = rxF_comp[re *2]; + dmrs_comp_p[(re_cnt*2)+1] = rxF_comp[(re *2)+1]; + re_cnt++; + } + else + { + /* Skip PTRS symbols and keep data in a continuous vector */ + rxF_comp[cnt *2]= rxF_comp[re *2]; + rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1]; + cnt++; + } + }/* RE loop */ + /* update the total ptrs RE in a symbol */ + *ptrs_sc = re_cnt; + + /*Multiple compensated data with conj of PTRS */ + mult_cpx_vector(dmrs_comp_p, ptrs_p, ptrs_ch_p,(1 + sc_per_symbol/4)*4,15); // 2^15 shifted + + /* loop over all ptrs sub carriers in a symbol */ + /* sum the error vector */ + for(int i = 0;i < sc_per_symbol; i++) + { + real+= ptrs_ch_p[(2*i)]; + imag+= ptrs_ch_p[(2*i)+1]; + } +#ifdef DEBUG_UL_PTRS + alpha = atan(imag/real); + printf("PTRS: Symbol %d atan(Im,real):= %f \n",symbol, alpha ); +#endif + /* mean */ + real /= sc_per_symbol; + imag /= sc_per_symbol; + /* absolute calculation */ + abs = sqrt(((real * real) + (imag * imag))); + /* normalized error estimation */ + error_est[0]= (real / abs)*(1<<15); + /* compensation in given by conjugate of estimated phase (e^-j*2*pi*fd*t)*/ + error_est[1]= (-1)*(imag / abs)*(1<<15); +#ifdef DEBUG_UL_PTRS + printf("PTRS: Estimated Symbol %d -> %d + j* %d \n",symbol, error_est[0], error_est[1] ); +#endif + /* free vectors */ + free(ptrs_p); + free(dmrs_comp_p); +} + + +/******************************************************************* + * + * NAME : nr_pusch_phase_interpolation + * + * PARAMETERS : *error_est : Data Pointer [Re Im Re Im ...] + * start_symbol : Start Symbol + * end_symbol : End Symbol + * RETURN : nothing + * + * DESCRIPTION : + * Perform Interpolation, extrapolation based upon the estimation + * location between the data Pointer Array. + * + *********************************************************************/ +void nr_pusch_phase_interpolation(int16_t *error_est, + uint8_t start_symbol, + uint8_t end_symbol + ) +{ + + int next = 0, prev = 0, candidates= 0, distance=0, leftEdge= 0, rightEdge = 0, getDiff =0 ; + double weight = 0.0; + double scale = 0.125 ; // to avoid saturation due to fixed point multiplication +#ifdef DEBUG_UL_PTRS + printf("PTRS: INT: Left limit %d, Right limit %d, Loop over %d Symbols \n", + start_symbol,end_symbol-1, (end_symbol -start_symbol)-1); +#endif + for(int i =start_symbol; i< end_symbol;i++) + { + /* Only update when an estimation is found */ + if( error_est[i*2] != 0 ) + { + /* if found a symbol then set next symbol also */ + next = nr_ptrs_find_next_estimate(error_est, i, end_symbol); + /* left extrapolation, if first estimate value is zero */ + if( error_est[i*2] == 0 ) + { + leftEdge = 1; + } + /* right extrapolation, if next is 0 before end symbol */ + if((next == 0) && (end_symbol > i)) + { + rightEdge = 1; + /* special case as no right extrapolation possible with DMRS on left */ + /* In this case take mean of most recent 2 estimated points */ + if(prev ==0) + { + prev = start_symbol -1; + next = start_symbol -2; + getDiff =1; + }else + { + /* for right edge previous is second last from right side */ + next = prev; + /* Set the current as recent estimation reference */ + prev = i; + } + } + /* update current symbol as prev for next symbol */ + if (rightEdge==0) + /* Set the current as recent estimation reference */ + prev = i; + } + /*extrapolation left side*/ + if(leftEdge) + { + distance = next - prev; + weight = 1.0/distance; + candidates = i; + for(int j = 1; j <= candidates; j++) + { + error_est[(i-j)*2] = 8 *(((double)(error_est[prev*2]) * scale * (distance + j) * weight) - + ((double)(error_est[next*2]) * scale * j * weight)); + error_est[((i-j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale* (distance + j) * weight) - + ((double)(error_est[((next*2)+1)]) * scale * j * weight)); +#ifdef DEBUG_UL_PTRS + printf("PTRS: INT: Left Edge i= %d weight= %f %d + j*%d, Prev %d Next %d \n", + (i-j),weight, error_est[(i-j)*2],error_est[((i-j)*2)+1], prev,next); +#endif + } + leftEdge = 0; + } + /* extrapolation at right side */ + else if (rightEdge ) + { + if(getDiff) + { + error_est[(i+1)*2] = ((1<<15) +(error_est[prev*2]) - error_est[next*2]); + error_est[((i+1)*2)+1]= error_est[(prev*2)+1] - error_est[(next*2)+1]; +#ifdef DEBUG_UL_PTRS + printf("PTRS: INT: Right Edge Special Case i= %d weight= %f %d + j*%d, Prev %d Next %d \n", + (i+1),weight, error_est[(i+1)*2],error_est[((i+1)*2)+1], prev,next); +#endif + i++; + } + else + { + distance = prev - next; + candidates = (end_symbol -1) - i; + weight = 1.0/distance; + for(int j = 1; j <= candidates; j++) + { + error_est[(i+j)*2] = 8 *(((double)(error_est[prev*2]) * scale * (distance + j) * weight) - + ((double)(error_est[next*2]) * scale * j * weight)); + error_est[((i+j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale * (distance + j) * weight) - + ((double)(error_est[((next*2)+1)]) * scale *j * weight)); +#ifdef DEBUG_UL_PTRS + printf("PTRS: INT: Right Edge i= %d weight= %f %d + j*%d, Prev %d Next %d \n", + (i+j),weight, error_est[(i+j)*2],error_est[((i+j)*2)+1], prev,next); +#endif + } + if(candidates > 1) + { + i+=candidates; + } + } + } + /* Interpolation between 2 estimated points */ + else if(next != 0 && ( error_est[2*i] == 0 )) + { + distance = next - prev; + weight = 1.0/distance; + candidates = next - i ; + for(int j = 0; j < candidates; j++) + { + + error_est[(i+j)*2] = 8 *(((double)(error_est[prev*2]) * scale * (distance - (j+1)) * weight) + + ((double)(error_est[next*2]) * scale * (j+1) * weight)); + error_est[((i+j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale *(distance - (j+1)) * weight) + + ((double)(error_est[((next*2)+1)]) * scale *(j+1) * weight)); +#ifdef DEBUG_UL_PTRS + printf("PTRS: INT: Interpolation i= %d weight= %f %d + j*%d, Prev %d Next %d\n", + (i+j),weight, error_est[(i+j)*2],error_est[((i+j)*2)+1],prev,next); +#endif + } + if(candidates > 1) + { + i+=candidates-1; + } + }// interpolation + }// symbol loop +} + +/* Find the next non zero Real value in a complex vector */ +int nr_ptrs_find_next_estimate(int16_t *error_est, + uint8_t counter, + uint8_t end_symbol) +{ + for (int i = counter +1 ; i< end_symbol; i++) + { + if( error_est[2*i] != 0) + { + return i; + } + } + return 0; +} diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index a7789c9224..0f71487e36 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -43,9 +43,38 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned char Ns, unsigned short p, unsigned char symbol, + int ul_id, unsigned short bwp_start_subcarrier, nfapi_nr_pusch_pdu_t *pusch_pdu); +void gNB_I0_measurements(PHY_VARS_gNB *gNB); + int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); + +void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, + nfapi_nr_pusch_pdu_t *rel15_ul, + uint8_t ulsch_id, + uint8_t nr_tti_rx, + uint8_t dmrs_symbol_flag, + unsigned char symbol, + uint32_t nb_re_pusch); + +void nr_pusch_phase_estimation(NR_DL_FRAME_PARMS *frame_parms, + nfapi_nr_pusch_pdu_t *rel15_ul, + int16_t *ptrs_ch_p, + unsigned char Ns, + unsigned char symbol, + int16_t *rxF_comp, + uint32_t ***ptrs_gold_seq, + int16_t *error_est, + uint16_t *ptrs_sc); + +void nr_pusch_phase_interpolation(int16_t *error_est, + uint8_t start_symbol, + uint8_t end_symbol); + +int nr_ptrs_find_next_estimate(int16_t *error_est, + uint8_t counter, + uint8_t end_symbol); #endif diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.c b/openair1/PHY/NR_REFSIG/dmrs_nr.c index 7042c152fd..415e6adfa2 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.c +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.c @@ -362,4 +362,25 @@ void generate_dmrs_pbch(uint32_t dmrs_pbch_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_H free(dmrs_sequence); #endif } +/* return the position of next dmrs symbol in a slot */ +int get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol) +{ + for(uint8_t symbol = counter; symbol < end_symbol; symbol++) + if((ul_dmrs_symb_pos >>symbol)&0x01 ) + { + return symbol; + } + return 0; +} + +/* return the total number of dmrs symbol in a slot */ +uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb) +{ + uint8_t tmp = 0; + for (int i = 0; i < nb_symb; i++) + { + tmp += (l_prime_mask >> i) & 0x01; + } + return tmp; +} diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 4eeb8a6e96..3e758c4fa5 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -223,3 +223,27 @@ int nr_pbch_dmrs_rx(int symbol, return(0); } + +/*! + \brief This function generate gold ptrs sequence for each OFDM symbol + \param *in gold sequence for ptrs per OFDM symbol + \param length is number of RE in a OFDM symbol + \param *output pointer to all ptrs RE in a OFDM symbol +*/ +void nr_gen_ref_conj_symbols(uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order) +{ + uint8_t idx, b_idx; + for (int i=0; i>b_idx)&1)<<(mod_order-j-1); + } + output[i<<1] = nr_rx_mod_table[(offset+idx)<<1]; + output[(i<<1)+1] = nr_rx_mod_table[((offset+idx)<<1)+1]; + } +} diff --git a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c new file mode 100644 index 0000000000..b0f9e6d03c --- /dev/null +++ b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c @@ -0,0 +1,87 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_refsig.h" +#include "nr_mod_table.h" + +void nr_generate_modulation_table() { + float sqrt2 = 0.70711; + float sqrt10 = 0.31623; + float sqrt42 = 0.15430; + float sqrt170 = 0.076696; + float val = 32768.0; + uint32_t i,j; + short* table; + + // QPSK + for (i=0; i<4; i++) { + nr_qpsk_mod_table[i*2] = (short)(1-2*(i&1))*val*sqrt2*sqrt2; + nr_qpsk_mod_table[i*2+1] = (short)(1-2*((i>>1)&1))*val*sqrt2*sqrt2; + //printf("%d j%d\n",nr_qpsk_mod_table[i*2],nr_qpsk_mod_table[i*2+1]); + } + +#if defined(__SSE2__) + //QPSK m128 + table = (short*) nr_qpsk_byte_mod_table; + for (i=0; i<256; i++) { + for (j=0; j<4; j++) { + table[i*8+(j*2)] = (short)(1-2*((i>>(j*2))&1))*val*sqrt2*sqrt2; + table[i*8+(j*2)+1] = (short)(1-2*((i>>(j*2+1))&1))*val*sqrt2*sqrt2; + //printf("%d j%d\n",nr_qpsk_byte_mod_table[i*8+(j*2)],nr_qpsk_byte_mod_table[i*8+(j*2)+1]); + } + } +#endif + + //16QAM + table = (short*) nr_16qam_byte_mod_table; + for (i=0; i<256; i++) { + for (j=0; j<2; j++) { + table[i*4+(j*2)] = (short)((1-2*((i>>(j*4))&1))*(2-(1-2*((i>>(j*4+2))&1))))*val*sqrt10*sqrt2; + table[i*4+(j*2)+1] = (short)((1-2*((i>>(j*4+1))&1))*(2-(1-2*((i>>(j*4+3))&1))))*val*sqrt10*sqrt2; + //printf("%d j%d\n",nr_16qam_byte_mod_table[i*4+(j*2)],nr_16qam_byte_mod_table[i*4+(j*2)+1]); + } + } + + table = (short*) nr_16qam_mod_table; + for (i=0; i<16; i++) { + table[i*2] = (short)((1-2*(i&1))*(2-(1-2*((i>>2)&1))))*val*sqrt10*sqrt2; + table[i*2+1] = (short)((1-2*((i>>1)&1))*(2-(1-2*((i>>3)&1))))*val*sqrt10*sqrt2; + //printf("%d j%d\n",table[i*2],table[i*2+1]); + } + + //64QAM + table = (short*) nr_64qam_mod_table; + for (i=0; i<4096; i++) { + for (j=0; j<2; j++) { + table[i*4+(j*2)] = (short)((1-2*((i>>(j*6))&1))*(4-(1-2*((i>>(j*6+2))&1))*(2-(1-2*((i>>(j*6+4))&1)))))*val*sqrt42*sqrt2; + table[i*4+(j*2)+1] = (short)((1-2*((i>>(j*6+1))&1))*(4-(1-2*((i>>(j*6+3))&1))*(2-(1-2*((i>>(j*6+5))&1)))))*val*sqrt42*sqrt2; + //printf("%d j%d\n",table[i*4+(j*2)],table[i*4+(j*2)+1]); + } + } + + //256QAM + table = (short*) nr_256qam_mod_table; + for (i=0; i<256; i++) { + table[i*2] = (short)((1-2*(i&1))*(8-(1-2*((i>>2)&1))*(4-(1-2*((i>>4)&1))*(2-(1-2*((i>>6)&1))))))*val*sqrt170*sqrt2; + table[i*2+1] = (short)((1-2*((i>>1)&1))*(8-(1-2*((i>>3)&1))*(4-(1-2*((i>>5)&1))*(2-(1-2*((i>>7)&1))))))*val*sqrt170*sqrt2; + } +} + diff --git a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m index 13a8d4ad09..6e1415bf28 100644 --- a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m +++ b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.m @@ -45,7 +45,7 @@ for r=0:1 %0 -- 1 LS for j=0:1 %0 -- 1 MS %% Formula is dispalayed -qpsk_table(2*r+j+1) = ((1-r*2)*QPSK + 1j*(1-2*j)*QPSK); +qpsk_table(2*j+r+1) = ((1-r*2)*QPSK + 1j*(1-2*j)*QPSK); end end @@ -61,7 +61,7 @@ for b0=0:1 for b1=0:1 for b2=0:1 for b3=0:1 -qam16_table2(b0*8+b1*4+b2*2+b3*1+1) = qam16_table(b0*2+b2*1+1) + 1j*qam16_table(b1*2+b3*1+1); +qam16_table2(b3*8+b2*4+b1*2+b0*1+1) = qam16_table(b0*2+b2*1+1) + 1j*qam16_table(b1*2+b3*1+1); end end end @@ -84,7 +84,7 @@ for b2=0:1 for b3=0:1 for b4=0:1 for b5=0:1 -qam64_table2(b0*32+b1*16+b2*8+b3*4+b4*2+b5*1+1) = qam64_table(b0*4+b2*2+b4*1+1) + 1j*qam64_table(b1*4+b3*2+b5*1+1); +qam64_table2(b5*32+b4*16+b3*8+b2*4+b1*2+b0*1+1) = qam64_table(b0*4+b2*2+b4*1+1) + 1j*qam64_table(b1*4+b3*2+b5*1+1); end end end @@ -116,7 +116,50 @@ for b6=0:1 for b7=0:1 %%qam64_table2(b0*32+b1*16+b2*8+b3*4+b4*2+b5*1+1) = qam64_table(b0*4+b2*2+b4*1+1) + 1j*qam64_table(b1*4+b3*2+b5*1+1); -qam256_table2(b0*128+b1*64+b2*32+b3*16+b4*8+b5*4+b6*2+b7*1+1) = qam256_table(b0*8+b2*4+b4*2+b6*1+1) + 1j*qam256_table(b1*8+b3*4+b5*2+b7*1+1); +qam256_table2(b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0*1+1) = qam256_table(b0*8+b2*4+b4*2+b6*1+1) + 1j*qam256_table(b1*8+b3*4+b5*2+b7*1+1); +end +end +end +end +end +end +end +end + +%%QPSK byte +for b0=0:1 +for b1=0:1 +for b2=0:1 +for b3=0:1 +for b4=0:1 +for b5=0:1 +for b6=0:1 +for b7=0:1 +qpsk_byte_table2(b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0*1+1,:)=[(1-b0*2)*QPSK (1-2*b1)*QPSK (1-b2*2)*QPSK (1-2*b3)*QPSK ... + (1-b4*2)*QPSK (1-2*b5)*QPSK (1-b6*2)*QPSK (1-2*b7)*QPSK]; + +end +end +end +end +end +end +end +end + +%%16QAM byte +qam16_byte_table2=[]; +for b0=0:1 +for b1=0:1 +for b2=0:1 +for b3=0:1 +for b4=0:1 +for b5=0:1 +for b6=0:1 +for b7=0:1 +qam16_byte_table2(b7*128+b6*64+b5*32+b4*16+b3*8+b2*4+b1*2+b0*1+1,:)=[qam16_table(b0*2+b2*1+1) qam16_table(b1*2+b3*1+1) ... + qam16_table(b4*2+b6*1+1) qam16_table(b5*2+b7*1+1) ]; + end end end @@ -133,6 +176,8 @@ save mod_table.mat table table2 = zeros(1,length(table)*2); table2(1:2:end) = real(table); table2(2:2:end) = imag(table); +qpsk_byte_table2=round(K * qpsk_byte_table2'(:)); +qam16_byte_table2=round(K * qam16_byte_table2'(:)); fd = fopen("nr_mod_table.h","w"); fprintf(fd,"#define NR_MOD_TABLE_SIZE_SHORT %d\n", length(table)*2); @@ -144,4 +189,10 @@ fprintf(fd,"#define NR_MOD_TABLE_QAM256_OFFSET %d\n", 87); fprintf(fd,"short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT] = {"); fprintf(fd,"%d,",table2(1:end-1)); fprintf(fd,"%d};\n",table2(end)); +fprintf(fd,"short nr_qpsk_mod_table[2048] = {"); +fprintf(fd,"%d,",qpsk_byte_table2(1:end-1)); +fprintf(fd,"%d};\n",qpsk_byte_table2(end)); +fprintf(fd,"short nr_qam16_mod_table[1024] = {"); +fprintf(fd,"%d,",qam16_byte_table2(1:end-1)); +fprintf(fd,"%d};\n",qam16_byte_table2(end)); fclose(fd); diff --git a/openair1/PHY/NR_REFSIG/nr_mod_table.h b/openair1/PHY/NR_REFSIG/nr_mod_table.h index c34dadb663..aa8b99f584 100644 --- a/openair1/PHY/NR_REFSIG/nr_mod_table.h +++ b/openair1/PHY/NR_REFSIG/nr_mod_table.h @@ -28,6 +28,17 @@ #define NR_MOD_TABLE_QAM16_OFFSET 7 #define NR_MOD_TABLE_QAM64_OFFSET 23 #define NR_MOD_TABLE_QAM256_OFFSET 87 -short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT] = {0,0,16384,16384,-16384,-16384,16384,16384,16384,-16384,-16384,16384,-16384,-16384,7327,7327,7327,21981,21981,7327,21981,21981,7327,-7327,7327,-21981,21981,-7327,21981,-21981,-7327,7327,-7327,21981,-21981,7327,-21981,21981,-7327,-7327,-7327,-21981,-21981,-7327,-21981,-21981,10726,10726,10726,3576,3576,10726,3576,3576,10726,17876,10726,25027,3576,17876,3576,25027,17876,10726,17876,3576,25027,10726,25027,3576,17876,17876,17876,25027,25027,17876,25027,25027,10726,-10726,10726,-3576,3576,-10726,3576,-3576,10726,-17876,10726,-25027,3576,-17876,3576,-25027,17876,-10726,17876,-3576,25027,-10726,25027,-3576,17876,-17876,17876,-25027,25027,-17876,25027,-25027,-10726,10726,-10726,3576,-3576,10726,-3576,3576,-10726,17876,-10726,25027,-3576,17876,-3576,25027,-17876,10726,-17876,3576,-25027,10726,-25027,3576,-17876,17876,-17876,25027,-25027,17876,-25027,25027,-10726,-10726,-10726,-3576,-3576,-10726,-3576,-3576,-10726,-17876,-10726,-25027,-3576,-17876,-3576,-25027,-17876,-10726,-17876,-3576,-25027,-10726,-25027,-3576,-17876,-17876,-17876,-25027,-25027,-17876,-25027,-25027,8886,8886,8886,12439,12439,8886,12439,12439,8886,5332,8886,1778,12439,5332,12439,1778,5332,8886,5332,12439,1778,8886,1778,12439,5332,5332,5332,1778,1778,5332,1778,1778,8886,19547,8886,15993,12439,19547,12439,15993,8886,23101,8886,26655,12439,23101,12439,26655,5332,19547,5332,15993,1778,19547,1778,15993,5332,23101,5332,26655,1778,23101,1778,26655,19547,8886,19547,12439,15993,8886,15993,12439,19547,5332,19547,1778,15993,5332,15993,1778,23101,8886,23101,12439,26655,8886,26655,12439,23101,5332,23101,1778,26655,5332,26655,1778,19547,19547,19547,15993,15993,19547,15993,15993,19547,23101,19547,26655,15993,23101,15993,26655,23101,19547,23101,15993,26655,19547,26655,15993,23101,23101,23101,26655,26655,23101,26655,26655,8886,-8886,8886,-12439,12439,-8886,12439,-12439,8886,-5332,8886,-1778,12439,-5332,12439,-1778,5332,-8886,5332,-12439,1778,-8886,1778,-12439,5332,-5332,5332,-1778,1778,-5332,1778,-1778,8886,-19547,8886,-15993,12439,-19547,12439,-15993,8886,-23101,8886,-26655,12439,-23101,12439,-26655,5332,-19547,5332,-15993,1778,-19547,1778,-15993,5332,-23101,5332,-26655,1778,-23101,1778,-26655,19547,-8886,19547,-12439,15993,-8886,15993,-12439,19547,-5332,19547,-1778,15993,-5332,15993,-1778,23101,-8886,23101,-12439,26655,-8886,26655,-12439,23101,-5332,23101,-1778,26655,-5332,26655,-1778,19547,-19547,19547,-15993,15993,-19547,15993,-15993,19547,-23101,19547,-26655,15993,-23101,15993,-26655,23101,-19547,23101,-15993,26655,-19547,26655,-15993,23101,-23101,23101,-26655,26655,-23101,26655,-26655,-8886,8886,-8886,12439,-12439,8886,-12439,12439,-8886,5332,-8886,1778,-12439,5332,-12439,1778,-5332,8886,-5332,12439,-1778,8886,-1778,12439,-5332,5332,-5332,1778,-1778,5332,-1778,1778,-8886,19547,-8886,15993,-12439,19547,-12439,15993,-8886,23101,-8886,26655,-12439,23101,-12439,26655,-5332,19547,-5332,15993,-1778,19547,-1778,15993,-5332,23101,-5332,26655,-1778,23101,-1778,26655,-19547,8886,-19547,12439,-15993,8886,-15993,12439,-19547,5332,-19547,1778,-15993,5332,-15993,1778,-23101,8886,-23101,12439,-26655,8886,-26655,12439,-23101,5332,-23101,1778,-26655,5332,-26655,1778,-19547,19547,-19547,15993,-15993,19547,-15993,15993,-19547,23101,-19547,26655,-15993,23101,-15993,26655,-23101,19547,-23101,15993,-26655,19547,-26655,15993,-23101,23101,-23101,26655,-26655,23101,-26655,26655,-8886,-8886,-8886,-12439,-12439,-8886,-12439,-12439,-8886,-5332,-8886,-1778,-12439,-5332,-12439,-1778,-5332,-8886,-5332,-12439,-1778,-8886,-1778,-12439,-5332,-5332,-5332,-1778,-1778,-5332,-1778,-1778,-8886,-19547,-8886,-15993,-12439,-19547,-12439,-15993,-8886,-23101,-8886,-26655,-12439,-23101,-12439,-26655,-5332,-19547,-5332,-15993,-1778,-19547,-1778,-15993,-5332,-23101,-5332,-26655,-1778,-23101,-1778,-26655,-19547,-8886,-19547,-12439,-15993,-8886,-15993,-12439,-19547,-5332,-19547,-1778,-15993,-5332,-15993,-1778,-23101,-8886,-23101,-12439,-26655,-8886,-26655,-12439,-23101,-5332,-23101,-1778,-26655,-5332,-26655,-1778,-19547,-19547,-19547,-15993,-15993,-19547,-15993,-15993,-19547,-23101,-19547,-26655,-15993,-23101,-15993,-26655,-23101,-19547,-23101,-15993,-26655,-19547,-26655,-15993,-23101,-23101,-23101,-26655,-26655,-23101,-26655,-26655}; +short nr_qpsk_mod_table[8]; + +int32_t nr_16qam_mod_table[16]; +#if defined(__SSE2__) +__m128i nr_qpsk_byte_mod_table[2048]; +#endif + +int64_t nr_16qam_byte_mod_table[1024]; + +int64_t nr_64qam_mod_table[4096]; + +int32_t nr_256qam_mod_table[512]; #endif diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index 1bf2ef4fb2..ced7f9eb66 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -52,8 +52,14 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, uint8_t dmrs_type); void init_scrambling_luts(void); +void nr_gen_ref_conj_symbols(uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order); +uint8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol); +uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb); + +void nr_generate_modulation_table(void); extern __m64 byte2m64_re[256]; extern __m64 byte2m64_im[256]; +extern __m128i byte2m128i[256]; #endif diff --git a/openair1/PHY/NR_REFSIG/scrambling_luts.c b/openair1/PHY/NR_REFSIG/scrambling_luts.c index 790d3f7719..3509291e42 100644 --- a/openair1/PHY/NR_REFSIG/scrambling_luts.c +++ b/openair1/PHY/NR_REFSIG/scrambling_luts.c @@ -32,6 +32,8 @@ __m64 byte2m64_re[256]; __m64 byte2m64_im[256]; +__m128i byte2m128i[256]; + void init_byte2m64(void) { for (int s=0;s<256;s++) { @@ -54,10 +56,24 @@ void init_byte2m64(void) { } } +void init_byte2m128i(void) { + + for (int s=0;s<256;s++) { + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*(s&1)),0); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>1)&1)),1); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>2)&1)),2); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>3)&1)),3); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>4)&1)),4); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>5)&1)),5); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>6)&1)),6); + byte2m128i[s] = _mm_insert_epi16(byte2m128i[s],(1-2*((s>>7)&1)),7); + } +} + void init_scrambling_luts(void) { init_byte2m64(); - + init_byte2m128i(); } #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index a29211b55b..ebcf4116d2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -154,14 +154,16 @@ void nr_pdcch_scrambling(uint32_t *in, } -uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu, + +uint8_t nr_generate_dci_top(PHY_VARS_gNB *gNB, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, + nfapi_nr_dl_tti_pdcch_pdu *ul_dci_pdu, uint32_t **gold_pdcch_dmrs, int32_t *txdataF, int16_t amp, NR_DL_FRAME_PARMS frame_parms) { - int16_t mod_dmrs[NR_MAX_CSET_DURATION][NR_MAX_PDCCH_DMRS_LENGTH>>1]; // 3 for the max coreset duration + int16_t mod_dmrs[NR_MAX_CSET_DURATION][NR_MAX_PDCCH_DMRS_LENGTH>>1] __attribute__((aligned(16))); // 3 for the max coreset duration uint16_t cset_start_sc; uint8_t cset_start_symb, cset_nsymb; int k,l,k_prime,dci_idx, dmrs_idx; @@ -180,15 +182,17 @@ uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, if (pdcch_pdu) pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15; - else if (ul_dci_pdu) pdcch_pdu_rel15 = &ul_dci_pdu->pdcch_pdu.pdcch_pdu_rel15; + else if (ul_dci_pdu) pdcch_pdu_rel15 = &ul_dci_pdu->pdcch_pdu_rel15; + + nr_fill_cce_list(gNB,0,pdcch_pdu_rel15); get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset); // compute rb_offset and n_prb based on frequency allocation if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_MIB_SIB1) { - cset_start_sc = frame_parms.first_carrier_offset + (frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB + - rb_offset)*NR_NB_SC_PER_RB; + cset_start_sc = frame_parms.first_carrier_offset + + (frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB + rb_offset)*NR_NB_SC_PER_RB; } else cset_start_sc = frame_parms.first_carrier_offset + rb_offset*NR_NB_SC_PER_RB; @@ -260,7 +264,7 @@ uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] ); #endif /// QPSK modulation - int16_t mod_dci[NR_MAX_DCI_SIZE>>1]; + int16_t mod_dci[NR_MAX_DCI_SIZE>>1] __attribute__((aligned(16))); nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, mod_dci); //Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_DCI @@ -324,6 +328,7 @@ uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, k -= frame_parms.ofdm_symbol_size; } // m } // reg_idx + } // for (int d=0;dnumDlDci;d++) return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.h b/openair1/PHY/NR_TRANSPORT/nr_dci.h index 047139aa63..288f525219 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.h @@ -29,9 +29,10 @@ uint16_t nr_get_dci_size(nfapi_nr_dci_format_e format, nfapi_nr_rnti_type_e rnti_type, uint16_t N_RB); -uint8_t nr_generate_dci_top(nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu, - uint32_t **gold_pdcch_dmrs, +uint8_t nr_generate_dci_top(PHY_VARS_gNB *gNB, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu, + nfapi_nr_dl_tti_pdcch_pdu *ul_pdcch_pdu, + uint32_t **gold_pdcch_dmrs, int32_t *txdataF, int16_t amp, NR_DL_FRAME_PARMS frame_parms); @@ -42,15 +43,21 @@ void nr_pdcch_scrambling(uint32_t *in, uint32_t n_RNTI, uint32_t *out); +int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type); + void nr_fill_dci(PHY_VARS_gNB *gNB, int frame, - int slot); + int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu); + +int16_t find_nr_ul_dci(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type); void nr_fill_ul_dci(PHY_VARS_gNB *gNB, int frame, - int slot); + int slot, + nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu); -void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m); +void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m,nfapi_nr_dl_tti_pdcch_pdu_rel15_t *); void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 02ecfc4404..2b64a3062c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -118,11 +118,11 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint16_t n_shift, uint8_t m) { */ -void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { +void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15) { nr_cce_t* cce; nr_reg_t* reg; - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu_rel15 = &gNB->pdcch_pdu->pdcch_pdu_rel15; + int bsize = pdcch_pdu_rel15->RegBundleSize; int R = pdcch_pdu_rel15->InterleaverSize; int n_shift = pdcch_pdu_rel15->ShiftIndex; @@ -139,6 +139,8 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { int N_reg = n_rb * pdcch_pdu_rel15->DurationSymbols; int C=-1; + AssertFatal(N_reg > 0,"N_reg cannot be 0\n"); + for (int d=0;dnumDlDci;d++) { int L = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; @@ -200,14 +202,38 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { ret |= ((field>>i)&1)<<(size-i-1); return ret; }*/ +int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) { + + uint16_t i; + int16_t first_free_index=-1; + + AssertFatal(gNB!=NULL,"gNB is null\n"); + for (i=0; ipdcch_pdu[i].frame,gNB->pdcch_pdu[i].slot,first_free_index); + if ((gNB->pdcch_pdu[i].frame == frame) && + (gNB->pdcch_pdu[i].slot==slot)) return i; + else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i; + } + if (type == SEARCH_EXIST) return -1; + + return first_free_index; +} + void nr_fill_dci(PHY_VARS_gNB *gNB, int frame, - int slot) { + int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu) { - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &gNB->pdcch_pdu->pdcch_pdu_rel15; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15; NR_gNB_DLSCH_t *dlsch; + int pdcch_id = find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST_OR_FREE); + AssertFatal(pdcch_id>=0 && pdcch_idpdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); + gNB->pdcch_pdu[pdcch_id].frame = frame; + gNB->pdcch_pdu[pdcch_id].slot = slot; + for (int i=0;inumDlDci;i++) { //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; @@ -230,7 +256,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, dlsch->harq_mask |= (1<rnti = pdcch_pdu_rel15->dci_pdu.RNTI[i]; - nr_fill_cce_list(gNB,0); + // nr_fill_cce_list(gNB,0); /* LOG_D(PHY, "DCI PDU: [0]->0x%lx \t [1]->0x%lx \n",dci_pdu[0], dci_pdu[1]); LOG_D(PHY, "DCI type %d payload (size %d) generated on candidate %d\n", dci_alloc->pdcch_params.dci_format, dci_alloc->size, cand_idx); @@ -239,19 +265,45 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, } } + + +int16_t find_nr_ul_dci(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) { + + uint16_t i; + int16_t first_free_index=-1; + + AssertFatal(gNB!=NULL,"gNB is null\n"); + for (i=0; iul_pdcch_pdu[i].frame,gNB->ul_pdcch_pdu[i].slot,first_free_index); + if ((gNB->ul_pdcch_pdu[i].frame == frame) && + (gNB->ul_pdcch_pdu[i].slot==slot)) return i; + else if (gNB->ul_pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i; + } + if (type == SEARCH_EXIST) return -1; + + return first_free_index; +} + + void nr_fill_ul_dci(PHY_VARS_gNB *gNB, int frame, - int slot) { + int slot, + nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu) { - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &gNB->ul_dci_pdu->pdcch_pdu.pdcch_pdu_rel15; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + int pdcch_id = find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST_OR_FREE); + AssertFatal(pdcch_id>=0 && pdcch_idul_pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); + gNB->ul_pdcch_pdu[pdcch_id].frame = frame; + gNB->ul_pdcch_pdu[pdcch_id].slot = slot; for (int i=0;inumDlDci;i++) { //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; // if there's no DL DCI then generate CCE list - if (gNB->pdcch_pdu) nr_fill_cce_list(gNB,0); + // nr_fill_cce_list(gNB,0); /* LOG_D(PHY, "DCI PDU: [0]->0x%lx \t [1]->0x%lx \n",dci_pdu[0], dci_pdu[1]); LOG_D(PHY, "DCI type %d payload (size %d) generated on candidate %d\n", dci_alloc->pdcch_params.dci_format, dci_alloc->size, cand_idx); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 23466132d6..4461edb33b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -109,220 +109,255 @@ void nr_pdsch_codeword_scrambling_optim(uint8_t *in, } -uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, - uint32_t ***pdsch_dmrs, - int32_t** txdataF, - int16_t amp, - int frame, - uint8_t slot, - NR_DL_FRAME_PARMS *frame_parms, - int xOverhead, - time_stats_t *dlsch_encoding_stats, - time_stats_t *dlsch_scrambling_stats, - time_stats_t *dlsch_modulation_stats, - time_stats_t *tinput, - time_stats_t *tprep, - time_stats_t *tparity, - time_stats_t *toutput, - time_stats_t *dlsch_rate_matching_stats, - time_stats_t *dlsch_interleaving_stats, - time_stats_t *dlsch_segmentation_stats) { +uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, + int frame, + int slot) { - int harq_pid = dlsch->harq_ids[frame%2][slot]; - NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; - uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; - int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; - int16_t **tx_layers = (int16_t**)dlsch->txdataF; - int8_t Wf[2], Wt[2], l0, l_prime[2], delta; - uint8_t dmrs_Type = rel15->dmrsConfigType; - int nb_re_dmrs; - uint16_t n_dmrs; - if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { - nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1; - } - else { - nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1; - } - uint16_t nb_re; - nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs-xOverhead)*rel15->rbSize*rel15->NrOfCodewords; - uint8_t Qm = rel15->qamModOrder[0]; - uint32_t encoded_length = nb_re*Qm; - int16_t mod_dmrs[n_dmrs<<1]; + NR_gNB_DLSCH_t *dlsch; + uint32_t ***pdsch_dmrs = gNB->nr_gold_pdsch_dmrs[slot]; + int32_t** txdataF = gNB->common_vars.txdataF; + int16_t amp = AMP; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + int xOverhead = 0; + time_stats_t *dlsch_encoding_stats=&gNB->dlsch_encoding_stats; + time_stats_t *dlsch_scrambling_stats=&gNB->dlsch_scrambling_stats; + time_stats_t *dlsch_modulation_stats=&gNB->dlsch_modulation_stats; + time_stats_t *tinput=&gNB->tinput; + time_stats_t *tprep=&gNB->tprep; + time_stats_t *tparity=&gNB->tparity; + time_stats_t *toutput=&gNB->toutput; + time_stats_t *dlsch_rate_matching_stats=&gNB->dlsch_rate_matching_stats; + time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats; + time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats; - /// CRC, coding, interleaving and rate matching - AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); - start_meas(dlsch_encoding_stats); - nr_dlsch_encoding(harq->pdu, frame, slot, dlsch, frame_parms,tinput,tprep,tparity,toutput, - dlsch_rate_matching_stats, - dlsch_interleaving_stats, - dlsch_segmentation_stats); - stop_meas(dlsch_encoding_stats); + for (int dlsch_id=0;dlsch_iddlsch[dlsch_id][0]; + if (dlsch->slot_tx[slot] == 0) continue; + + int harq_pid = dlsch->harq_ids[frame%2][slot]; + NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; + int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; + int16_t **tx_layers = (int16_t**)dlsch->txdataF; + int8_t Wf[2], Wt[2], l0, l_prime[2], delta; + uint8_t dmrs_Type = rel15->dmrsConfigType; + int nb_re_dmrs; + uint16_t n_dmrs; + if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; + n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1; + } + else { + nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; + n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1; + } + uint16_t nb_re; + nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs-xOverhead)*rel15->rbSize*rel15->NrOfCodewords; + uint8_t Qm = rel15->qamModOrder[0]; + uint32_t encoded_length = nb_re*Qm; + int16_t mod_dmrs[n_dmrs<<1] __attribute__ ((aligned(16))); + + + /// CRC, coding, interleaving and rate matching + AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); + start_meas(dlsch_encoding_stats); + nr_dlsch_encoding(gNB, + harq->pdu, frame, slot, dlsch, frame_parms,tinput,tprep,tparity,toutput, + dlsch_rate_matching_stats, + dlsch_interleaving_stats, + dlsch_segmentation_stats); + stop_meas(dlsch_encoding_stats); #ifdef DEBUG_DLSCH - printf("PDSCH encoding:\nPayload:\n"); - for (int i=0; iB>>7; i++) { - for (int j=0; j<16; j++) - printf("0x%02x\t", harq->pdu[(i<<4)+j]); - printf("\n"); - } - printf("\nEncoded payload:\n"); - for (int i=0; i>3; i++) { - for (int j=0; j<8; j++) - printf("%d", harq->f[(i<<3)+j]); - printf("\t"); - } - printf("\n"); -#endif - - - - /// scrambling - start_meas(dlsch_scrambling_stats); - for (int q=0; qNrOfCodewords; q++) - memset((void*)scrambled_output[q], 0, (encoded_length>>5)*sizeof(uint32_t)); - for (int q=0; qNrOfCodewords; q++) - nr_pdsch_codeword_scrambling_optim(harq->f, - encoded_length, - q, - rel15->dlDmrsScramblingId, - rel15->rnti, - scrambled_output[q]); - - stop_meas(dlsch_scrambling_stats); -#ifdef DEBUG_DLSCH - printf("PDSCH scrambling:\n"); - for (int i=0; i>8; i++) { - for (int j=0; j<8; j++) - printf("0x%08x\t", scrambled_output[0][(i<<3)+j]); - printf("\n"); - } -#endif - - /// Modulation - start_meas(dlsch_modulation_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 1); - for (int q=0; qNrOfCodewords; q++) - nr_modulation(scrambled_output[q], - encoded_length, - Qm, - mod_symbs[q]); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 0); - stop_meas(dlsch_modulation_stats); -#ifdef DEBUG_DLSCH - printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_re); - for (int i=0; i>3; i++) { - for (int j=0; j<8; j++) { - printf("%d %d\t", mod_symbs[0][((i<<3)+j)<<1], mod_symbs[0][(((i<<3)+j)<<1)+1]); + printf("PDSCH encoding:\nPayload:\n"); + for (int i=0; iB>>7; i++) { + for (int j=0; j<16; j++) + printf("0x%02x\t", harq->pdu[(i<<4)+j]); + printf("\n"); + } + printf("\nEncoded payload:\n"); + for (int i=0; i>3; i++) { + for (int j=0; j<8; j++) + printf("%d", harq->f[(i<<3)+j]); + printf("\t"); } printf("\n"); - } #endif - - - /// Layer mapping - nr_layer_mapping(mod_symbs, - rel15->nrOfLayers, - nb_re, - tx_layers); + + + + /// scrambling + start_meas(dlsch_scrambling_stats); + for (int q=0; qNrOfCodewords; q++) + memset((void*)scrambled_output[q], 0, (encoded_length>>5)*sizeof(uint32_t)); + for (int q=0; qNrOfCodewords; q++) + nr_pdsch_codeword_scrambling_optim(harq->f, + encoded_length, + q, + rel15->dlDmrsScramblingId, + rel15->rnti, + scrambled_output[q]); + + stop_meas(dlsch_scrambling_stats); #ifdef DEBUG_DLSCH - printf("Layer mapping (%d layers):\n", rel15->nrOfLayers); - for (int l=0; lnrOfLayers; l++) - for (int i=0; i<(nb_re/rel15->nrOfLayers)>>3; i++) { - printf("layer %d, Re %d..%d : ",l,i<<3,(i<<3)+7); + printf("PDSCH scrambling:\n"); + for (int i=0; i>8; i++) { + for (int j=0; j<8; j++) + printf("0x%08x\t", scrambled_output[0][(i<<3)+j]); + printf("\n"); + } +#endif + + /// Modulation + start_meas(dlsch_modulation_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 1); + for (int q=0; qNrOfCodewords; q++) + nr_modulation(scrambled_output[q], + encoded_length, + Qm, + mod_symbs[q]); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 0); + stop_meas(dlsch_modulation_stats); +#ifdef DEBUG_DLSCH + printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_re); + for (int i=0; i>3; i++) { for (int j=0; j<8; j++) { - printf("l%d %d\t", tx_layers[l][((i<<3)+j)<<1], tx_layers[l][(((i<<3)+j)<<1)+1]); + printf("%d %d\t", mod_symbs[0][((i<<3)+j)<<1], mod_symbs[0][(((i<<3)+j)<<1)+1]); } printf("\n"); } #endif - - /// Antenna port mapping - //to be moved to init phase potentially, for now tx_layers 1-8 are mapped on antenna ports 1000-1007 - - /// DMRS QPSK modulation - - - l0 = get_l0(rel15->dlDmrsSymbPos); - nr_modulation(pdsch_dmrs[l0][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated - + + + /// Layer mapping + nr_layer_mapping(mod_symbs, + rel15->nrOfLayers, + nb_re, + tx_layers); #ifdef DEBUG_DLSCH - printf("DMRS modulation (single symbol %d, %d symbols, type %d):\n", l0, n_dmrs>>1, dmrs_Type); - for (int i=0; i>4; i++) { - for (int j=0; j<8; j++) { - printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]); + printf("Layer mapping (%d layers):\n", rel15->nrOfLayers); + for (int l=0; lnrOfLayers; l++) + for (int i=0; i<(nb_re/rel15->nrOfLayers)>>3; i++) { + printf("layer %d, Re %d..%d : ",l,i<<3,(i<<3)+7); + for (int j=0; j<8; j++) { + printf("l%d %d\t", tx_layers[l][((i<<3)+j)<<1], tx_layers[l][(((i<<3)+j)<<1)+1]); + } + printf("\n"); + } +#endif + + /// Antenna port mapping + //to be moved to init phase potentially, for now tx_layers 1-8 are mapped on antenna ports 1000-1007 + + /// DMRS QPSK modulation + + + l0 = get_l0(rel15->dlDmrsSymbPos); + nr_modulation(pdsch_dmrs[l0][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + +#ifdef DEBUG_DLSCH + printf("DMRS modulation (single symbol %d, %d symbols, type %d):\n", l0, n_dmrs>>1, dmrs_Type); + for (int i=0; i>4; i++) { + for (int j=0; j<8; j++) { + printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]); + } + printf("\n"); } - printf("\n"); - } #endif - - - /// Resource mapping - - // Non interleaved VRB to PRB mapping - uint16_t start_sc = frame_parms->first_carrier_offset + rel15->rbStart*NR_NB_SC_PER_RB; - if (start_sc >= frame_parms->ofdm_symbol_size) - start_sc -= frame_parms->ofdm_symbol_size; - + + + /// Resource mapping + + // Non interleaved VRB to PRB mapping + uint16_t start_sc = frame_parms->first_carrier_offset + rel15->rbStart*NR_NB_SC_PER_RB; + if (start_sc >= frame_parms->ofdm_symbol_size) + start_sc -= frame_parms->ofdm_symbol_size; + #ifdef DEBUG_DLSCH_MAPPING - printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", - start_sc, rel15->StartSymbolIndex, rel15->rbSize, nb_re,rel15->nrOfLayers); + printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", + start_sc, rel15->StartSymbolIndex, rel15->rbSize, nb_re,rel15->nrOfLayers); #endif - for (int ap=0; apnrOfLayers; ap++) { - - // DMRS params for this ap - get_Wt(Wt, ap, dmrs_Type); - get_Wf(Wf, ap, dmrs_Type); - delta = get_delta(ap, dmrs_Type); - l_prime[0] = 0; // single symbol ap 0 - uint8_t dmrs_symbol = l0+l_prime[0]; + for (int ap=0; apnrOfLayers; ap++) { + + // DMRS params for this ap + get_Wt(Wt, ap, dmrs_Type); + get_Wf(Wf, ap, dmrs_Type); + delta = get_delta(ap, dmrs_Type); + l_prime[0] = 0; // single symbol ap 0 + uint8_t dmrs_symbol = l0+l_prime[0]; #ifdef DEBUG_DLSCH_MAPPING - printf("DMRS Type %d params for ap %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n", - 1+dmrs_Type,ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol); + printf("DMRS Type %d params for ap %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n", + 1+dmrs_Type,ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol); #endif - uint8_t k_prime=0; - uint16_t m=0, n=0, dmrs_idx=0, k=0; - - int txdataF_offset = (slot%2)*frame_parms->samples_per_slot_wCP; - if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k) - dmrs_idx = rel15->rbStart*6; - else - dmrs_idx = rel15->rbStart*4; - - for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { - k = start_sc; - for (int i=0; irbSize*NR_NB_SC_PER_RB; i++) { - if ((l == dmrs_symbol) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) { - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (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 + (2*txdataF_offset)] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + uint8_t k_prime=0; + uint16_t m=0, n=0, dmrs_idx=0, k=0; + + int txdataF_offset = (slot%2)*frame_parms->samples_per_slot_wCP; + if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k) + dmrs_idx = rel15->rbStart*6; + else + dmrs_idx = rel15->rbStart*4; + + for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { + k = start_sc; + for (int i=0; irbSize*NR_NB_SC_PER_RB; i++) { + if ((l == dmrs_symbol) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) { + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (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 + (2*txdataF_offset)] = (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) + (2*txdataF_offset)], - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); -#endif - dmrs_idx++; - k_prime++; - k_prime&=1; - n+=(k_prime)?0:1; - } - - else { - if( (l != dmrs_symbol) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15; - ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (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) + (2*txdataF_offset)], + 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) + (2*txdataF_offset)], ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); #endif - m++; - } - } - if (++k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; - } - } - } + dmrs_idx++; + k_prime++; + k_prime&=1; + n+=(k_prime)?0:1; + } + + else { + if( (l != dmrs_symbol) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15; + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (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) + (2*txdataF_offset)], + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); +#endif + m++; + } + } + if (++k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; + } //RE loop + } // symbol loop + }// layer loop + dlsch->slot_tx[slot]=0; + }// dlsch loop return 0; } + +void dump_pdsch_stats(PHY_VARS_gNB *gNB) { + + for (int i=0;idlsch_stats[i].rnti > 0) + LOG_I(PHY,"DLSCH RNTI %x: round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, current_Qm %d, current_RI %d, total_bytes TX %d\n", + gNB->dlsch_stats[i].rnti, + gNB->dlsch_stats[i].round_trials[0], + (double)gNB->dlsch_stats[i].round_trials[1]/gNB->dlsch_stats[i].round_trials[0], + gNB->dlsch_stats[i].round_trials[1], + (double)gNB->dlsch_stats[i].round_trials[2]/gNB->dlsch_stats[i].round_trials[0], + gNB->dlsch_stats[i].round_trials[2], + (double)gNB->dlsch_stats[i].round_trials[3]/gNB->dlsch_stats[i].round_trials[0], + gNB->dlsch_stats[i].round_trials[3], + gNB->dlsch_stats[i].current_Qm, + gNB->dlsch_stats[i].current_RI, + gNB->dlsch_stats[i].total_bytes_tx); + +} + +void clear_pdsch_stats(PHY_VARS_gNB *gNB) { + + for (int i=0;idlsch_stats[i],0,sizeof(gNB->dlsch_stats[i])); +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 3a6851ee8f..23ec756531 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -69,27 +69,9 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, unsigned char *sdu); -uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, - uint32_t ***pdsch_dmrs, - int32_t** txdataF, - int16_t amp, - int frame, - uint8_t slot, - NR_DL_FRAME_PARMS *frame_parms, - int xOverhead, - time_stats_t *dlsch_encoding_stats, - time_stats_t *dlsch_scrambling_stats, - time_stats_t *dlsch_modulation_stats, - time_stats_t *tinput, - time_stats_t *tprep, - time_stats_t *tparity, - time_stats_t *toutput, - time_stats_t *dlsch_rate_matching_stats, - time_stats_t *dlsch_interleaving_stats, - time_stats_t *dlsch_segmentation_stats); - - - +uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, + int frame, + int slot); void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB); void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); @@ -98,7 +80,10 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch); int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); -int nr_dlsch_encoding(unsigned char *a,int frame, +NR_gNB_SCH_STATS_t *find_nr_dlsch_stats(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); + +int nr_dlsch_encoding(PHY_VARS_gNB *gNB, + unsigned char *a,int frame, uint8_t slot, NR_gNB_DLSCH_t *dlsch, NR_DL_FRAME_PARMS* frame_parms, @@ -113,4 +98,8 @@ int nr_dlsch_encoding(unsigned char *a,int frame, void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size); +void dump_pdsch_stats(PHY_VARS_gNB *gNB); + +void clear_pdsch_stats(PHY_VARS_gNB *gNB); + #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 2f55bde321..e5841d3262 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -61,7 +61,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) if (N_RB != 273) { a_segments = a_segments*N_RB; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } @@ -150,7 +150,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, if (N_RB != 273) { a_segments = a_segments*N_RB; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment @@ -309,7 +309,8 @@ void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) } } -int nr_dlsch_encoding(unsigned char *a, +int nr_dlsch_encoding(PHY_VARS_gNB *gNB, + unsigned char *a, int frame, uint8_t slot, NR_gNB_DLSCH_t *dlsch, @@ -326,7 +327,8 @@ int nr_dlsch_encoding(unsigned char *a, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15; uint16_t nb_rb = rel15->rbSize; uint8_t nb_symb_sch = rel15->NrOfSymbols; - uint32_t A, Z, Kb, F=0; + uint32_t A, Kb, F=0; + static uint32_t Z = 0; uint32_t *Zc = &Z; uint8_t mod_order = rel15->qamModOrder[0]; uint16_t Kr=0,r; @@ -347,10 +349,34 @@ int nr_dlsch_encoding(unsigned char *a, float Coderate = 0.0; uint8_t Nl = 4; + dlsch->harq_processes[harq_pid]->round = nr_rv_round_map[rel15->rvIndex[0]]; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); A = rel15->TBSize[0]<<3; + NR_gNB_SCH_STATS_t *stats=NULL; + int first_free=-1; + for (int i=0;idlsch_stats[i].rnti == 0 && first_free == -1) { + first_free = i; + stats=&gNB->dlsch_stats[i]; + } + if (gNB->dlsch_stats[i].rnti == dlsch->rnti) { + stats=&gNB->dlsch_stats[i]; + break; + } + } + + if (stats) { + stats->round_trials[dlsch->harq_processes[harq_pid]->round]++; + stats->rnti = dlsch->rnti; + if (dlsch->harq_processes[harq_pid]->round == 0){ + stats->total_bytes_tx += rel15->TBSize[0]; + stats->current_RI = rel15->nrOfLayers; + stats->current_Qm = rel15->qamModOrder[0]; + } + } G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); LOG_D(PHY,"dlsch coding A %d G %d mod_order %d\n", A,G, mod_order); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 7702d770ee..5ce2c45a7d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -255,27 +255,28 @@ void nr_emulate_dlsch_payload(uint8_t* pdu, uint16_t size) { } int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { - - uint16_t i; - int16_t first_free_index=-1; - - AssertFatal(gNB!=NULL,"gNB is null\n"); - for (i=0; idlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i); - AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i); - LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); - if ((gNB->dlsch[i][0]->harq_mask >0) && - (gNB->dlsch[i][0]->rnti==rnti)) return i; - else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; - } - if (type == SEARCH_EXIST) return -1; - if (first_free_index != -1) - gNB->dlsch[first_free_index][0]->rnti = 0; - return first_free_index; + + uint16_t i; + int16_t first_free_index=-1; + + AssertFatal(gNB!=NULL,"gNB is null\n"); + for (i=0; idlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i); + AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i); + LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, + gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); + if ((gNB->dlsch[i][0]->harq_mask >0) && + (gNB->dlsch[i][0]->rnti==rnti)) return i; + else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + } + if (type == SEARCH_EXIST) return -1; + if (first_free_index != -1) + gNB->dlsch[first_free_index][0]->rnti = 0; + return first_free_index; + } - void nr_fill_dlsch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -291,7 +292,7 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB, NR_DL_gNB_HARQ_t **harq = dlsch->harq_processes; /// DLSCH struct memcpy((void*)&harq[dlsch->harq_ids[frame%2][slot]]->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - gNB->num_pdsch_rnti++; + gNB->num_pdsch_rnti[slot]++; AssertFatal(sdu!=NULL,"sdu is null\n"); harq[dlsch->harq_ids[frame%2][slot]]->pdu = sdu; diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index bc33d93811..bd1278b2eb 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -40,7 +40,7 @@ //#define DEBUG_PBCH_ENCODING //#define DEBUG_PBCH_DMRS -extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT]; +extern short nr_qpsk_mod_table[8]; 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 @@ -61,9 +61,9 @@ int nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, /// QPSK modulation for (int m=0; m>5])>>((m<<1)&0x1f))&1)<<1) ^ (((gold_pbch_dmrs[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1); - 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]; + idx = (((gold_pbch_dmrs[(m<<1)>>5])>>((m<<1)&0x1f))&3); + mod_dmrs[m<<1] = nr_qpsk_mod_table[idx<<1]; + mod_dmrs[(m<<1)+1] = nr_qpsk_mod_table[(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]); @@ -323,9 +323,9 @@ int nr_generate_pbch(NR_gNB_PBCH *pbch, /// QPSK modulation 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]; + idx = ((pbch->pbch_e[(i<<1)>>5]>>((i<<1)&0x1f))&3); + mod_pbch_e[i<<1] = nr_qpsk_mod_table[idx<<1]; + mod_pbch_e[(i<<1)+1] = nr_qpsk_mod_table[(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]); #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 0e9efdce85..52cf19be09 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -37,7 +37,6 @@ extern uint16_t prach_root_sequence_map_0_3[838]; extern uint16_t prach_root_sequence_map_abc[138]; extern uint16_t nr_du[838]; -extern int16_t nr_ru[2*839]; extern const char *prachfmt[9]; void init_prach_list(PHY_VARS_gNB *gNB) { @@ -567,7 +566,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, uint16_t rootSequenceIndex; int numrootSequenceIndex; uint8_t restricted_set; - uint8_t n_ra_prb; + uint8_t n_ra_prb=0xFF; int16_t *prachF=NULL; int nb_rx; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 543042ff32..417f0d41a3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -344,9 +344,15 @@ void nr_decode_pucch1(int32_t **rxdataF, uint8_t timeDomainOCC, uint8_t nr_bit); +void nr_decode_pucch2(PHY_VARS_gNB *gNB, + int slot, + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, + nfapi_nr_pucch_pdu_t* pucch_pdu); + void nr_decode_pucch0(PHY_VARS_gNB *gNB, - int slot, + int slot, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu); + #endif /*__NR_TRANSPORT__H__*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 3622e61b61..0040f01544 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -33,7 +33,7 @@ #include #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h" -#include "PHY/LTE_REFSIG/lte_refsig.h" +#include "PHY/NR_REFSIG/nr_refsig.h" int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { @@ -103,3 +103,62 @@ void nr_ulsch_unscrambling(int16_t* llr, llr[i] = -llr[i]; } } + +void nr_ulsch_unscrambling_optim(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI) { + +#if defined(__x86_64__) || defined(__i386__) + uint32_t x1, x2, s=0; + + x2 = (n_RNTI<<15) + Nid; + + uint8_t *s8=(uint8_t *)&s; + __m128i *llr128 = (__m128i*)llr; + int j=0; + s = lte_gold_generic(&x1, &x2, 1); + + for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++,j+=4) { + llr128[j] = _mm_mullo_epi16(llr128[j],byte2m128i[s8[0]]); + llr128[j+1] = _mm_mullo_epi16(llr128[j+1],byte2m128i[s8[1]]); + llr128[j+2] = _mm_mullo_epi16(llr128[j+2],byte2m128i[s8[2]]); + llr128[j+3] = _mm_mullo_epi16(llr128[j+3],byte2m128i[s8[3]]); + s = lte_gold_generic(&x1, &x2, 0); + } +#else + + nr_ulsch_unscrambling(llr, + size, + q, + Nid, + n_RNTI); +#endif +} + +void dump_pusch_stats(PHY_VARS_gNB *gNB) { + + for (int i=0;iulsch_stats[i].rnti>0) + LOG_I(PHY,"ULSCH RNTI %x: round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, current_Qm %d, current_RI %d, total_bytes RX/SCHED %d/%d\n", + gNB->ulsch_stats[i].rnti, + gNB->ulsch_stats[i].round_trials[0], + (double)gNB->ulsch_stats[i].round_trials[1]/gNB->ulsch_stats[i].round_trials[0], + gNB->ulsch_stats[i].round_trials[1], + (double)gNB->ulsch_stats[i].round_trials[2]/gNB->ulsch_stats[i].round_trials[0], + gNB->ulsch_stats[i].round_trials[2], + (double)gNB->ulsch_stats[i].round_trials[3]/gNB->ulsch_stats[i].round_trials[0], + gNB->ulsch_stats[i].round_trials[3], + gNB->ulsch_stats[i].current_Qm, + gNB->ulsch_stats[i].current_RI, + gNB->ulsch_stats[i].total_bytes_rx, + gNB->ulsch_stats[i].total_bytes_tx); + +} + +void clear_pusch_stats(PHY_VARS_gNB *gNB) { + + for (int i=0;iulsch_stats[i],0,sizeof(gNB->ulsch_stats[i])); +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index 7ff52ae692..a9845b6bbb 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -75,9 +75,19 @@ void nr_ulsch_unscrambling(int16_t* llr, uint32_t n_RNTI); +void nr_ulsch_unscrambling_optim(int16_t* llr, + uint32_t size, + uint8_t q, + uint32_t Nid, + uint32_t n_RNTI); + void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int UE_id, uint8_t harq_pid); int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); + +void dump_pusch_stats(PHY_VARS_gNB *gNB); + +void clear_pusch_stats(PHY_VARS_gNB *gNB); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index e00975eee1..7980206eb4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -67,7 +67,7 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr,uint8_t N_RB_UL) if (ulsch) { if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } @@ -119,11 +119,10 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint16_t N_RB_UL, uint if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment - ulsch = (NR_gNB_ULSCH_t *)malloc16(sizeof(NR_gNB_ULSCH_t)); if (ulsch) { @@ -209,8 +208,6 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch) ulsch->Mlimit = 0; ulsch->max_ldpc_iterations = 0; ulsch->last_iteration_cnt = 0; - ulsch->num_active_cba_groups = 0; - for (i=0;icba_rnti[i] = 0; for (i=0;iharq_process_id[i] = 0; for (i=0; iharq_processes[i]->rar_alloc=0; ulsch->harq_processes[i]->status=NR_SCH_IDLE; ulsch->harq_processes[i]->subframe_scheduling_flag=0; - ulsch->harq_processes[i]->subframe_cba_scheduling_flag=0; ulsch->harq_processes[i]->phich_active=0; ulsch->harq_processes[i]->phich_ACK=0; ulsch->harq_processes[i]->previous_first_rb=0; @@ -290,7 +286,7 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch) static uint32_t prnt_crc_cnt = 0; #endif -uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, +uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB, uint8_t UE_id, short *ulsch_llr, NR_DL_FRAME_PARMS *frame_parms, @@ -312,7 +308,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, #endif - NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0]; + NR_gNB_ULSCH_t *ulsch = gNB->ulsch[UE_id][0]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; t_nrLDPC_dec_params decParams; @@ -360,28 +356,21 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,1); harq_process->TBS = pusch_pdu->pusch_data.tb_size; + harq_process->round = nr_rv_round_map[pusch_pdu->pusch_data.rv_index]; A = (harq_process->TBS)<<3; ret = ulsch->max_ldpc_iterations + 1; LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers); - if (harq_process->round == 0) { - - // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) - harq_process->B = A+24; - else - harq_process->B = A+16; - - if (R<1024) - Coderate = (float) R /(float) 1024; - else - Coderate = (float) R /(float) 2048; - - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25){ - p_decParams->BG = 2; - if (Coderate < 0.3333) { + if (R<1024) + Coderate = (float) R /(float) 1024; + else + Coderate = (float) R /(float) 2048; + + 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; } @@ -408,6 +397,34 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, kc = 27; } } + + NR_gNB_SCH_STATS_t *stats=NULL; + int first_free=-1; + for (int i=0;iulsch_stats[i].rnti == 0 && first_free == -1) { + first_free = i; + stats=&gNB->ulsch_stats[i]; + } + if (gNB->ulsch_stats[i].rnti == ulsch->rnti) { + stats=&gNB->ulsch_stats[i]; + break; + } + } + if (stats) { + stats->rnti = ulsch->rnti; + stats->round_trials[harq_process->round]++; + } + if (harq_process->round == 0) { + if (stats) { + stats->current_Qm = Qm; + stats->current_RI = n_layers; + stats->total_bytes_tx += harq_process->TBS; + } + // This is a new packet, so compute quantities regarding segmentation + if (A > 3824) + harq_process->B = A+24; + else + harq_process->B = A+16; // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F) nr_segmentation(NULL, @@ -438,7 +455,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, if (nb_rb != 273) { a_segments = a_segments*nb_rb; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } if (harq_process->C > a_segments) { @@ -460,7 +477,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, E = nr_get_E(G, harq_process->C, Qm, n_layers, r); - start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + start_meas(&gNB->ulsch_deinterleaving_stats); //////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// @@ -476,11 +493,10 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, //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); - stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + stop_meas(&gNB->ulsch_deinterleaving_stats); -#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", + 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, rvidx %d, round %d)...\n", harq_pid,r, G, Kr*3, harq_process->TBS, @@ -489,7 +505,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, n_layers, pusch_pdu->pusch_data.rv_index, harq_process->round); -#endif ////////////////////////////////////////////////////////////////////////////////////////// @@ -499,7 +514,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ///////////////////////// harq_process->e =====> harq_process->d ///////////////////////// - start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + start_meas(&gNB->ulsch_rate_unmatching_stats); Tbslbrm = nr_compute_tbslbrm(0,nb_rb,n_layers,harq_process->C); @@ -516,12 +531,12 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, harq_process->F, Kr-harq_process->F-2*(p_decParams->Z))==-1) { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + stop_meas(&gNB->ulsch_rate_unmatching_stats); LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n"); return (ulsch->max_ldpc_iterations + 1); } else { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + stop_meas(&gNB->ulsch_rate_unmatching_stats); } r_offset += E; @@ -559,7 +574,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, if (err_flag == 0) { - start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); + start_meas(&gNB->ulsch_ldpc_decoding_stats); //LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A); @@ -573,7 +588,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, AssertFatal(kc!=255,""); j+=(harq_process->F>>3); - // for (i=Kr_bytes,j=K_bytes_F-((2*p_decParams->Z)>>3); i < ((kc*p_decParams->Z)>>3); i++, j++) { for (i=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) { pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j])); } @@ -628,7 +642,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4); #endif - stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); + stop_meas(&gNB->ulsch_ldpc_decoding_stats); } if ((err_flag == 0) && (ret >= (ulsch->max_ldpc_iterations + 1))) { @@ -651,7 +665,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, #ifdef gNB_DEBUG_TRACE LOG_I(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d) Kr %d r %d\n", - phy_vars_gNB->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,Kr,r); + gNB->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,Kr,r); #endif // harq_process->harq_ack.ack = 0; @@ -668,7 +682,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, } // 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); + // gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->status,harq_process->round,ulsch->Mlimit,harq_process->TBS); harq_process->handled = 1; ret = ulsch->max_ldpc_iterations + 1; @@ -677,18 +691,18 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, #ifdef gNB_DEBUG_TRACE LOG_I(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d TBS %d\n", - phy_vars_gNB->Mod_id,nr_tti_rx,harq_process->TBS); + gNB->Mod_id,nr_tti_rx,harq_process->TBS); #endif harq_process->status = SCH_IDLE; harq_process->round = 0; // harq_process->handled = 0; - ulsch->harq_mask &= ~(1 << harq_pid); + 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; - // 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); + // LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->round,harq_process->TBS); // Reassembly of Transport block here @@ -711,14 +725,15 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, #endif } + if (stats) stats->total_bytes_rx += harq_process->TBS; } #ifdef DEBUG_ULSCH_DECODING - LOG_I(PHY, "Decoder output (payload): \n"); - for (i = 0; i < harq_process->TBS ; i++) { + LOG_I(PHY, "Decoder output (payload) at SFN/SF: %d/%d TBS: %d\n", frame, nr_tti_rx,harq_process->TBS); + for (i = 0; i < harq_process->TBS; i++) { //harq_process_ul_ue->a[i] = (unsigned char) rand(); //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - printf("%02x",harq_process->b[i]); + printf("%02x ",harq_process->b[i]); } #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index a966db5844..3fd7966ce7 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -232,18 +232,13 @@ void nr_ulsch_extract_rbs_single(int32_t **rxdataF, unsigned short start_re, re, nb_re_pusch; unsigned char aarx; - uint8_t K_ptrs = 0; uint32_t rxF_ext_index = 0; uint32_t ul_ch0_ext_index = 0; uint32_t ul_ch0_index = 0; - uint32_t ul_ch0_ptrs_ext_index = 0; - uint32_t ul_ch0_ptrs_index = 0; - uint8_t is_ptrs_symbol_flag,k_prime; - uint16_t n=0, num_ptrs_symbols; + uint8_t k_prime; + uint16_t n; int16_t *rxF,*rxF_ext; int *ul_ch0,*ul_ch0_ext; - int *ul_ch0_ptrs,*ul_ch0_ptrs_ext; - uint16_t n_rnti = pusch_pdu->rnti; uint8_t delta = 0; #ifdef DEBUG_RB_EXT @@ -252,84 +247,74 @@ void nr_ulsch_extract_rbs_single(int32_t **rxdataF, printf("--------------------ch_ext_index = %d-----------------------\n", symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size); #endif - + uint8_t is_dmrs_re; start_re = (frame_parms->first_carrier_offset + (pusch_pdu->rb_start * NR_NB_SC_PER_RB))%frame_parms->ofdm_symbol_size; nb_re_pusch = NR_NB_SC_PER_RB * pusch_pdu->rb_size; - is_ptrs_symbol_flag = 0; - num_ptrs_symbols = 0; +#ifdef __AVX2__ + int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); +#else + int nb_re_pusch2 = nb_re_pusch; +#endif for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - + rxF = (int16_t *)&rxdataF[aarx][symbol * frame_parms->ofdm_symbol_size]; - rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6 + rxF_ext = (int16_t *)&pusch_vars->rxdataF_ext[aarx][symbol * nb_re_pusch2]; // [hna] rxdataF_ext isn't contiguous in order to solve an alignment problem ib llr computation in case of mod_order = 4, 6 ul_ch0 = &pusch_vars->ul_ch_estimates[aarx][pusch_vars->dmrs_symbol*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aarx][symbol*nb_re_pusch]; - - ul_ch0_ptrs = &pusch_vars->ul_ch_ptrs_estimates[aarx][pusch_vars->ptrs_symbol_index*frame_parms->ofdm_symbol_size]; // update channel estimates if new dmrs symbol are available - - ul_ch0_ptrs_ext = &pusch_vars->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch]; + ul_ch0_ext = &pusch_vars->ul_ch_estimates_ext[aarx][symbol*nb_re_pusch2]; n = 0; k_prime = 0; - for (re = 0; re < nb_re_pusch; re++) { - - if (is_dmrs_symbol) - is_dmrs_re = (re == get_dmrs_freq_idx_ul(n, k_prime, delta, pusch_pdu->dmrs_config_type)); - else - is_dmrs_re = 0; - - if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - K_ptrs = (pusch_pdu->pusch_ptrs.ptrs_freq_density)?4:2; - if(is_ptrs_symbol(symbol, pusch_vars->ptrs_symbols)) - is_ptrs_symbol_flag = is_ptrs_subcarrier((start_re + re) % frame_parms->ofdm_symbol_size, - n_rnti, - aarx, - pusch_pdu->dmrs_config_type, - K_ptrs, - pusch_pdu->rb_size, - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset, - start_re, - frame_parms->ofdm_symbol_size); - - if (is_ptrs_symbol_flag == 1) - num_ptrs_symbols++; - - } - - #ifdef DEBUG_RB_EXT - printf("re = %d, is_ptrs_symbol_flag = %d, symbol = %d\n", re, is_ptrs_symbol_flag, symbol); - #endif - - if ( is_dmrs_re == 0 && is_ptrs_symbol_flag == 0) { - - rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); - rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]); - ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index]; - ul_ch0_ptrs_ext[ul_ch0_ptrs_ext_index] = ul_ch0_ptrs[ul_ch0_ptrs_index]; - - #ifdef DEBUG_RB_EXT - printf("rxF_ext[%d] = (%d,%d)\n", rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1]); - #endif - - ul_ch0_ext_index++; - ul_ch0_ptrs_ext_index++; - rxF_ext_index +=2; + if (is_dmrs_symbol == 0) { + // + //rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); + if (start_re + nb_re_pusch < frame_parms->ofdm_symbol_size) { + memcpy1((void*)rxF_ext, + (void*)&rxF[start_re*2], + nb_re_pusch*sizeof(int32_t)); } else { - k_prime++; - k_prime&=1; - n+=(k_prime)?0:1; + int neg_length = frame_parms->ofdm_symbol_size-start_re; + int pos_length = nb_re_pusch-neg_length; + + memcpy1((void*)rxF_ext,(void*)&rxF[start_re*2],neg_length*sizeof(int32_t)); + memcpy1((void*)&rxF_ext[2*neg_length],(void*)rxF,pos_length*sizeof(int32_t)); + } + memcpy1((void*)ul_ch0_ext,(void*)ul_ch0,nb_re_pusch*sizeof(int32_t)); + } + else { + for (re = 0; re < nb_re_pusch; re++) { + + is_dmrs_re = (re == get_dmrs_freq_idx_ul(n, k_prime, delta, pusch_pdu->dmrs_config_type)); + +#ifdef DEBUG_RB_EXT + printf("re = %d, kprime %d, n %d, is_dmrs_symbol = %d, symbol = %d\n", re, k_prime, n, is_dmrs_symbol, symbol); +#endif + + /* save only data and respective channel estimates */ + if (is_dmrs_re == 0) { + rxF_ext[rxF_ext_index] = (rxF[ ((start_re + re)*2) % (frame_parms->ofdm_symbol_size*2)]); + rxF_ext[rxF_ext_index + 1] = (rxF[(((start_re + re)*2) + 1) % (frame_parms->ofdm_symbol_size*2)]); + ul_ch0_ext[ul_ch0_ext_index] = ul_ch0[ul_ch0_index]; + +#ifdef DEBUG_RB_EXT + printf("dmrs symb %d: rxF_ext[%d] = (%d,%d), ul_ch0_ext[%d] = (%d,%d)\n", + is_dmrs_symbol,rxF_ext_index>>1, rxF_ext[rxF_ext_index],rxF_ext[rxF_ext_index+1], + ul_ch0_ext_index, ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[0], ((int16_t*)&ul_ch0_ext[ul_ch0_ext_index])[1]); +#endif + ul_ch0_ext_index++; + rxF_ext_index +=2; + } else { + n += k_prime; + k_prime ^= 1; + } + ul_ch0_index++; } - ul_ch0_index++; - ul_ch0_ptrs_index++; } } - - pusch_vars->ptrs_sc_per_ofdm_symbol = num_ptrs_symbols; - } void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, @@ -356,10 +341,16 @@ void nr_ulsch_scale_channel(int **ul_ch_estimates_ext, ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13 +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + for (aatx=0; aatx < frame_parms->nb_antenna_ports_gNB; aatx++) { for (aarx=0; aarx < frame_parms->nb_antennas_rx; aarx++) { - ul_ch128 = (__m128i *)&ul_ch_estimates_ext[aarx][symbol*nb_rb*NR_NB_SC_PER_RB]; + ul_ch128 = (__m128i *)&ul_ch_estimates_ext[aarx][symbol*(off+(nb_rb*NR_NB_SC_PER_RB))]; if (is_dmrs_symbol==1){ if (pusch_dmrs_type == pusch_dmrs_type1) @@ -408,12 +399,18 @@ void nr_ulsch_channel_level(int **ul_ch_estimates_ext, int16_t x = factor2(len); int16_t y = (len)>>x; +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + for (aatx = 0; aatx < frame_parms->nb_antennas_tx; aatx++) for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128U = _mm_setzero_si128(); - ul_ch128=(__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*nb_rb*12]; + ul_ch128=(__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; for (rb = 0; rb < len/12; rb++) { avg128U = _mm_add_epi32(avg128U, _mm_srai_epi32(_mm_madd_epi16(ul_ch128[0], ul_ch128[0]), x)); @@ -501,13 +498,13 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, unsigned short nb_rb, unsigned char output_shift) { + #ifdef DEBUG_CH_COMP int16_t *rxF, *ul_ch; int prnt_idx; - - rxF = (int16_t *)&rxdataF_ext[0][(symbol*nb_rb*12)]; - ul_ch = (int16_t *)&ul_ch_estimates_ext[0][symbol*nb_rb*12]; + rxF = (int16_t *)&rxdataF_ext[0][symbol*(off+(nb_rb*12))]; + ul_ch = (int16_t *)&ul_ch_estimates_ext[0][symbol*(off+(nb_rb*1))2]; printf("--------------------symbol = %d, mod_order = %d, output_shift = %d-----------------------\n", symbol, mod_order, output_shift); printf("----------------Before compensation------------------\n"); @@ -526,7 +523,7 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, int print_idx; - ch_mag = (int16_t *)&ul_ch_mag[0][(symbol*nb_rb*12)]; + ch_mag = (int16_t *)&ul_ch_mag[0][symbol*(off+(nb_rb*12))]; printf("--------------------symbol = %d, mod_order = %d-----------------------\n", symbol, mod_order); printf("----------------Before computation------------------\n"); @@ -539,7 +536,13 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, #endif -#if defined(__i386) || defined(__x86_64) +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + +#if defined(__i386) || defined(__x86_64__) unsigned short rb; unsigned char aatx,aarx; @@ -561,11 +564,11 @@ void nr_ulsch_channel_compensation(int **rxdataF_ext, for (aarx=0; aarxnb_antennas_rx; aarx++) { - ul_ch128 = (__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*nb_rb*12]; - ul_ch_mag128 = (__m128i *)&ul_ch_mag[(aatx<<1)+aarx][symbol*nb_rb*12]; - ul_ch_mag128b = (__m128i *)&ul_ch_magb[(aatx<<1)+aarx][symbol*nb_rb*12]; - rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*nb_rb*12]; - rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*nb_rb*12]; + ul_ch128 = (__m128i *)&ul_ch_estimates_ext[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; + ul_ch_mag128 = (__m128i *)&ul_ch_mag[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; + ul_ch_mag128b = (__m128i *)&ul_ch_magb[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; + rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*(off+(nb_rb*12))]; + rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*(off+(nb_rb*12))]; for (rb=0; rbnb_antennas_rx; +#if defined(__x86_64__) || defined(__i386__) + __m128i *rxdataF_comp128[1+n_rx],*ul_ch_mag128[1+n_rx],*ul_ch_mag128b[1+n_rx]; +#elif defined(__arm__) + int16x8_t *rxdataF_comp128_0,*ul_ch_mag128_0,*ul_ch_mag128_0b; + int16x8_t *rxdataF_comp128_1,*ul_ch_mag128_1,*ul_ch_mag128_1b; +#endif + int32_t i; + +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + + if (frame_parms->nb_antennas_rx>1) { +#if defined(__x86_64__) || defined(__i386__) + int nb_re = nb_rb*12; + for (int aa=0;aanb_antennas_rx;aa++) { + rxdataF_comp128[aa] = (__m128i *)&rxdataF_comp[aa][(symbol*(nb_re + off))]; + ul_ch_mag128[aa] = (__m128i *)&ul_ch_mag[aa][(symbol*(nb_re + off))]; + ul_ch_mag128b[aa] = (__m128i *)&ul_ch_magb[aa][(symbol*(nb_re + off))]; + + // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) + for (i=0; iN_RB_DL*12]; + rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_0 = (int16x8_t *)&ul_ch_mag[0][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_1 = (int16x8_t *)&ul_ch_mag[1][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_0b = (int16x8_t *)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12]; + ul_ch_mag128_1b = (int16x8_t *)&ul_ch_magb[1][symbol*frame_parms->N_RB_DL*12]; + + // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) + for (i=0; iframe_parms; nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id][0]->harq_processes[harq_pid]->ulsch_pdu; dmrs_symbol_flag = 0; - gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol = 0; if(symbol == rel15_ul->start_symbol_index){ - gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset = 0; gNB->pusch_vars[ulsch_id]->dmrs_symbol = 0; gNB->pusch_vars[ulsch_id]->cl_done = 0; - gNB->pusch_vars[ulsch_id]->ptrs_symbols = 0; - - if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { // if there is ptrs pdu - L_ptrs = 1<<(rel15_ul->pusch_ptrs.ptrs_time_density); - - set_ptrs_symb_idx(&gNB->pusch_vars[ulsch_id]->ptrs_symbols, - rel15_ul->nr_of_symbols, - rel15_ul->start_symbol_index, - L_ptrs, - rel15_ul->ul_dmrs_symb_pos); - } } + bwp_start_subcarrier = (rel15_ul->rb_start*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; dmrs_symbol_flag = ((rel15_ul->ul_dmrs_symb_pos)>>symbol)&0x01; + LOG_D(PHY,"symbol %d bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n",symbol,bwp_start_subcarrier,rel15_ul->rb_start,frame_parms->first_carrier_offset); + LOG_D(PHY,"ul_dmrs_symb_pos %x\n",rel15_ul->ul_dmrs_symb_pos); + if (dmrs_symbol_flag == 1){ if (((rel15_ul->ul_dmrs_symb_pos)>>((symbol+1)%frame_parms->symbols_per_slot))&0x01) AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); @@ -1062,28 +1116,32 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, else { nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4)); } + LOG_D(PHY,"dmrs_symbol: nb_re_pusch %d\n",nb_re_pusch); gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; } else { nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; } - if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { // if there is ptrs pdu - if(is_ptrs_symbol(symbol, gNB->pusch_vars[ulsch_id]->ptrs_symbols)) - gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = symbol; - } - - //---------------------------------------------------------- //--------------------- Channel estimation --------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_channel_estimation_stats); - if (dmrs_symbol_flag == 1) + if (dmrs_symbol_flag == 1) { nr_pusch_channel_estimation(gNB, nr_tti_rx, 0, // p symbol, + ulsch_id, bwp_start_subcarrier, rel15_ul); + + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + gNB->pusch_vars[ulsch_id]->ulsch_power[aarx] = signal_energy(&gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aarx][symbol*frame_parms->ofdm_symbol_size], + rel15_ul->rb_size*12); + if (gNB->pusch_vars[ulsch_id]->ulsch_power[aarx]==1) return (1); + } + + } stop_meas(&gNB->ulsch_channel_estimation_stats); //---------------------------------------------------------- //--------------------- RBs extraction --------------------- @@ -1091,6 +1149,8 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, if (nb_re_pusch > 0) { + gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] = nb_re_pusch; + start_meas(&gNB->ulsch_rbs_extraction_stats); nr_ulsch_extract_rbs_single(gNB->common_vars.rxdataF, gNB->pusch_vars[ulsch_id], @@ -1100,6 +1160,10 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, frame_parms); stop_meas(&gNB->ulsch_rbs_extraction_stats); + //---------------------------------------------------------- + //--------------------- Channel Scaling -------------------- + //---------------------------------------------------------- + nr_ulsch_scale_channel(gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, frame_parms, gNB->ulsch[ulsch_id], @@ -1124,10 +1188,14 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, for (aarx=0;aarxnb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); - gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs)/2)+1; + gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs)/2)+3; gNB->pusch_vars[ulsch_id]->cl_done = 1; } + //---------------------------------------------------------- + //--------------------- Channel Compensation --------------- + //---------------------------------------------------------- + start_meas(&gNB->ulsch_channel_compensation_stats); nr_ulsch_channel_compensation(gNB->pusch_vars[ulsch_id]->rxdataF_ext, gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, @@ -1143,34 +1211,66 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, gNB->pusch_vars[ulsch_id]->log2_maxh); stop_meas(&gNB->ulsch_channel_compensation_stats); - - int rxsig = signal_energy(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][(symbol*rel15_ul->rb_size*12)], - rel15_ul->rb_size*12); - - if (rxsig==1) return (rxsig); - + start_meas(&gNB->ulsch_mrc_stats); + nr_ulsch_detection_mrc(frame_parms, + gNB->pusch_vars[ulsch_id]->rxdataF_comp, + gNB->pusch_vars[ulsch_id]->ul_ch_mag, + gNB->pusch_vars[ulsch_id]->ul_ch_magb, + symbol, + rel15_ul->rb_size); + stop_meas(&gNB->ulsch_mrc_stats); #ifdef NR_SC_FDMA nr_idft(&((uint32_t*)gNB->pusch_vars[ulsch_id]->rxdataF_ext[0])[symbol * rel15_ul->rb_size * NR_NB_SC_PER_RB], nb_re_pusch); #endif - //---------------------------------------------------------- - //-------------------- LLRs computation -------------------- - //---------------------------------------------------------- - start_meas(&gNB->ulsch_llr_stats); - AssertFatal(gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset * rel15_ul->qam_mod_order+nb_re_pusch*rel15_ul->qam_mod_order < (8*((3*8*6144)+12)) , "Mysterious llr buffer size check"); - nr_ulsch_compute_llr(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][symbol * rel15_ul->rb_size * NR_NB_SC_PER_RB], - gNB->pusch_vars[ulsch_id]->ul_ch_mag0, - gNB->pusch_vars[ulsch_id]->ul_ch_magb0, - &gNB->pusch_vars[ulsch_id]->llr[gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset * rel15_ul->qam_mod_order], - rel15_ul->rb_size, - nb_re_pusch, - symbol, - rel15_ul->qam_mod_order); - stop_meas(&gNB->ulsch_llr_stats); + //---------------------------------------------------------- + //--------------------- PTRS Processing -------------------- + //---------------------------------------------------------- + + /* In case PTRS is enabled then LLR will be calculated after PTRS symbols are processed * + * otherwise LLR are calculated for each symbol based upon DMRS channel estimates only. */ + if (rel15_ul->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) + { + start_meas(&gNB->ulsch_ptrs_processing_stats); + nr_pusch_ptrs_processing(gNB, + rel15_ul, + ulsch_id, + nr_tti_rx, + dmrs_symbol_flag, + symbol, + nb_re_pusch); + stop_meas(&gNB->ulsch_ptrs_processing_stats); + + /* Subtract total PTRS RE's in the symbol from PUSCH RE's */ + gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] -= gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol; + } + + /*---------------------------------------------------------------------------------------------------- */ + /*-------------------- LLRs computation -------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------------------------*/ + if(symbol == (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols -1)) + { +#ifdef __AVX2__ + int off = ((rel15_ul->rb_size&1) == 1)? 4:0; +#else + int off = 0; +#endif + uint32_t rxdataF_ext_offset = 0; + for(uint8_t i =rel15_ul->start_symbol_index; i< (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);i++) { + start_meas(&gNB->ulsch_llr_stats); + nr_ulsch_compute_llr(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][i * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)], + gNB->pusch_vars[ulsch_id]->ul_ch_mag0, + gNB->pusch_vars[ulsch_id]->ul_ch_magb0, + &gNB->pusch_vars[ulsch_id]->llr[rxdataF_ext_offset * rel15_ul->qam_mod_order], + rel15_ul->rb_size, + gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[i], + i, + rel15_ul->qam_mod_order); + stop_meas(&gNB->ulsch_llr_stats); + rxdataF_ext_offset += gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[i]; + }// symbol loop + }// last symbol check } - - gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset = gNB->pusch_vars[ulsch_id]->rxdataF_ext_offset + nb_re_pusch; return (0); - } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c index 233ecd8de7..bf96a76106 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_llr_computation.c @@ -34,9 +34,6 @@ #include "PHY/sse_intrin.h" #include "PHY/impl_defs_top.h" -__m128i xmm0 __attribute__ ((aligned(32))); -__m128i xmm1 __attribute__ ((aligned(32))); -__m128i xmm2 __attribute__ ((aligned(32))); //---------------------------------------------------------------------------------------------- @@ -47,20 +44,19 @@ void nr_ulsch_qpsk_llr(int32_t *rxdataF_comp, uint32_t nb_re, uint8_t symbol) { - int i; - uint32_t *rxF = (uint32_t*)rxdataF_comp; uint32_t *llr32 = (uint32_t*)ulsch_llr; if (!llr32) { LOG_E(PHY,"nr_ulsch_qpsk_llr: llr is null, symbol %d, llr32 = %p\n",symbol, llr32); } - + /* for (i = 0; i < nb_re; i++) { *llr32 = *rxF; rxF++; llr32++; - } + }*/ + memcpy1((void*)llr32,(void*)rxF,nb_re<<2); } //---------------------------------------------------------------------------------------------- @@ -76,9 +72,17 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, { #if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + __m256i *rxF = (__m256i*)rxdataF_comp; + __m256i *ch_mag; + __m256i llr256[2]; + register __m256i xmm0; +#else __m128i *rxF = (__m128i*)rxdataF_comp; __m128i *ch_mag; __m128i llr128[2]; + register __m128i xmm0; +#endif uint32_t *llr32; #elif defined(__arm__) @@ -90,7 +94,12 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, int i; - unsigned char len_mod4 = 0; + +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif #if defined(__x86_64__) || defined(__i386__) @@ -100,22 +109,69 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, #endif #if defined(__x86_64__) || defined(__i386__) - ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*nb_rb*12)]; +#ifdef __AVX2__ + ch_mag = (__m256i*)&ul_ch_mag[0][(symbol*(off+(nb_rb*12)))]; +#else + ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*(off+(nb_rb*12)))]; +#endif #elif defined(__arm__) ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*nb_rb*12)]; #endif - len_mod4 = nb_re&3; +#ifdef __AVX2__ + unsigned char len_mod8 = nb_re&7; + nb_re >>= 3; // length in quad words (4 REs) + nb_re += (len_mod8 == 0 ? 0 : 1); +#else + unsigned char len_mod4 = nb_re&3; nb_re >>= 2; // length in quad words (4 REs) nb_re += (len_mod4 == 0 ? 0 : 1); +#endif for (i=0; i |y_R|, registers of odd index in xmm0-> |y_I| + xmm0 = _mm256_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 + + llr256[0] = _mm256_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st,2nd,5th and 6th REs + llr256[1] = _mm256_unpackhi_epi32(rxF[i],xmm0); // llr128[1] contains the llrs of the 3rd, 4th, 7th and 8th REs + + // 1st RE + llr32[0] = _mm256_extract_epi32(llr256[0],0); // llr32[0] low 16 bits-> y_R , high 16 bits-> y_I + llr32[1] = _mm256_extract_epi32(llr256[0],1); // llr32[1] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + // 2nd RE + llr32[2] = _mm256_extract_epi32(llr256[0],2); // llr32[2] low 16 bits-> y_R , high 16 bits-> y_I + llr32[3] = _mm256_extract_epi32(llr256[0],3); // llr32[3] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 3rd RE + llr32[4] = _mm256_extract_epi32(llr256[1],0); // llr32[4] low 16 bits-> y_R , high 16 bits-> y_I + llr32[5] = _mm256_extract_epi32(llr256[1],1); // llr32[5] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 4th RE + llr32[6] = _mm256_extract_epi32(llr256[1],2); // llr32[6] low 16 bits-> y_R , high 16 bits-> y_I + llr32[7] = _mm256_extract_epi32(llr256[1],3); // llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 5th RE + llr32[8] = _mm256_extract_epi32(llr256[0],4); // llr32[8] low 16 bits-> y_R , high 16 bits-> y_I + llr32[9] = _mm256_extract_epi32(llr256[0],5); // llr32[9] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 6th RE + llr32[10] = _mm256_extract_epi32(llr256[0],6); // llr32[10] low 16 bits-> y_R , high 16 bits-> y_I + llr32[11] = _mm256_extract_epi32(llr256[0],7); // llr32[11] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 7th RE + llr32[12] = _mm256_extract_epi32(llr256[1],4); // llr32[12] low 16 bits-> y_R , high 16 bits-> y_I + llr32[13] = _mm256_extract_epi32(llr256[1],5); // llr32[13] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + // 8th RE + llr32[14] = _mm256_extract_epi32(llr256[1],6); // llr32[14] low 16 bits-> y_R , high 16 bits-> y_I + llr32[15] = _mm256_extract_epi32(llr256[1],7); // llr32[15] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 + + llr32+=16; +#else xmm0 = _mm_abs_epi16(rxF[i]); // registers of even index in xmm0-> |y_R|, registers of odd index in xmm0-> |y_I| - - xmm0 = _mm_subs_epi16(ch_mag[i],xmm0); // registers of even index in xmm0-> |y_R|-|h|^2, registers of odd index in xmm0-> |y_I|-|h|^2 llr128[0] = _mm_unpacklo_epi32(rxF[i],xmm0); // llr128[0] contains the llrs of the 1st and 2nd REs @@ -138,6 +194,7 @@ void nr_ulsch_16qam_llr(int32_t *rxdataF_comp, llr32[7] = _mm_extract_epi32(llr128[1],3); // llr32[7] low 16 bits-> |h|-|y_R|^2, high 16 bits-> |h|-|y_I|^2 llr32+=8; +#endif #elif defined(__arm__) xmm0 = vabsq_s16(rxF[i]); xmm0 = vqsubq_s16((*(__m128i*)&ones[0]),xmm0); @@ -182,40 +239,69 @@ void nr_ulsch_64qam_llr(int32_t *rxdataF_comp, uint8_t symbol) { +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + #if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + __m256i *rxF = (__m256i*)rxdataF_comp; + __m256i *ch_mag,*ch_magb; + register __m256i xmm0,xmm1,xmm2; +#else __m128i *rxF = (__m128i*)rxdataF_comp; __m128i *ch_mag,*ch_magb; + register __m128i xmm0,xmm1,xmm2; +#endif #elif defined(__arm__) int16x8_t *rxF = (int16x8_t*)&rxdataF_comp; int16x8_t *ch_mag,*ch_magb; // [hna] This should be uncommented once channel estimation is implemented - int16x8_t xmm1,xmm2; + int16x8_t xmm0,xmm1,xmm2; #endif int i; - unsigned char len_mod4; #if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + ch_mag = (__m256i*)&ul_ch_mag[0][(symbol*(off+(nb_rb*12)))]; + ch_magb = (__m256i*)&ul_ch_magb[0][(symbol*(off+(nb_rb*12)))]; +#else ch_mag = (__m128i*)&ul_ch_mag[0][(symbol*nb_rb*12)]; ch_magb = (__m128i*)&ul_ch_magb[0][(symbol*nb_rb*12)]; +#endif #elif defined(__arm__) ch_mag = (int16x8_t*)&ul_ch_mag[0][(symbol*nb_rb*12)]; ch_magb = (int16x8_t*)&ul_ch_magb[0][(symbol*nb_rb*12)]; #endif - len_mod4 = nb_re&3; +#ifdef __AVX2__ + int len_mod8 = nb_re&7; + nb_re = nb_re>>3; // length in quad words (4 REs) + nb_re += ((len_mod8 == 0) ? 0 : 1); +#else + int len_mod4 = nb_re&3; nb_re = nb_re>>2; // length in quad words (4 REs) nb_re += ((len_mod4 == 0) ? 0 : 1); - +#endif for (i=0; ipucch[i]!=NULL,"gNB->pucch[%d] is null\n",i); if ((gNB->pucch[i]->active >0) && (gNB->pucch[i]->pucch_pdu.rnti==rnti) && @@ -315,7 +315,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int16_t xr[24] __attribute__((aligned(32))); //int16_t xrt[24] __attribute__((aligned(32))); int32_t xrtmag=0; - int maxpos=0; + uint8_t maxpos=0; int n2=0; uint8_t index=0; memset((void*)xr,0,24*sizeof(int16_t)); @@ -339,7 +339,8 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, #endif } } - int32_t corr_re,corr_im,temp; + int32_t corr_re,corr_im,temp,no_corr=0; + int32_t av_corr=0; int seq_index; for(i=0;i%f\n",mcs[i],seq_index,corr_re,corr_im,10*log10(corr_re*corr_re + corr_im*corr_im)); #endif - if ((temp=corr_re*corr_re + corr_im*corr_im)>xrtmag) { + temp=corr_re*corr_re + corr_im*corr_im; + av_corr+=temp; + if (temp>xrtmag) { xrtmag=temp; maxpos=i; } } + if(nr_sequences>1) + no_corr=(av_corr-xrtmag)/(nr_sequences-1); + av_corr/=nr_sequences; uint8_t xrtmag_dB = dB_fixed(xrtmag); - -//#ifdef DEBUG_NR_PUCCH_RX + +#ifdef DEBUG_NR_PUCCH_RX printf("PUCCH 0 : maxpos %d\n",maxpos); -//#endif +#endif index=maxpos; #endif + + // estimate CQI for MAC (from antenna port 0 only) + int SNRtimes10 = dB_fixed_times10(signal_energy(&rxdataF[0][pucch_pdu->start_symbol_index*frame_parms->ofdm_symbol_size+re_offset],12)) - (10*gNB->measurements.n0_power_tot_dB); + int cqi; + if (SNRtimes10 < -640) cqi=0; + else if (SNRtimes10 > 635) cqi=255; + else cqi=(640+SNRtimes10)/5; + + bool no_conf=false; + if (nr_sequences>1) { + if ((xrtmag_dB<(11+dB_fixed(no_corr))) || (dB_fixed(av_corr)<(13+gNB->measurements.n0_power_tot_dB))) //TODO these are temporary threshold based on measurments with the phone + no_conf=true; + } // first bit of bitmap for sr presence and second bit for acknack presence uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq>0)<<1); uci_pdu->pucch_format = 0; // format 0 - uci_pdu->ul_cqi = 0xff; // currently not valid + uci_pdu->ul_cqi = cqi; // currently not valid uci_pdu->timing_advance = 0xffff; // currently not valid - uci_pdu->rssi = 0xffff; // currently not valid - + uci_pdu->rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(signal_energy(&rxdataF[0][pucch_pdu->start_symbol_index*frame_parms->ofdm_symbol_size+re_offset],12))); if (pucch_pdu->bit_len_harq==0) { uci_pdu->harq = NULL; uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); - if (xrtmag_dB>(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres)) { + uci_pdu->sr->sr_confidence_level = (xrtmag_dB<(13+gNB->measurements.n0_power_tot_dB)) ? 1 : 0; + if (xrtmag_dB>(gNB->measurements.n0_power_tot_dB)) { uci_pdu->sr->sr_indication = 1; - uci_pdu->sr->sr_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); } else { uci_pdu->sr->sr_indication = 0; - uci_pdu->sr->sr_confidence_level = (gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres)-xrtmag_dB; } } else if (pucch_pdu->bit_len_harq==1) { uci_pdu->harq = calloc(1,sizeof(*uci_pdu->harq)); uci_pdu->harq->num_harq = 1; - uci_pdu->harq->harq_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->harq->harq_confidence_level = (no_conf) ? 1 : 0; uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(1); uci_pdu->harq->harq_list[0].harq_value = index&0x01; + LOG_I(PHY, "HARQ value %d with confidence level (0 is good, 1 is bad) %d\n", + uci_pdu->harq->harq_list[0].harq_value,uci_pdu->harq->harq_confidence_level); if (pucch_pdu->sr_flag == 1) { uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); uci_pdu->sr->sr_indication = (index>1) ? 1 : 0; - uci_pdu->sr->sr_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->sr->sr_confidence_level = (no_conf) ? 1 : 0; } } else { uci_pdu->harq = calloc(1,sizeof(*uci_pdu->harq)); uci_pdu->harq->num_harq = 2; - uci_pdu->harq->harq_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->harq->harq_confidence_level = (no_conf) ? 1 : 0; uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(2); - uci_pdu->harq->harq_list[1].harq_value = index&0x01; uci_pdu->harq->harq_list[0].harq_value = (index>>1)&0x01; - + LOG_I(PHY, "HARQ values %d and %d with confidence level (0 is good, 1 is bad) %d\n", + uci_pdu->harq->harq_list[1].harq_value,uci_pdu->harq->harq_list[0].harq_value,uci_pdu->harq->harq_confidence_level); if (pucch_pdu->sr_flag == 1) { uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); uci_pdu->sr->sr_indication = (index>3) ? 1 : 0; - uci_pdu->sr->sr_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); + uci_pdu->sr->sr_confidence_level = (no_conf) ? 1 : 0; } } } @@ -1047,6 +1066,8 @@ void init_pucch2_luts() { bit = (i&0x80) > 0 ? 0 : 1; *lut_num_i = _mm_insert_epi16(*lut_num_i,bit,7); *lut_den_i = _mm_insert_epi16(*lut_den_i,1-bit,7); + +#ifdef DEBUG_NR_PUCCH_RX printf("i %d, lut_num (%d,%d,%d,%d,%d,%d,%d,%d)\n",i, ((int16_t *)lut_num_i)[0], ((int16_t *)lut_num_i)[1], @@ -1056,6 +1077,7 @@ void init_pucch2_luts() { ((int16_t *)lut_num_i)[5], ((int16_t *)lut_num_i)[6], ((int16_t *)lut_num_i)[7]); +#endif } } @@ -1418,56 +1440,60 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } printf("\n"); #endif - // do complex correlation - for (int aa=0;aa (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",aa, - ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3], - ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7], - ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11], - ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]); - printf("prod_im[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",aa, - ((int16_t*)&prod_im[aa])[0],((int16_t*)&prod_im[aa])[1],((int16_t*)&prod_im[aa])[2],((int16_t*)&prod_im[aa])[3], - ((int16_t*)&prod_im[aa])[4],((int16_t*)&prod_im[aa])[5],((int16_t*)&prod_im[aa])[6],((int16_t*)&prod_im[aa])[7], - ((int16_t*)&prod_im[aa])[8],((int16_t*)&prod_im[aa])[9],((int16_t*)&prod_im[aa])[10],((int16_t*)&prod_im[aa])[11], - ((int16_t*)&prod_im[aa])[12],((int16_t*)&prod_im[aa])[13],((int16_t*)&prod_im[aa])[14],((int16_t*)&prod_im[aa])[15]); - -#endif - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15 - prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); - } - int64_t corr_re=0,corr_im=0; - int64_t corr_tmp = 0; - for (int aa=0;aa (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",aa, + ((int16_t*)&prod_re[aa])[0],((int16_t*)&prod_re[aa])[1],((int16_t*)&prod_re[aa])[2],((int16_t*)&prod_re[aa])[3], + ((int16_t*)&prod_re[aa])[4],((int16_t*)&prod_re[aa])[5],((int16_t*)&prod_re[aa])[6],((int16_t*)&prod_re[aa])[7], + ((int16_t*)&prod_re[aa])[8],((int16_t*)&prod_re[aa])[9],((int16_t*)&prod_re[aa])[10],((int16_t*)&prod_re[aa])[11], + ((int16_t*)&prod_re[aa])[12],((int16_t*)&prod_re[aa])[13],((int16_t*)&prod_re[aa])[14],((int16_t*)&prod_re[aa])[15]); + printf("prod_im[%d] => (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",aa, + ((int16_t*)&prod_im[aa])[0],((int16_t*)&prod_im[aa])[1],((int16_t*)&prod_im[aa])[2],((int16_t*)&prod_im[aa])[3], + ((int16_t*)&prod_im[aa])[4],((int16_t*)&prod_im[aa])[5],((int16_t*)&prod_im[aa])[6],((int16_t*)&prod_im[aa])[7], + ((int16_t*)&prod_im[aa])[8],((int16_t*)&prod_im[aa])[9],((int16_t*)&prod_im[aa])[10],((int16_t*)&prod_im[aa])[11], + ((int16_t*)&prod_im[aa])[12],((int16_t*)&prod_im[aa])[13],((int16_t*)&prod_im[aa])[14],((int16_t*)&prod_im[aa])[15]); + +#endif + prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1 + prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); + prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3 + prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); + prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7 + prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); + prod_re[aa] = _mm256_hadds_epi16(prod_re[aa],prod_re[aa]);// 0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15 + prod_im[aa] = _mm256_hadds_epi16(prod_im[aa],prod_im[aa]); + } + int64_t corr_re=0,corr_im=0; + + + for (int aa=0;aa corr) { corr = corr_tmp; cw_ML=cw; } - } + } // cw loop corr_dB = dB_fixed64((uint64_t)corr); LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); decodedPayload[0]=(uint64_t)cw_ML; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 1a6006c3ba..36bcb2f379 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -68,7 +68,7 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) if (dlsch) { if (N_RB_DL != 273) { a_segments = a_segments*N_RB_DL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } @@ -266,8 +266,14 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, double Coderate;// = 0.0; uint8_t dmrs_Type = harq_process->dmrsConfigType; - AssertFatal(dmrs_Type == 1 || dmrs_Type == 2,"Illegal dmrs_type %d\n",dmrs_Type); - uint8_t nb_re_dmrs = (dmrs_Type==1)?6:4; // should be changed based on MAC parameters + AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); + uint8_t nb_re_dmrs; + if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; + } + else { + nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; + } uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos); AssertFatal(dmrs_length == 1 || dmrs_length == 2,"Illegal dmrs_length %d\n",dmrs_length); @@ -277,7 +283,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, __m128i *pl = (__m128i*)&l; vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN); - + //NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[0]; if (!dlsch_llr) { @@ -409,7 +415,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (nb_rb != 273) { a_segments = a_segments*nb_rb; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } if (harq_process->C > a_segments) { @@ -584,6 +590,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // 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)) { LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); + if (r==0) + for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]); + //Temporary hack no_iteration_ldpc = dlsch->max_ldpc_iterations; ret = no_iteration_ldpc; @@ -657,9 +666,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, 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++; // [hna] uncomment this line when HARQ is implemented - // printf("Rate: [UE %d] DLSCH: Setting NACK for subframe %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,subframe,harq_pid,harq_process->round); + // printf("Rate: [UE %d] DLSCH: Setting NACK for slot %d (pid %d, round %d)\n",phy_vars_ue->Mod_id,nr_tti_rx,harq_pid,harq_process->round); if (harq_process->round >= dlsch->Mlimit) { harq_process->status = SCH_IDLE; harq_process->round = 0; @@ -805,7 +813,12 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, //nfapi_nr_config_request_t *cfg = &phy_vars_ue->nrUE_config; //uint8_t dmrs_type = cfg->pdsch_config.dmrs_type.value; - uint8_t nb_re_dmrs = 12;//(dmrs_type==1)?6:4; + uint8_t nb_re_dmrs; + if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) + nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; + else + nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; + uint16_t length_dmrs = get_num_dmrs(dl_config_pdu->dlDmrsSymbPos); uint32_t i,j; @@ -947,7 +960,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, if (nb_rb != 273) { a_segments = a_segments*nb_rb; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } if (harq_process->C > a_segments) { @@ -1525,7 +1538,7 @@ void nr_dlsch_decoding_process(void *arg) if (nb_rb != 273) { a_segments = a_segments*nb_rb; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } if (harq_process->C > a_segments) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index a8827b4e92..7aa0e357aa 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -134,7 +134,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, int avgs = 0;// rb; NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL; - uint8_t beamforming_mode; + uint8_t beamforming_mode = 0; int32_t **rxdataF_comp_ptr; int32_t **dl_ch_mag_ptr; @@ -159,27 +159,34 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, switch (type) { case SI_PDSCH: - pdsch_vars = ue->pdsch_vars_SI; + pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]]; dlsch = &ue->dlsch_SI[eNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - beamforming_mode = 0; + break; case RA_PDSCH: - pdsch_vars = ue->pdsch_vars_ra; + pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]]; dlsch = &ue->dlsch_ra[eNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - beamforming_mode = 0; break; case PDSCH: pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]]; dlsch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id]; - beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id]; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; dlsch1_harq = dlsch[1]->harq_processes[harq_pid]; + beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id]; + break; + + default: + LOG_E(PHY, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); + return -1; + break; + } + + if (dlsch0_harq && dlsch1_harq){ //printf("status TB0 = %d, status TB1 = %d \n", dlsch[0]->harq_processes[harq_pid]->status, dlsch[1]->harq_processes[harq_pid]->status); LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", frame, nr_tti_rx, symbol, harq_pid, dlsch0_harq->status, dlsch1_harq->status); @@ -191,27 +198,25 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid]; #ifdef DEBUG_HARQ - printf("[DEMOD] I am assuming both TBs are active\n"); + printf("[DEMOD] I am assuming both TBs are active, in cw0 %d and cw1 %d \n", codeword_TB0, codeword_TB1); #endif } else if ((dlsch0_harq->status == ACTIVE) && (dlsch1_harq->status != ACTIVE) ) { codeword_TB0 = dlsch0_harq->codeword; - codeword_TB1 = -1; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch0_harq = dlsch[codeword_TB0]->harq_processes[harq_pid]; dlsch1_harq = NULL; #ifdef DEBUG_HARQ - printf("[DEMOD] I am assuming only TB0 is active\n"); + printf("[DEMOD] I am assuming only TB0 is active, in cw %d \n", codeword_TB0); #endif } else if ((dlsch0_harq->status != ACTIVE) && (dlsch1_harq->status == ACTIVE)){ - codeword_TB0 = -1; codeword_TB1 = dlsch1_harq->codeword; dlsch0_harq = NULL; - dlsch1_harq = dlsch[1]->harq_processes[codeword_TB1]; + dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid]; #ifdef DEBUG_HARQ - printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", dlsch1_harq->codeword); + printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", codeword_TB1); #endif LOG_E(PHY, "[UE][FATAL] DLSCH: TB0 not active and TB1 active case is not supported\n"); @@ -221,17 +226,19 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx); return(-1); } + } else if (dlsch0_harq) { + if (dlsch0_harq->status == ACTIVE) { + codeword_TB0 = dlsch0_harq->codeword; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - break; - - default: - LOG_E(PHY, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); - return(-1); - break; - - } - - if (dlsch0_harq == NULL) { + #ifdef DEBUG_HARQ + printf("[DEMOD] I am assuming only TB0 is active\n"); + #endif + } else { + LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx); + return (-1); + } + } else { LOG_E(PHY, "Done\n"); return -1; } @@ -336,9 +343,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id_i]->pmi_ext, symbol, - pilots, - start_rb, - nb_rb_pdsch, + pilots, + start_rb, + nb_rb_pdsch, nr_tti_rx, ue->high_speed_flag, frame_parms, @@ -351,9 +358,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id_i]->pmi_ext, symbol, - pilots, - start_rb, - nb_rb_pdsch, + pilots, + start_rb, + nb_rb_pdsch, nr_tti_rx, ue->high_speed_flag, frame_parms, @@ -513,7 +520,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, frame_parms, symbol, - pilots, + pilots, first_symbol_flag, dlsch0_harq->Qm, nb_rb, @@ -1144,7 +1151,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, int **rho, NR_DL_FRAME_PARMS *frame_parms, unsigned char symbol, - uint8_t pilots, + uint8_t pilots, uint8_t first_symbol_flag, unsigned char mod_order, unsigned short nb_rb, @@ -2380,7 +2387,7 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, for (aarx=0; aarxnb_antennas_rx; aarx++) { - k = frame_parms->first_carrier_offset + 12*start_rb; + k = frame_parms->first_carrier_offset + NR_NB_SC_PER_RB*start_rb; if (high_speed_flag == 1) dl_ch0 = &dl_ch_estimates[aarx][(2*(frame_parms->ofdm_symbol_size))]; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c index ce1c0df156..e0b24a033a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c @@ -786,16 +786,16 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, //---------------------------------------------------------------------------------------------- void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t **rxdataF_comp, - int16_t *dlsch_llr, - int32_t **dl_ch_mag, - int32_t **dl_ch_magb, - uint8_t symbol, - uint32_t len, - uint8_t first_symbol_flag, - uint16_t nb_rb, - uint32_t llr_offset, - uint8_t beamforming_mode) + int32_t **rxdataF_comp, + int16_t *dlsch_llr, + int32_t **dl_ch_mag, + int32_t **dl_ch_magb, + uint8_t symbol, + uint32_t len, + uint8_t first_symbol_flag, + uint16_t nb_rb, + uint32_t llr_offset, + uint8_t beamforming_mode) { #if defined(__x86_64__) || defined(__i386__) __m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*nb_rb*12)]; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 3bf12b876c..8eaaea8bee 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -44,18 +44,8 @@ //#define NR_PRACH_DEBUG 1 -extern uint16_t NCS_unrestricted_delta_f_RA_125[16]; -extern uint16_t NCS_restricted_TypeA_delta_f_RA_125[15]; -extern uint16_t NCS_restricted_TypeB_delta_f_RA_125[13]; -extern uint16_t NCS_unrestricted_delta_f_RA_5[16]; -extern uint16_t NCS_restricted_TypeA_delta_f_RA_5[16]; -extern uint16_t NCS_restricted_TypeB_delta_f_RA_5[14]; -extern uint16_t NCS_unrestricted_delta_f_RA_15[16]; extern uint16_t prach_root_sequence_map_0_3[838]; extern uint16_t prach_root_sequence_map_abc[138]; -extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9]; -extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; -extern int64_t table_6_3_3_2_4_prachConfig_Index [256][10]; extern uint16_t nr_du[838]; extern int16_t nr_ru[2*839]; extern const char *prachfmt[9]; @@ -81,7 +71,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ int16_t prach_tmp[98304*2*4] __attribute__((aligned(32))); int16_t Ncp = 0, amp, *prach, *prach2, *prachF, *Xu; - int32_t Xu_re, Xu_im, samp_count; + int32_t Xu_re, Xu_im; int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k; //int restricted_Type; @@ -113,22 +103,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index, ue->X_u); - if (mu == 0) - samp_count = fp->samples_per_subframe; - else - samp_count = (slot%(fp->slots_per_subframe/2)) ? fp->samples_per_slotN0 : fp->samples_per_slot0; - - #if defined (OAI_USRP) - prach_start = (ue->rx_offset + slot*samp_count - ue->hw_timing_advance - ue->N_TA_offset); - #else //normal case (simulation) - prach_start = slot*samp_count - ue->N_TA_offset; - #endif - - if (prach_start<0) - prach_start += (fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME); - - if (prach_start >= (fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME)) - prach_start -= (fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME); + prach_start = fp->get_samples_slot_timestamp(slot, fp, 0); // First compute physical root sequence /************************************************************************ @@ -208,15 +183,18 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // now generate PRACH signal #ifdef NR_PRACH_DEBUG if (NCS>0) - LOG_I(PHY, "PRACH [UE %d] generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d\n", Mod_id, - rootSequenceIndex, - preamble_index, - prachfmt[prach_fmt_id], - NCS, - N_ZC, - preamble_offset, - preamble_shift); -#endif + LOG_I(PHY, "PRACH [UE %d] generate PRACH in slot %d for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d msg1 frequency start %d\n", + Mod_id, + slot, + rootSequenceIndex, + preamble_index, + prachfmt[prach_fmt_id], + NCS, + N_ZC, + preamble_offset, + preamble_shift, + n_ra_prb); + #endif // nsymb = (frame_parms->Ncp==0) ? 14:12; // subframe_offset = (unsigned int)frame_parms->ofdm_symbol_size*slot*nsymb; @@ -383,8 +361,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else { - //LOG_D(PHY, "PRACH [UE %d] in slot %d, format %d, msg1 frequency start %d startSymbol %d \n", Mod_id, slot, prachfmt[prach_fmt_id], n_ra_prb, prachStartSymbol); - switch (prach_fmt_id) { case 4: //A1 Ncp = 288/(1<N_RB_UL <= 100) AssertFatal(1==0,"N_RB_UL %d not supported for NR PRACH yet\n",fp->N_RB_UL); @@ -805,40 +783,16 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } #ifdef NR_PRACH_DEBUG - LOG_I(PHY, "PRACH [UE %d] N_RB_UL %d prach_start %d, prach_len %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", Mod_id, + LOG_I(PHY, "PRACH [UE %d] N_RB_UL %d prach_start %d, prach_len %d\n", Mod_id, fp->N_RB_UL, prach_start, - prach_len, - ue->rx_offset, - ue->hw_timing_advance, - ue->N_TA_offset); + prach_len); #endif - #if defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) - int j, overflow = prach_start + prach_len - NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe; - - #ifdef NR_PRACH_DEBUG - LOG_I( PHY, "PRACH [UE %d] overflow = %d\n", Mod_id, overflow); - #endif - - // prach_start=414.730, overflow=-39470 prach_len=6600 fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME 460.800 prach_start+prach_len 421.330 fp->samples_per_subframe 46080 - - // from prach_start=414.730 to prach_start+prach_len 421.330 - for (i = prach_start, j = 0; i < min(fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME, prach_start + prach_len); i++, j++) { - ((int16_t*)ue->common_vars.txdata[0])[2*i] = prach[2*j]; - ((int16_t*)ue->common_vars.txdata[0])[2*i+1] = prach[2*j+1]; - } - - for (i = 0; i < overflow; i++,j++) { - ((int16_t*)ue->common_vars.txdata[0])[2*i] = prach[2*j]; - ((int16_t*)ue->common_vars.txdata[0])[2*i+1] = prach[2*j+1]; - } - #else // simulators - for (i=0; icommon_vars.txdata[0][prach_start]))[2*i] = prach[2*i]; - ((int16_t*)(&ue->common_vars.txdata[0][prach_start]))[2*i+1] = prach[2*i+1]; - } - #endif + for (i=0; icommon_vars.txdata[0][prach_start]))[2*i] = prach[2*i]; + ((int16_t*)(&ue->common_vars.txdata[0][prach_start]))[2*i+1] = prach[2*i+1]; + } //printf("----------------------\n"); //for(int ii = prach_start; ii<2*(prach_start + prach_len); ii++){ @@ -846,7 +800,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ //} //printf(" \n"); - #if defined(PRACH_WRITE_OUTPUT_DEBUG) + #ifdef PRACH_WRITE_OUTPUT_DEBUG LOG_M("prach_tx0.m", "prachtx0", prach+(Ncp<<1), prach_len-Ncp, 1, 1); LOG_M("Prach_txsig.m","txs",(int16_t*)(&ue->common_vars.txdata[0][prach_start]), 2*(prach_start+prach_len), 1, 1) #endif 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 bde9ae03f1..845eace8b6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1064,7 +1064,7 @@ void nr_pusch_codeword_scrambling(uint8_t *in, void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, unsigned char harq_pid, - uint8_t frame, + uint32_t frame, uint8_t slot, uint8_t thread_id, int gNB_id); @@ -1074,11 +1074,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, */ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, - uint8_t harq_pid, uint8_t slot, - uint8_t thread_id, - uint8_t gNB_id, - NR_DL_FRAME_PARMS *frame_parms); + NR_DL_FRAME_PARMS *frame_parms, + uint8_t Nl); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 6b2d5e7255..d1dd0f785b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -177,7 +177,7 @@ typedef struct { /// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14) uint8_t b_tilde[MAX_NUM_NR_CHANNEL_BITS]; /// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14) - uint32_t d_mod[MAX_NUM_NR_RE]; + uint32_t d_mod[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); /// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4) uint32_t y[MAX_NUM_NR_RE] __attribute__ ((aligned(16))); /* @@ -292,6 +292,8 @@ typedef struct { uint16_t dlDmrsSymbPos; /// DMRS Configuration Type uint8_t dmrsConfigType; + // Number of DMRS CDM groups with no data + uint8_t n_dmrs_cdm_groups; /// Starting Symbol number uint16_t start_symbol; /// Current subband PMI allocation diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 4b36f91e69..6f5fba7812 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -57,7 +57,7 @@ void free_nr_ue_ulsch(NR_UE_ULSCH_t **ulschptr,unsigned char N_RB_UL) if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } @@ -114,7 +114,7 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL, if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; - a_segments = a_segments/273; + a_segments = a_segments/273 +1; } uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment @@ -225,8 +225,9 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, unsigned int crc; NR_UL_UE_HARQ_t *harq_process; uint16_t nb_rb ; - uint32_t A, Z, F; - uint32_t *pz; + uint32_t A, F; + static uint32_t Z = 0; + uint32_t *pz = &Z; uint8_t mod_order; uint16_t Kr,r; uint32_t r_offset; @@ -258,6 +259,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, Ilbrm = 0; Tbslbrm = 950984; //max tbs Coderate = 0.0; + harq_process->round = nr_rv_round_map_ue[harq_process->pusch_pdu.pusch_data.rv_index]; /////////// ///////////////////////////////////////////////////////////////////////////////////////// @@ -409,6 +411,8 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, /////////////////////////////////////////////////////////////////////////////// } + F = harq_process->F; + Kr = harq_process->K; for (r=0; rC; r++) { // looping over C segments @@ -420,19 +424,15 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, } } -#ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); -#endif + + LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n", + r, + G, + Kr*3, + mod_order,nb_rb, + harq_process->pusch_pdu.pusch_data.rv_index); //start_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", harq_process->pusch_pdu.pusch_data.rv_index); -#endif - ///////////////////////// d---->| Rate matching bit selection |---->e ///////////////////////// /////////// diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 93acda23f8..c85a7691f6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -93,14 +93,14 @@ void nr_pusch_codeword_scrambling(uint8_t *in, void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, unsigned char harq_pid, - uint8_t frame, + uint32_t frame, uint8_t slot, uint8_t thread_id, int gNB_id) { LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot); - uint32_t available_bits, TBS; + uint32_t available_bits; uint8_t mod_order, cwd_index, num_of_codewords, l; uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; uint32_t ***pusch_dmrs; @@ -113,7 +113,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, int ap, start_symbol, Nid_cell, i; int sample_offsetF, N_RE_prime, N_PRB_oh; uint16_t ul_dmrs_symb_pos; - uint8_t data_existing =0; uint8_t L_ptrs, K_ptrs; // PTRS parameters uint16_t beta_ptrs; // PTRS parameter related to power control @@ -121,7 +120,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, NR_UL_UE_HARQ_t *harq_process_ul_ue=NULL; NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; NR_UE_PUSCH *pusch_ue = UE->pusch_vars[thread_id][gNB_id]; - uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; // ptrs_UplinkConfig_t *ptrs_Uplink_Config = &UE->pusch_config.dmrs_UplinkConfig.ptrs_UplinkConfig; num_of_codewords = 1; // tmp assumption @@ -171,54 +169,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, 0, harq_process_ul_ue->pusch_pdu.nrOfLayers); - uint8_t access_mode = SCHEDULED_ACCESS; - - //-----------------------------------------------------// - // to be removed later when MAC is ready - - if (harq_process_ul_ue != NULL){ - TBS = harq_process_ul_ue->pusch_pdu.pusch_data.tb_size; - data_existing = 0; - - if (IS_SOFTMODEM_NOS1){ - data_existing = nr_ue_get_sdu(UE->Mod_id, UE->CC_id, frame, - slot, 0, ulsch_input_buffer, TBS/8, &access_mode); - //IP traffic to be transmitted - if(data_existing){ - //harq_process_ul_ue->a = (unsigned char*)calloc(harq_process_ul_ue->TBS/8, sizeof(unsigned char)); - memcpy(harq_process_ul_ue->a, ulsch_input_buffer, TBS/8); - } - } - //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity - if (!IS_SOFTMODEM_NOS1 || !data_existing) { - //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid - //and block this traffic from being forwarded to the upper layers at the gNB - LOG_D(PHY, "Random data to be tranmsitted: \n"); - - //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) - //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should - //have a valid LCID (nr_process_mac_pdu function) - harq_process_ul_ue->a[0] = 0x31; - - for (i = 1; i < TBS / 8; i++) { - harq_process_ul_ue->a[i] = (unsigned char) rand(); - //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - } - } -#ifdef DEBUG_MAC_PDU - LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS/8); - for (i = 0; i < TBS / 8; i++) { - printf("%02x",harq_process_ul_ue->a[i]); - } - printf("\n"); -#endif - } else { - LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n"); - return; - } - - //-----------------------------------------------------// - /////////////////////////ULSCH coding///////////////////////// /////////// @@ -268,7 +218,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////// pusch_dmrs = UE->nr_gold_pusch_dmrs[slot]; n_dmrs = (nb_rb*((dmrs_type == pusch_dmrs_type1) ? 6:4)*number_dmrs_symbols); - int16_t mod_dmrs[n_dmrs<<1]; + int16_t mod_dmrs[n_dmrs<<1] __attribute((aligned(16))); /////////// //////////////////////////////////////////////////////////////////////// @@ -276,12 +226,12 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////////////////////PTRS parameters' initialization///////////////////////// /////////// - int16_t mod_ptrs[(nb_rb/2)*(NR_SYMBOLS_PER_SLOT-1)*2]; // assume maximum number of PTRS per pusch allocation + int16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation K_ptrs = 0; // just to avoid a warning if (harq_process_ul_ue->pusch_pdu.pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { - K_ptrs = (harq_process_ul_ue->pusch_pdu.pusch_ptrs.ptrs_freq_density)?4:2; + K_ptrs = harq_process_ul_ue->pusch_pdu.pusch_ptrs.ptrs_freq_density; L_ptrs = 1<pusch_pdu.pusch_ptrs.ptrs_time_density; beta_ptrs = 1; // temp value until power control is implemented @@ -372,7 +322,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint16_t m=0, n=0, dmrs_idx=0, ptrs_idx = 0; for (l=start_symbol; lulsch[thread_id][gNB_id][0]->harq_processes[harq_pid]->pusch_pdu.nrOfLayers; // cw 0 /////////////////////////IFFT/////////////////////// /////////// -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - timing_advance = UE->timing_advance; -#else - timing_advance = 0; -#endif - - tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0) - timing_advance; - - if (tx_offset < 0) - tx_offset += frame_parms->samples_per_frame; + tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); // clear the transmit data array for the current subframe /*for (int aa=0; aaframe_parms.nb_antennas_tx; aa++) { @@ -512,49 +448,32 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, txdata = UE->common_vars.txdata; txdataF = UE->common_vars.txdataF; - if(UE->N_TA_offset > tx_offset) { - int32_t *tmp_idft_out = (int32_t*)malloc16(frame_parms->get_samples_per_slot(slot, frame_parms) * sizeof(int32_t)); - - for(ap = 0; ap < Nl; ap++) { - if (frame_parms->Ncp == 1) { // extended cyclic prefix - PHY_ofdm_mod(txdataF[ap], - tmp_idft_out, - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { // normal cyclic prefix - nr_normal_prefix_mod(txdataF[ap], - tmp_idft_out, - 14, - frame_parms); - } - - memcpy((void *) &txdata[ap][frame_parms->samples_per_frame - UE->N_TA_offset + tx_offset], - (void *) tmp_idft_out, - (UE->N_TA_offset - tx_offset) * sizeof(int32_t)); - - memcpy((void *) &txdata[ap][0], - (void *) &tmp_idft_out[UE->N_TA_offset - tx_offset], - (frame_parms->get_samples_per_slot(slot, frame_parms) - UE->N_TA_offset + tx_offset) * sizeof(int32_t)); + int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + for(ap = 0; ap < Nl; ap++) { + for (int s=0;s (%d.%d)\n", + s,s+symb_offset,frame_parms->symbol_rotation[2*(s+symb_offset)],frame_parms->symbol_rotation[1+(2*(s+symb_offset))]); + rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s], + &frame_parms->symbol_rotation[2*(s+symb_offset)], + (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s], + frame_parms->ofdm_symbol_size, + 15); } + } - free(tmp_idft_out); - } else { // UE->N_TA_offset <= tx_offset - for (ap = 0; ap < Nl; ap++) { - if (frame_parms->Ncp == 1) { // extended cyclic prefix - PHY_ofdm_mod(txdataF[ap], - &txdata[ap][tx_offset-UE->N_TA_offset], - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { // normal cyclic prefix - nr_normal_prefix_mod(txdataF[ap], - &txdata[ap][tx_offset-UE->N_TA_offset], - 14, - frame_parms); - } + for (ap = 0; ap < Nl; ap++) { + if (frame_parms->Ncp == 1) { // extended cyclic prefix + PHY_ofdm_mod(txdataF[ap], + &txdata[ap][tx_offset], + frame_parms->ofdm_symbol_size, + 12, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } else { // normal cyclic prefix + nr_normal_prefix_mod(txdataF[ap], + &txdata[ap][tx_offset], + 14, + frame_parms); } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index c977118df3..cf0fc716f9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -270,7 +270,6 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size; - for (int i=0; i < LENGTH_PSS_NR; i++) { synchroF_tmp[2*k] = primary_synchro[2*i]; synchroF_tmp[2*k+1] = primary_synchro[2*i+1]; diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index d2a8e64749..0b8111fc32 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -113,7 +113,7 @@ void nr_generate_pucch0(PHY_VARS_NR_UE *ue, // if frequency hopping is enabled n_hop = 1 for second hop. Not sure frequency hopping concerns format 0. FIXME!!! // if ((PUCCH_Frequency_Hopping == 1)&&(l == (nrofSymbols-1))) n_hop = 1; nr_group_sequence_hopping(pucch_GroupHopping,hoppingId,n_hop,nr_tti_tx,&u,&v); // calculating u and v value - alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,l,startingSymbolIndex,nr_tti_tx); + alpha = nr_cyclic_shift_hopping(hoppingId,m0,mcs,l,startingSymbolIndex,nr_tti_tx); #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u,v,alpha,l); #endif @@ -928,7 +928,17 @@ void nr_uci_encoding(uint64_t payload, 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) - b[0] = encodeSmallBlock((uint16_t*)&payload,A); + uint64_t b0= encodeSmallBlock((uint16_t*)&payload,A); + // repetition for rate-matching up to 16 PRB + b[0] = b0 | (b0<<32); + b[1] = b[0]; + b[2] = b[0]; + b[3] = b[0]; + b[4] = b[0]; + b[5] = b[0]; + b[6] = b[0]; + b[7] = b[0]; + AssertFatal(nrofPRB<=16,"Number of PRB >16\n"); } else if (A>=12) { AssertFatal(A<65,"Polar encoding not supported yet for UCI with more than 64 bits\n"); t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, @@ -963,7 +973,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint64_t b[16]; // limit to 1024-bit encoded length // 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,(void*)b,&M_bit); + nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,&b[0],&M_bit); /* * Implementing TS 38.211 * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2) @@ -985,7 +995,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ - nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,b,btilde); + nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,&b[0],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 @@ -1154,7 +1164,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, //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,(void*)b,&M_bit); + nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,&b[0],&M_bit); /* * Implementing TS 38.211 * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) @@ -1176,7 +1186,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, /* * 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); + nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,&b[0],btilde); /* * Implementing TS 38.211 Subclause 6.3.2.6.2 modulation formats 3 and 4 * diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index dfb148d34e..78e34036a3 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -26,6 +26,7 @@ #include #include "nr_phy_scope.h" #include "executables/nr-softmodem-common.h" +#include "executables/softmodem-common.h" #include #define TPUT_WINDOW_LENGTH 100 @@ -400,7 +401,8 @@ static void *scope_thread_gNB(void *arg) { // FILE *gNB_stats = fopen("gNB_stats.txt", "w"); //#endif size_t stksize=0; - pthread_attr_t atr= {0}; + pthread_attr_t atr; + pthread_attr_init(&atr); pthread_attr_getstacksize(&atr, &stksize); pthread_attr_setstacksize(&atr,32*1024*1024 ); sleep(3); // no clean interthread barriers @@ -523,32 +525,25 @@ static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_ if (!phy_vars_ue->pdcch_vars[0][eNB_id]->llr) return; - NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms; - uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; - uint8_t nb_antennas_tx = frame_parms->nb_antennas_tx; - scopeSample_t **chest_f = (scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates; - int ind = 0; - float chest_f_abs[frame_parms->ofdm_symbol_size]; - float freq[frame_parms->ofdm_symbol_size]; + int num_re = 4*273*12; // 12*frame_parms->N_RB_DL*num_pdcch_symbols + int Qm = 2; + int coded_bits_per_codeword = num_re*Qm; + localBuff(llr,coded_bits_per_codeword*RX_NB_TH_MAX); + localBuff(bit,coded_bits_per_codeword*RX_NB_TH_MAX); + int base=0; - for (int atx=0; atxofdm_symbol_size; k++) { - freq[ind] = (float)ind; - chest_f_abs[ind] = (short)10*log10(1.0+SquaredNorm(chest_f[(atx<<1)+arx][6144+k])); - ind++; - } - } + for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { + int16_t *pdcch_llr = (int16_t *) phy_vars_ue->pdcch_vars[thr][eNB_id]->llr; + + for (int i=0; ichest_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); - oai_xygraph(graph,freq,chest_f_abs,frame_parms->ofdm_symbol_size,0,10); + oai_xygraph(graph,bit,llr,base,0,10); } static void uePcchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { @@ -768,6 +763,15 @@ void nrUEinitScope(PHY_VARS_NR_UE *ue) { threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW); } + +void nrscope_autoinit(void *dataptr) { + AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context"); + + if (IS_SOFTMODEM_GNB_BIT) + gNBinitScope(dataptr); + else + nrUEinitScope(dataptr); +} // Kept to put back the functionality soon #if 0 //FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; @@ -795,6 +799,8 @@ static void reset_stats_gNB(FL_OBJECT *button, } } + + static FD_stats_form *create_form_stats_form(int ID) { FL_OBJECT *obj; FD_stats_form *fdui = calloc(( sizeof *fdui ),1); diff --git a/openair1/PHY/TOOLS/nr_phy_scope.h b/openair1/PHY/TOOLS/nr_phy_scope.h index 429537141a..84b9e66908 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.h +++ b/openair1/PHY/TOOLS/nr_phy_scope.h @@ -40,8 +40,6 @@ typedef struct { PHY_VARS_gNB *gNB; } scopeParms_t; -void gNBinitScope(scopeParms_t *p); -void nrUEinitScope(PHY_VARS_NR_UE *ue); extern RAN_CONTEXT_t RC; #endif diff --git a/openair1/PHY/TOOLS/phy_scope_interface.c b/openair1/PHY/TOOLS/phy_scope_interface.c index 835fb4ea7b..af237b2325 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.c +++ b/openair1/PHY/TOOLS/phy_scope_interface.c @@ -37,10 +37,10 @@ #define SOFTSCOPE_ENDFUNC_IDX 0 static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}}; -int load_softscope(char *exectype) { +int load_softscope(char *exectype, void *initarg) { char libname[64]; sprintf(libname,"%.10sscope",exectype); - return load_module_shlib(libname,scope_fdesc,1,NULL); + return load_module_shlib(libname,scope_fdesc,1,initarg); } int end_forms(void) { diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 779a57a720..adf04d5ea4 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -31,5 +31,5 @@ */ -int load_softscope(char *exectype); +int load_softscope(char *exectype, void *initarg); int end_forms(void) ; diff --git a/openair1/PHY/TOOLS/readme.md b/openair1/PHY/TOOLS/readme.md new file mode 100644 index 0000000000..f6671acc6d --- /dev/null +++ b/openair1/PHY/TOOLS/readme.md @@ -0,0 +1,12 @@ + +To use the scope, run the xNB or the UE with option "-d" + +Usage in gdb +In gdb, when you break, you can refresh immediatly the scope view by calling the display function. +The first paramter is the graph context, nevertheless we keep the last value for a dirty call in gdb (so you can use '0') + +Example with no variable known +phy_scope_nrUE(0, PHY_vars_UE_g[0][0], 0, 0, 0) + +or +phy_scope_gNB(0, phy_vars_gnb, phy_vars_ru, UE_id) diff --git a/openair1/PHY/defs_UE.h b/openair1/PHY/defs_UE.h index 9163fc13b6..e17b752e7b 100644 --- a/openair1/PHY/defs_UE.h +++ b/openair1/PHY/defs_UE.h @@ -452,55 +452,6 @@ typedef struct { uint32_t llr_length[14]; } LTE_UE_PDSCH; -typedef struct { - /// \brief Received frequency-domain signal after extraction. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **rxdataF_ext; - /// \brief Received frequency-domain signal after extraction and channel compensation. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **rxdataF_comp; - /// \brief Downlink channel estimates extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **dl_ch_estimates_ext; - /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_rho_ext; - /// \brief Downlink PMIs extracted in PRBS and grouped in subbands. - /// - first index: ressource block [0..N_RB_DL[ - uint8_t *pmi_ext; - /// \brief Magnitude of Downlink Channel (16QAM level/First 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_mag; - /// \brief Magnitude of Downlink Channel (2nd 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_magb; - /// \brief Cross-correlation of two eNB signals. - /// - first index: rx antenna [0..nb_antennas_rx[ - /// - second index: ? [0..] - double **rho; - /// never used... always send dl_ch_rho_ext instead... - double **rho_i; - /// \brief Pointers to llr vectors (2 TBs). - /// - first index: ? [0..1] (hard coded) - /// - second index: ? [0..1179743] (hard coded) - int16_t *llr[2]; - /// \f$\log_2(\max|H_i|^2)\f$ - uint8_t log2_maxh; - /// \brief Pointers to llr vectors (128-bit alignment). - /// - first index: ? [0..0] (hard coded) - /// - second index: ? [0..] - int16_t **llr128; - //uint32_t *rb_alloc; - //uint8_t Qm[2]; - //MIMO_mode_t mimo_mode; -} LTE_UE_PDSCH_FLP; - typedef struct { /// \brief Pointers to extracted PDCCH symbols in frequency-domain. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx @@ -667,7 +618,6 @@ typedef struct { uint8_t current_thread_id[10]; LTE_UE_PDSCH *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads - LTE_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; LTE_UE_PDSCH *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1]; diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index 75b2d54dc6..27765a8548 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -1094,5 +1094,4 @@ static inline int release_thread(pthread_mutex_t *mutex, return(0); } - #endif // __PHY_DEFS_COMMON_H__ diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index e2cdebff3a..179ca0331f 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -112,6 +112,26 @@ typedef struct { uint32_t F; } NR_DL_gNB_HARQ_t; +typedef struct { + int frame; + int slot; + nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu; +} NR_gNB_PDCCH_t; + +typedef struct { + int frame; + int slot; + nfapi_nr_ul_dci_request_pdus_t pdcch_pdu; +} NR_gNB_UL_PDCCH_t; + +typedef struct { + uint16_t rnti; + int round_trials[8]; + int total_bytes_tx; + int total_bytes_rx; + int current_Qm; + int current_RI; +} NR_gNB_SCH_STATS_t; typedef struct { /// Pointers to 16 HARQ processes for the DLSCH @@ -158,6 +178,8 @@ typedef struct { int16_t sqrt_rho_b; } NR_gNB_DLSCH_t; + + typedef struct { int frame; int slot; @@ -334,10 +356,6 @@ typedef struct { 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 { @@ -365,6 +383,8 @@ typedef struct { /// - second index: tx antenna [0..14[ where 14 is the total supported antenna ports. /// - third index: sample [0..] int32_t **txdataF; + int32_t *debugBuff; + int32_t debugBuff_sample_offset; } NR_gNB_COMMON; @@ -377,8 +397,6 @@ typedef struct { /// - first index: rx antenna id [0..nb_antennas_rx[ /// - second index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[ int32_t **rxdataF_ext2; - /// \brief Offset for calculating the index of rxdataF_ext for the current symbol - uint32_t rxdataF_ext_offset; /// \brief Hold the channel estimates in time domain based on DRS. /// - first index: rx antenna id [0..nb_antennas_rx[ /// - second index: ? [0..4*ofdm_symbol_size[ @@ -446,6 +464,13 @@ typedef struct { uint16_t ptrs_symbols; // PTRS subcarriers per OFDM symbol uint16_t ptrs_sc_per_ofdm_symbol; + /// \brief Estimated phase error based upon PTRS on each symbol . + /// - first index: ? [0..7] Number of Antenna + /// - second index: ? [0...14] smybol per slot + int32_t **ptrs_phase_per_slot; + /// \brief Total RE count after DMRS/PTRS RE's are extracted from respective symbol. + /// - first index: ? [0...14] smybol per slot + int16_t *ul_valid_re_per_slot; /// flag to verify if channel level computation is done uint8_t cl_done; } NR_gNB_PUSCH; @@ -674,21 +699,28 @@ typedef struct PHY_VARS_gNB_s { nfapi_nr_ul_tti_request_t UL_tti_req; nfapi_nr_uci_indication_t uci_indication; - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu; - nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu; + // nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu; + // nfapi_nr_ul_dci_request_pdus_t *ul_dci_pdu; nfapi_nr_dl_tti_ssb_pdu ssb_pdu; - int num_pdsch_rnti; + uint16_t num_pdsch_rnti[80]; NR_gNB_PBCH pbch; nr_cce_t cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL]; NR_gNB_COMMON common_vars; NR_gNB_PRACH prach_vars; NR_gNB_PUSCH *pusch_vars[NUMBER_OF_NR_ULSCH_MAX]; NR_gNB_PUCCH_t *pucch[NUMBER_OF_NR_PUCCH_MAX]; + NR_gNB_PDCCH_t pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX]; + NR_gNB_UL_PDCCH_t ul_pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX]; NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2]; // Nusers times two spatial streams NR_gNB_ULSCH_t *ulsch[NUMBER_OF_NR_ULSCH_MAX][2]; // [Nusers times][2 codewords] NR_gNB_DLSCH_t *dlsch_SI,*dlsch_ra,*dlsch_p; NR_gNB_DLSCH_t *dlsch_PCH; + /// statistics for DLSCH measurement collection + NR_gNB_SCH_STATS_t dlsch_stats[NUMBER_OF_NR_SCH_STATS_MAX]; + /// statistics for ULSCH measurement collection + NR_gNB_SCH_STATS_t ulsch_stats[NUMBER_OF_NR_SCH_STATS_MAX]; + t_nrPolar_params *uci_polarParams; uint8_t pbch_configured; @@ -715,6 +747,10 @@ typedef struct PHY_VARS_gNB_s { /// PUSCH DMRS uint32_t ****nr_gold_pusch_dmrs; + // Mask of occupied RBs + uint32_t rb_mask_ul[9]; + int ulmask_symb; + /// Indicator set to 0 after first SR uint8_t first_sr[NUMBER_OF_NR_SR_MAX]; @@ -769,15 +805,19 @@ typedef struct PHY_VARS_gNB_s { time_stats_t dlsch_interleaving_stats; time_stats_t dlsch_segmentation_stats; + time_stats_t rx_pusch_stats; time_stats_t ulsch_decoding_stats; time_stats_t ulsch_rate_unmatching_stats; time_stats_t ulsch_ldpc_decoding_stats; time_stats_t ulsch_deinterleaving_stats; time_stats_t ulsch_unscrambling_stats; time_stats_t ulsch_channel_estimation_stats; + time_stats_t ulsch_ptrs_processing_stats; time_stats_t ulsch_channel_compensation_stats; time_stats_t ulsch_rbs_extraction_stats; + time_stats_t ulsch_mrc_stats; time_stats_t ulsch_llr_stats; + /* time_stats_t rx_dft_stats; time_stats_t ulsch_freq_offset_estimation_stats; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 9bdf892ceb..62ffeaaea8 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -416,55 +416,6 @@ typedef struct { uint32_t llr_length[14]; } NR_UE_PDSCH; -typedef struct { - /// \brief Received frequency-domain signal after extraction. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **rxdataF_ext; - /// \brief Received frequency-domain signal after extraction and channel compensation. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **rxdataF_comp; - /// \brief Downlink channel estimates extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - int32_t **dl_ch_estimates_ext; - /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_rho_ext; - /// \brief Downlink PMIs extracted in PRBS and grouped in subbands. - /// - first index: ressource block [0..N_RB_DL[ - uint8_t *pmi_ext; - /// \brief Magnitude of Downlink Channel (16QAM level/First 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_mag; - /// \brief Magnitude of Downlink Channel (2nd 64QAM level). - /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx - /// - second index: ? [0..] - double **dl_ch_magb; - /// \brief Cross-correlation of two eNB signals. - /// - first index: rx antenna [0..nb_antennas_rx[ - /// - second index: ? [0..] - double **rho; - /// never used... always send dl_ch_rho_ext instead... - double **rho_i; - /// \brief Pointers to llr vectors (2 TBs). - /// - first index: ? [0..1] (hard coded) - /// - second index: ? [0..1179743] (hard coded) - int16_t *llr[2]; - /// \f$\log_2(\max|H_i|^2)\f$ - uint8_t log2_maxh; - /// \brief Pointers to llr vectors (128-bit alignment). - /// - first index: ? [0..0] (hard coded) - /// - second index: ? [0..] - int16_t **llr128; - //uint32_t *rb_alloc; - //uint8_t Qm[2]; - //MIMO_mode_t mimo_mode; -} NR_UE_PDSCH_FLP; - #define NR_PDCCH_DEFS_NR_UE #define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0) #define NR_NBR_SEARCHSPACE_ACT_BWP 10 // The number of SearchSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0) @@ -902,11 +853,6 @@ typedef struct { t_nrPolar_params *polarList; 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]; - NR_UE_PDSCH *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1]; - NR_UE_PDSCH *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1]; - NR_UE_PDSCH *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1]; - NR_UE_PDSCH *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; 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]; @@ -1022,7 +968,6 @@ typedef struct { /// Timing Advance updates variables /// Timing advance update computed from the TA command signalled from gNB int timing_advance; - int hw_timing_advance; int N_TA_offset; ///timing offset used in TDD NR_UL_TIME_ALIGNMENT_t ul_time_alignment[NUMBER_OF_CONNECTED_gNB_MAX]; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 584962c55c..a21af3fa03 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -111,6 +111,9 @@ #define MAX_NUM_NR_CHANNEL_BITS (14*273*12*8) // 14 symbols, 273 RB #define MAX_NUM_NR_RE (14*273*12) +extern const uint8_t nr_rv_round_map[4]; +extern const uint8_t nr_rv_round_map_ue[4]; + typedef enum { NR_MU_0=0, NR_MU_1, @@ -319,6 +322,8 @@ struct NR_DL_FRAME_PARMS { uint8_t nb_antenna_ports_gNB; /// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP) lte_prefix_type_t Ncp; + /// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211 + int16_t symbol_rotation[224*2]; /// shift of pilot position in one RB uint8_t nushift; /// SRS configuration from TS 38.331 RRC diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index a4607d3106..6c3d97838d 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -265,7 +265,7 @@ #define NB_NUMEROLOGIES_NR (5) #define TDD_CONFIG_NB_FRAMES (2) #define NR_MAX_SLOTS_PER_FRAME (160) /* number of slots per frame */ -#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (4) /* FFS_NR_TODO it defines ue capability which is the number of slots */ +#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (6) /* FFS_NR_TODO it defines ue capability which is the number of slots */ /* - between reception of pdsch and tarnsmission of its acknowlegment */ /* - between reception of un uplink grant and its related transmission */ diff --git a/openair1/PHY/phy_vars.h b/openair1/PHY/phy_vars.h index a74d148479..5e2be8bd8f 100644 --- a/openair1/PHY/phy_vars.h +++ b/openair1/PHY/phy_vars.h @@ -59,10 +59,10 @@ const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; unsigned char NB_RU=0; #ifndef OPENAIR2 -unsigned char NB_eNB_INST=0; -uint16_t NB_UE_INST=0; -unsigned char NB_RN_INST=0; -unsigned char NB_INST=0; +//unsigned char NB_eNB_INST=0; +//uint16_t NB_UE_INST=0; +//unsigned char NB_RN_INST=0; +//unsigned char NB_INST=0; #endif int number_of_cards; diff --git a/openair1/PHY/phy_vars_nr_ue.h b/openair1/PHY/phy_vars_nr_ue.h index 1843d8d5bc..baa64561f0 100644 --- a/openair1/PHY/phy_vars_nr_ue.h +++ b/openair1/PHY/phy_vars_nr_ue.h @@ -138,4 +138,4 @@ uint8_t scrambling_lut[65536*16] __attribute__((aligned(32))); uint8_t max_ldpc_iterations=4; uint8_t max_turbo_iterations=4; -#endif /*__PHY_VARS_H__ */ +#endif diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 558fa8d4eb..b3e3ab8c4e 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -20,12 +20,12 @@ */ /*! \file phy_procedures_lte_eNB.c - * \brief Implementation of eNB procedures from 36.213 LTE specifications - * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas + * \brief Implementation of eNB procedures from 36.213 LTE specifications / FeMBMS 36.231 LTE procedures v14.2 + * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas, J. Morgade * \date 2011 * \version 0.1 * \company Eurecom - * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk + * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk, javier.morgade@ieee.org * \note * \warning */ @@ -122,12 +122,32 @@ lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subfr } #ifdef MBMS_NFAPI_SCHEDULER -void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { +void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, int fembms_flag) { int subframe = proc->subframe_tx; // This is DL-Cell spec pilots in Control region - generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1); - if(eNB->dlsch_MCH->active==1) - generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/); + if(!fembms_flag){ + generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1); + generate_mbsfn_pilot(eNB,proc, + eNB->common_vars.txdataF, + AMP); + }else + generate_mbsfn_pilot_khz_1dot25(eNB,proc, + eNB->common_vars.txdataF, + AMP); + + if(eNB->dlsch_MCH->active==1){ + if(!fembms_flag){ + generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/); + } + else{ + generate_mch_khz_1dot25 (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/); + } + + LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (TBS %d) fembms %d \n", + eNB->Mod_id,proc->frame_tx,subframe, + eNB->dlsch_MCH->harq_processes[0]->TBS>>3,fembms_flag); + + } eNB->dlsch_MCH->active = 0; } #else @@ -171,6 +191,80 @@ void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } #endif +void common_signal_procedures_fembms (PHY_VARS_eNB *eNB,int frame, int subframe) { + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int **txdataF = eNB->common_vars.txdataF; + uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; + + if((frame&3)!=0 /*&& subframe != 0*/) + return; + + LOG_I(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s index:%d\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?",(frame&15)/4); + // generate Cell-Specific Reference Signals for both slots + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1); + + + if(subframe_select(fp,subframe) == SF_S) + generate_pilots_slot(eNB, + txdataF, + AMP, + subframe<<1,1); + else + generate_pilots_slot(eNB, + txdataF, + AMP, + subframe<<1,0); + + // check that 2nd slot is for DL + if (subframe_select (fp, subframe) == SF_DL) + generate_pilots_slot (eNB, txdataF, AMP, (subframe << 1) + 1, 0); + + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME (VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX, 0); + + // First half of PSS/SSS (FDD, slot 0) + if (subframe == 0) { + //if (fp->frame_type == FDD) { + generate_pss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 0); + generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 5 : 4, 0); + //} + + /// First half of SSS (TDD, slot 1) + + //if (fp->frame_type == TDD) { + generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 1); + //} + + // generate PBCH (Physical Broadcast CHannel) info + + /// generate PBCH + if ((frame&15)==0) { + //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n"); + if (eNB->pbch_configured!=1) return; + + eNB->pbch_configured=0; + } + + T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), + T_BUFFER(pbch_pdu, 3)); + generate_pbch_fembms (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, (frame & 15)/4); + } //else if ((subframe == 1) && (fp->frame_type == TDD)) { + //generate_pss (txdataF, AMP, fp, 2, 2); + // } + // Second half of PSS/SSS (FDD, slot 10) + else if ((subframe == 5) && (fp->frame_type == FDD) && is_fembms_nonMBSFN_subframe(frame,subframe,fp)) { + generate_pss (txdataF, AMP, &eNB->frame_parms, (fp->Ncp == NORMAL) ? 6 : 5, 10); + generate_sss (txdataF, AMP, &eNB->frame_parms, (fp->Ncp == NORMAL) ? 5 : 4, 10); + } + // Second-half of SSS (TDD, slot 11) + // else if ((subframe == 5) && (fp->frame_type == TDD)) { + // generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 11); + // } + // Second half of PSS (TDD, slot 12) + // else if ((subframe == 6) && (fp->frame_type == TDD)) { + // generate_pss (txdataF, AMP, fp, 2, 12); + // } +} + void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int **txdataF = eNB->common_vars.txdataF; @@ -417,12 +511,30 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, } if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_fembms_pmch_subframe(frame,subframe,fp)) { +#ifdef MBMS_NFAPI_SCHEDULER + pmch_procedures(eNB,proc,1); + LOG_D(MAC,"frame %d, subframe %d -> PMCH\n",frame,subframe); + return; +#endif + }else if(is_fembms_cas_subframe(frame,subframe,fp) || is_fembms_nonMBSFN_subframe(frame,subframe,fp)){ + LOG_D(MAC,"frame %d, subframe %d -> CAS\n",frame,subframe); + common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx); + //return; + } + + if((!is_fembms_cas_subframe(frame,subframe,fp)) && (!is_fembms_nonMBSFN_subframe(frame,subframe,fp))){ if (is_pmch_subframe(frame,subframe,fp)) { +#ifdef MBMS_NFAPI_SCHEDULER + pmch_procedures(eNB,proc,0); +#else pmch_procedures(eNB,proc); +#endif } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx); } + } } // clear existing ulsch dci allocations before applying info from MAC (this is table @@ -508,6 +620,18 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_fembms_pmch_subframe(frame,subframe,fp)) { +#ifdef MBMS_NFAPI_SCHEDULER + pmch_procedures(eNB,proc,1); + return; +#endif + }else if(is_fembms_cas_subframe(frame,subframe,fp)){ + common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx); + } + } + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); // Now scan UE specific DLSCH diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c index cb03821388..e472d64db4 100644 --- a/openair1/SCHED/ru_procedures.c +++ b/openair1/SCHED/ru_procedures.c @@ -41,6 +41,17 @@ * \warning */ +/*! \function feptx0 + * \brief Implementation of ofdm encoding for FeMBMS profile in one eNB + * \author J. Morgade + * \date 2020 + * \version 0.1 + * \email: javier.morgade@ieee.org + * \note + * \warning + */ + + #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" @@ -76,7 +87,7 @@ void feptx0(RU_t *ru, int slot_sizeF = (fp->ofdm_symbol_size) * ((fp->Ncp==1) ? 6 : 7); int subframe = ru->proc.tti_tx; - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+slot , 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(slot&1) , 1 ); slot_offset = slot*(fp->samples_per_tti>>1); //slot_offset = subframe*fp->samples_per_tti + (slot*(fp->samples_per_tti>>1)); @@ -91,7 +102,17 @@ void feptx0(RU_t *ru, fp->nb_prefix_samples, CYCLIC_PREFIX); } else { - if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)){ + if(is_fembms_pmch_subframe(ru->proc.frame_tx,subframe,fp)){ + if((slot&1)==0){//just use one slot chance + PHY_ofdm_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF], + (int*)&ru->common.txdata[aa][slot_offset], + fp->ofdm_symbol_size_khz_1dot25, + 1, + fp->ofdm_symbol_size_khz_1dot25>>2, + CYCLIC_PREFIX); + LOG_D(HW,"Generating PMCH FeMBMS TX subframe %d %d\n",subframe,fp->ofdm_symbol_size_khz_1dot25); + } + } else if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)){ if ((slot&1) == 0) {//just use one slot chance normal_prefix_mod(&ru->common.txdataF_BF[aa][(slot&1)*slot_sizeF], (int*)&ru->common.txdata[aa][slot_offset], diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 2870f1d42e..84490bfad4 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -94,9 +94,9 @@ void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, LOG_D(PHY,"Frame %d, Slot %d: DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure - gNB->pdcch_pdu = pdcch_pdu; + // gNB->pdcch_pdu = pdcch_pdu; - nr_fill_dci(gNB,frame,slot); + nr_fill_dci(gNB,frame,slot,pdcch_pdu); @@ -109,9 +109,9 @@ void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure - gNB->ul_dci_pdu = ul_dci_request_pdu; + // gNB->ul_dci_pdu = ul_dci_request_pdu; - nr_fill_ul_dci(gNB,frame,slot); + nr_fill_ul_dci(gNB,frame,slot,ul_dci_request_pdu); } @@ -154,13 +154,12 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ number_ul_dci_pdu,number_ul_tti_pdu); int pdcch_received=0; - gNB->num_pdsch_rnti=0; + gNB->num_pdsch_rnti[slot]=0; for (int i=0; idlsch[i][0]->rnti=0; gNB->dlsch[i][0]->harq_mask=0; } - gNB->pdcch_pdu = NULL; - gNB->ul_dci_pdu = NULL; + gNB->pbch_configured=0; for (int i=0;iSFN, UL_tti_req->Slot); nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); break; } } diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 560f47059a..9723b2f99e 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -87,14 +87,29 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { CYCLIC_PREFIX); else { if (fp->numerology_index != 0) { + + if (!(slot%(fp->slots_per_subframe/2))&&(first_symbol==0)) { // case where first symbol in slot has longer prefix + apply_nr_rotation(fp, + (int16_t*)&ru->common.txdataF_BF[aa][slot_offsetF], + slot, + 0, + 1, + fp->ofdm_symbol_size); - if (!(slot%(fp->slots_per_subframe/2))&&(first_symbol==0)) { PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], (int*)&ru->common.txdata[aa][slot_offset], fp->ofdm_symbol_size, 1, fp->nb_prefix_samples0, CYCLIC_PREFIX); + + apply_nr_rotation(fp, + (int16_t*)&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size], + slot, + 1, + num_symbols-1, + fp->ofdm_symbol_size); + PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size], (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size], fp->ofdm_symbol_size, @@ -102,7 +117,13 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples, CYCLIC_PREFIX); } - else { + else { // all symbols in slot have shorter prefix + apply_nr_rotation(fp, + (int16_t*)&ru->common.txdataF_BF[aa][slot_offsetF], + slot, + first_symbol, + num_symbols, + fp->ofdm_symbol_size); PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], (int*)&ru->common.txdata[aa][slot_offset], fp->ofdm_symbol_size, @@ -110,9 +131,8 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples, CYCLIC_PREFIX); } - } - - else { + } // numerology_index!=0 + else { //numerology_index == 0 for (uint16_t idx_sym=abs_first_symbol; idx_symcommon.txdataF_BF[aa][slot_offsetF], @@ -121,6 +141,12 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { 1, fp->nb_prefix_samples, CYCLIC_PREFIX); + apply_nr_rotation(fp, + (int16_t*)&ru->common.txdata[aa][slot_offset], + slot, + idx_sym, + 1, + fp->ofdm_symbol_size+fp->nb_prefix_samples); slot_offset += fp->nb_prefix_samples+fp->ofdm_symbol_size; } else { @@ -130,6 +156,12 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { 1, fp->nb_prefix_samples0, CYCLIC_PREFIX); + apply_nr_rotation(fp, + (int16_t*)&ru->common.txdata[aa][slot_offset], + slot, + 0, + 1, + fp->ofdm_symbol_size+fp->nb_prefix_samples0); slot_offset += fp->nb_prefix_samples0+fp->ofdm_symbol_size; } } diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 0ccb13fc7c..9d34f496b3 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -29,11 +29,9 @@ * ************************************************************************/ -#include "SCHED_NR_UE/defs.h" +#include "PHY/defs_nr_common.h" #include "PHY/defs_nr_UE.h" -#include "SCHED_NR_UE/phy_frame_config_nr.h" -#include "PHY/impl_defs_nr.h" -#include "PHY/impl_defs_top.h" +#include "SCHED_NR/phy_frame_config_nr.h" /******************************************************************* * @@ -369,73 +367,6 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti) } } -/******************************************************************* -* -* NAME : nr_ue_slot_select -* -* DESCRIPTION : function for the UE equivalent to nr_slot_select -* -*********************************************************************/ - -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) { - /* for FFD all slot can be considered as an uplink */ - int mu = cfg->ssb_config.scs_common, check_slot = 0; - - if (cfg->cell_config.frame_duplex_type == FDD) { - return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT); - } - - if (nr_frame%2 == 0) { - for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { - check_slot++; - } - } - - if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { - return (NR_UPLINK_SLOT); - } - - check_slot = 0; - - for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) { - check_slot++; - } - } - - if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { - return (NR_DOWNLINK_SLOT); - } else { - return (NR_MIXED_SLOT); - } - } else { - for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1< /************** DEFINE ********************************************/ #define TDD_CONFIG_NB_FRAMES (2) @@ -77,10 +76,9 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); * @param frame_parms NR DL Frame parameters * @param nr_frame : frame number * @param nr_tti : slot number - @returns nr_slot_t : downlink or uplink */ + @returns int : downlink, uplink or mixed slot type*/ -nr_slot_t nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti); -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti); +int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti); /** \brief This function frees tdd configuration for nr * @param frame_parms NR DL Frame parameters diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 992c908c5d..6dfe967edc 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -26,6 +26,7 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h" +#include "PHY/NR_TRANSPORT/nr_dci.h" #include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include "SCHED/sched_eNB.h" @@ -160,41 +161,41 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); + int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST); + int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST); - if (gNB->pdcch_pdu || gNB->ul_dci_pdu) { + LOG_D(PHY,"[gNB %d] Frame %d slot %d, pdcch_pdu_id %d, ul_pdcch_pdu_id %d\n", + gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id); + + if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) { LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", gNB->Mod_id, frame, slot, - gNB->ul_dci_pdu==NULL?0:gNB->ul_dci_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci, - gNB->pdcch_pdu==NULL?0:gNB->pdcch_pdu->pdcch_pdu_rel15.numDlDci); + gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci, + gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1); - nr_generate_dci_top(gNB->pdcch_pdu, - gNB->ul_dci_pdu, + nr_generate_dci_top(gNB, + pdcch_pdu_id>=0 ? &gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu : NULL, + ul_pdcch_pdu_id>=0 ? &gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu : NULL, gNB->nr_gold_pdcch_dmrs[slot], &gNB->common_vars.txdataF[0][txdataF_offset], AMP, *fp); - + + // free up entry in pdcch tables + if (pdcch_pdu_id>=0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1; + if (ul_pdcch_pdu_id>=0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0); + if (pdcch_pdu_id >= 0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1; + if (ul_pdcch_pdu_id >= 0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1; } - for (int i=0; inum_pdsch_rnti; i++) { + for (int i=0; inum_pdsch_rnti[slot]; i++) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); - LOG_D(PHY, "PDSCH generation started (%d)\n", gNB->num_pdsch_rnti); - nr_generate_pdsch(gNB->dlsch[i][0], - gNB->nr_gold_pdsch_dmrs[slot], - gNB->common_vars.txdataF, - AMP, frame, slot, fp, 0, - &gNB->dlsch_encoding_stats, - &gNB->dlsch_scrambling_stats, - &gNB->dlsch_modulation_stats, - &gNB->tinput, - &gNB->tprep, - &gNB->tparity, - &gNB->toutput, - &gNB->dlsch_rate_matching_stats, - &gNB->dlsch_interleaving_stats, - &gNB->dlsch_segmentation_stats); + LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot); + nr_generate_pdsch(gNB,frame, slot); + if ((frame&127) == 0) dump_pdsch_stats(gNB); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); } @@ -239,16 +240,30 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs pusch_pdu->qam_mod_order, pusch_pdu->nrOfLayers); - + + AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n", + pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); + LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n", + pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); //---------------------------------------------------------- //------------------- ULSCH unscrambling ------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_unscrambling_stats); - nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id]->llr, - G, - 0, - pusch_pdu->data_scrambling_id, - pusch_pdu->rnti); + nr_ulsch_unscrambling_optim(gNB->pusch_vars[ULSCH_id]->llr, + G, + 0, + pusch_pdu->data_scrambling_id, + pusch_pdu->rnti); stop_meas(&gNB->ulsch_unscrambling_stats); //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- @@ -266,13 +281,12 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH G); stop_meas(&gNB->ulsch_decoding_stats); - if (ret > gNB->ulsch[ULSCH_id][0]->max_ldpc_iterations){ - LOG_I(PHY, "ULSCH %d in error\n",ULSCH_id); + LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1); } else if(gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->b!=NULL){ - LOG_I(PHY, "ULSCH received ok \n"); + LOG_D(PHY, "ULSCH received ok \n"); nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 0); } } @@ -313,7 +327,9 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, LOG_D(PHY, "Estimated timing advance PUSCH is = %d, timing_advance_update is %d \n", sync_pos,timing_advance_update); // estimate UL_CQI for MAC (from antenna port 0 only) - int SNRtimes10 = dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]) - 300;//(10*gNB->measurements.n0_power_dB[0]); + int SNRtimes10 = dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0]) - (10*gNB->measurements.n0_power_dB[0]); + + LOG_D(PHY, "Estimated SNR for PUSCH is = %d dB\n", SNRtimes10/10); if (SNRtimes10 < -640) cqi=0; else if (SNRtimes10 > 635) cqi=255; @@ -332,7 +348,8 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, gNB->crc_pdu_list[num_crc].num_cb = pusch_pdu->pusch_data.num_cb; gNB->crc_pdu_list[num_crc].ul_cqi = cqi; gNB->crc_pdu_list[num_crc].timing_advance = timing_advance_update; - gNB->crc_pdu_list[num_crc].rssi = 0xffff; // invalid value as this is not yet computed + // in terms of dBFS range -128 to 0 with 0.1 step + gNB->crc_pdu_list[num_crc].rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0])); gNB->UL_INFO.crc_ind.number_crcs++; @@ -346,7 +363,7 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, gNB->rx_pdu_list[num_rx].harq_id = harq_pid; gNB->rx_pdu_list[num_rx].ul_cqi = cqi; gNB->rx_pdu_list[num_rx].timing_advance = timing_advance_update; - gNB->rx_pdu_list[num_rx].rssi = 0xffff; // invalid value as this is not yet computed + gNB->rx_pdu_list[num_rx].rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0])); if (crc_flag) gNB->rx_pdu_list[num_rx].pdu_length = 0; else { @@ -359,6 +376,71 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, pthread_mutex_unlock(&gNB->UL_INFO_mutex); } +// Function to fill UL RB mask to be used for N0 measurements +void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { + + int rb2, rb, nb_rb; + for (int symbol=0;symbol<14;symbol++) { + if (gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol].slot_config.value==1){ + nb_rb = 0; + for (int m=0;m<9;m++) gNB->rb_mask_ul[m] = 0; + gNB->ulmask_symb = -1; + + for (int i=0;ipucch[i]; + if (pucch) { + if ((pucch->active == 1) && + (pucch->frame == frame_rx) && + (pucch->slot == slot_rx) ) { + gNB->ulmask_symb = symbol; + nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch[i].pucch_pdu; + if ((symbol>=pucch_pdu->start_symbol_index) && + (symbol<(pucch_pdu->start_symbol_index + pucch_pdu->nr_of_symbols))){ + for (rb=0; rbprb_size; rb++) { + rb2 = rb+pucch_pdu->prb_start; + gNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + nb_rb+=pucch_pdu->prb_size; + } + } + } + } + for (int ULSCH_id=0;ULSCH_idulsch[ULSCH_id][0]; + int harq_pid; + NR_UL_gNB_HARQ_t *ulsch_harq; + + if ((ulsch) && + (ulsch->rnti > 0)) { + for (harq_pid=0;harq_pidharq_processes[harq_pid]; + AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); + if ((ulsch_harq->status == NR_ACTIVE) && + (ulsch_harq->frame == frame_rx) && + (ulsch_harq->slot == slot_rx) && + (ulsch_harq->handled == 0)){ + uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; + uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; + gNB->ulmask_symb = symbol; + if ((symbol>=symbol_start) && + (symbolulsch_pdu.rb_size; rb++) { + rb2 = rb+ulsch_harq->ulsch_pdu.rb_start; + gNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + nb_rb+=ulsch_harq->ulsch_pdu.rb_size; + } + } + } + } + //TODO Add check for PRACH as well? + } + if (nb_rbframe_parms.N_RB_UL) + return; + } + } +} + void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { uint8_t symbol; @@ -385,6 +467,9 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); + fill_ul_rb_mask(gNB, frame_rx, slot_rx); + gNB_I0_measurements(gNB); + for (int i=0;ipucch[i]; if (pucch) { @@ -431,42 +516,66 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) (ulsch->rnti > 0)) { // for for an active HARQ process for (harq_pid=0;harq_pidharq_processes[harq_pid]; + ulsch_harq = ulsch->harq_processes[harq_pid]; AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); if ((ulsch_harq->status == NR_ACTIVE) && (ulsch_harq->frame == frame_rx) && (ulsch_harq->slot == slot_rx) && (ulsch_harq->handled == 0)){ + LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n", + frame_rx,slot_rx); + #ifdef DEBUG_RXDATA NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; RU_t *ru = gNB->RU_list[0]; int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx,frame_parms,0); slot_offset -= ru->N_TA_offset; - char name[128]; - FILE *f; - sprintf(name, "rxdata.%d.%d.raw", frame_rx,slot_rx); - f = fopen(name, "w"); if (f == NULL) exit(1); - fwrite(&ru->common.rxdata[0][slot_offset],2,frame_parms->get_samples_per_slot(slot_rx,frame_parms)*2, f); - fclose(f); + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[0]=(int16_t)ulsch->rnti; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[1]=(int16_t)ulsch_harq->ulsch_pdu.rb_size; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[2]=(int16_t)ulsch_harq->ulsch_pdu.rb_start; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[3]=(int16_t)ulsch_harq->ulsch_pdu.nr_of_symbols; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[4]=(int16_t)ulsch_harq->ulsch_pdu.start_symbol_index; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[5]=(int16_t)ulsch_harq->ulsch_pdu.mcs_index; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[6]=(int16_t)ulsch_harq->ulsch_pdu.pusch_data.rv_index; + ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[7]=(int16_t)harq_pid; + memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset+4],&ru->common.rxdata[0][slot_offset],frame_parms->get_samples_per_slot(slot_rx,frame_parms)*sizeof(int32_t)); + gNB->common_vars.debugBuff_sample_offset+=(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4); + if(gNB->common_vars.debugBuff_sample_offset>((frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+2)*20)) { + FILE *f; + f = fopen("rxdata_buff.raw", "w"); if (f == NULL) exit(1); + fwrite((int16_t*)gNB->common_vars.debugBuff,2,(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4)*20*2, f); + fclose(f); + exit(-1); + } #endif uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1); - for(uint8_t symbol = symbol_start; symbol < symbol_end; symbol++) { - nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, symbol, harq_pid); - } + start_meas(&gNB->rx_pusch_stats); + for(uint8_t symbol = symbol_start; symbol < symbol_end; symbol++) { + no_sig = nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, symbol, harq_pid); + if (no_sig) { + LOG_I(PHY, "PUSCH not detected in symbol %d\n",symbol); + nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1); + return; + } + } + stop_meas(&gNB->rx_pusch_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,0); //LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); //LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,1); - nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid); + nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,0); break; } } } } + // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS + if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); } diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index f0481f4f32..24885f1bb4 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -34,7 +34,7 @@ #include "PHY/NR_TRANSPORT/nr_dci.h" #include "phy_frame_config_nr.h" - +void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx); void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp); void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, int frame_tx, int slot_tx, int do_meas); void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index f852ae4ae1..55c7cd0baf 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -106,6 +106,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->start_symbol = dlsch_config_pdu->start_symbol; dlsch0_harq->dlDmrsSymbPos = dlsch_config_pdu->dlDmrsSymbPos; dlsch0_harq->dmrsConfigType = dlsch_config_pdu->dmrsConfigType; + dlsch0_harq->n_dmrs_cdm_groups = dlsch_config_pdu->n_dmrs_cdm_groups; dlsch0_harq->mcs = dlsch_config_pdu->mcs; dlsch0_harq->rvidx = dlsch_config_pdu->rv; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; @@ -116,6 +117,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); dlsch0_harq->harq_ack.vDAI_DL = dlsch_config_pdu->dai; LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs); + } } } @@ -147,12 +149,32 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ // pusch config pdu pusch_config_pdu = &ul_config->ul_config_list[i].pusch_config_pdu; current_harq_pid = pusch_config_pdu->pusch_data.harq_process_id; - nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch0->harq_processes[current_harq_pid]->pusch_pdu; + NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch0->harq_processes[current_harq_pid]; - memcpy(pusch_pdu, pusch_config_pdu, sizeof(nfapi_nr_ue_pusch_pdu_t)); + if (harq_process_ul_ue){ + + nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &harq_process_ul_ue->pusch_pdu; + + memcpy(pusch_pdu, pusch_config_pdu, sizeof(nfapi_nr_ue_pusch_pdu_t)); + + ulsch0->f_pusch = pusch_config_pdu->absolute_delta_PUSCH; + + if (scheduled_response->tx_request){ + fapi_nr_tx_request_body_t *tx_req_body = scheduled_response->tx_request->tx_request_body; + + //harq_process_ul_ue->a = (unsigned char*)calloc(TBS/8, sizeof(unsigned char)); + memcpy(harq_process_ul_ue->a, tx_req_body->pdu, tx_req_body->pdu_length); + + harq_process_ul_ue->status = ACTIVE; + } + + } else { + + LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n"); + return -1; + + } - ulsch0->f_pusch = pusch_config_pdu->absolute_delta_PUSCH; - ulsch0->harq_processes[current_harq_pid]->status = ACTIVE; break; case (FAPI_NR_UL_CONFIG_TYPE_PUCCH): @@ -214,9 +236,6 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ } else { } - if (scheduled_response->tx_request != NULL){ - } else { - } } return 0; diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.h b/openair1/SCHED_NR_UE/phy_frame_config_nr.h index a7e78397fe..3669239578 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.h +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.h @@ -62,10 +62,18 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); * @param frame_parms NR DL Frame parameters * @param nr_frame : frame number * @param nr_tti : slot number - @returns nr_slot_t : downlink or uplink */ + @returns int : downlink or uplink */ int slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_tti); +/** \brief This function checks nr UE slot direction : downlink or uplink + * @param cfg : FAPI Config Request + * @param nr_frame : frame number + * @param nr_tti : slot number + @returns int : downlink, uplink or mixed slot type */ + +int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti); + /** \brief This function frees tdd configuration for nr * @param frame_parms NR DL Frame parameters @returns none */ diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c new file mode 100644 index 0000000000..640ffb4ac3 --- /dev/null +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c @@ -0,0 +1,99 @@ +/* + * 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 + */ + +/*********************************************************************** +* +* FILENAME : phy_frame_configuration_nr_ue.c +* +* DESCRIPTION : functions related to FDD/TDD configuration for NR +* see TS 38.213 11.1 Slot configuration +* and TS 38.331 for RRC configuration +* +************************************************************************/ + +#include "PHY/defs_nr_UE.h" + +/******************************************************************* +* +* NAME : nr_ue_slot_select +* +* DESCRIPTION : function for the UE equivalent to nr_slot_select +* +*********************************************************************/ + +int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) { + /* for FFD all slot can be considered as an uplink */ + int mu = cfg->ssb_config.scs_common, check_slot = 0; + + if (cfg->cell_config.frame_duplex_type == FDD) { + return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT); + } + + if (nr_frame%2 == 0) { + for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { + check_slot++; + } + } + + if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + return (NR_UPLINK_SLOT); + } + + check_slot = 0; + + for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) { + check_slot++; + } + } + + if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + return (NR_DOWNLINK_SLOT); + } else { + return (NR_MIXED_SLOT); + } + } else { + for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1<frame_parms; - - int nsymb; - int nr_tti_tx = proc->nr_tti_tx; - int frame_tx = proc->frame_tx; - int ulsch_start; - int overflow=0; -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - int k,l; - int dummy_tx_buffer[frame_parms->samples_per_subframe] __attribute__((aligned(16))); -#endif - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN); -#if UE_TIMING_TRACE - start_meas(&ue->ofdm_mod_stats); -#endif - nsymb = (frame_parms->Ncp == 0) ? 14 : 12; - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)//this is the EXPRESS MIMO case - ulsch_start = (ue->rx_offset+nr_tti_tx*frame_parms->samples_per_subframe- - ue->hw_timing_advance- - ue->timing_advance- - ue->N_TA_offset+5); - //LOG_E(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d]\n",nr_tti_tx, ulsch_start); - - if(ulsch_start < 0) - ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); - - if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe)) - ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); - - //LOG_E(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d]\n",nr_tti_tx, ulsch_start); -#else //this is the normal case - ulsch_start = (frame_parms->samples_per_subframe*nr_tti_tx)-ue->N_TA_offset; //-ue->timing_advance; -#endif //else EXMIMO - - //#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - if (empty_subframe) - { - //#if 1 - overflow = ulsch_start - 9*frame_parms->samples_per_subframe; - for (aa=0; aanb_antennas_tx; aa++) { - - if (overflow > 0) - { - memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*(frame_parms->samples_per_subframe-overflow)); - memset(&ue->common_vars.txdata[aa][0],0,4*overflow); - } - else - { - memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*frame_parms->samples_per_subframe); - } - } - /*#else - overflow = ulsch_start - 9*frame_parms->samples_per_subframe; - for (aa=0; aanb_antennas_tx; aa++) { - for (k=ulsch_start; ksamples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++) { - ((short*)ue->common_vars.txdata[aa])[2*k] = 0; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = 0; - } - - for (k=0; kcommon_vars.txdata[aa])[2*k] = 0; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = 0; - } - } - endif*/ - return; - } - - - if ((frame_tx%100) == 0) - LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: ulsch_start = %d (rxoff %d, HW TA %d, timing advance %d, TA_offset %d\n", - ue->Mod_id,frame_tx,nr_tti_tx, - ulsch_start, - ue->rx_offset, - ue->hw_timing_advance, - ue->timing_advance, - ue->N_TA_offset); - - - for (aa=0; aanb_antennas_tx; aa++) { - if (frame_parms->Ncp == 1) - PHY_ofdm_mod(&ue->common_vars.txdataF[aa][nr_tti_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - dummy_tx_buffer, -#else - &ue->common_vars.txdata[aa][ulsch_start], -#endif - frame_parms->ofdm_symbol_size, - nsymb, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - else - normal_prefix_mod(&ue->common_vars.txdataF[aa][nr_tti_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - dummy_tx_buffer, -#else - &ue->common_vars.txdata[aa][ulsch_start], -#endif - nsymb, - &ue->frame_parms); - - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - apply_7_5_kHz(ue,dummy_tx_buffer,0); - apply_7_5_kHz(ue,dummy_tx_buffer,1); -#else - apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0); - apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1); -#endif - - -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - overflow = ulsch_start - 9*frame_parms->samples_per_subframe; - - - for (k=ulsch_start,l=0; ksamples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++,l++) { - ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; - } - - for (k=0; kcommon_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4; - ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4; - } -#if defined(EXMIMO) - // handle switch before 1st TX nr_tti_rx, guarantee that the slot prior to transmission is switch on - for (k=ulsch_start - (frame_parms->samples_per_subframe>>1) ; kcommon_vars.txdata[aa][k+frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; - else if (k>(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)) - ue->common_vars.txdata[aa][k-frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE; - else - ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE; - } -#endif -#endif - /* - only for debug - LOG_I(PHY,"ul-signal [nr_tti_rx: %d, ulsch_start %d, TA: %d, rxOffset: %d, timing_advance: %d, hw_timing_advance: %d]\n",nr_tti_tx, ulsch_start, ue->N_TA_offset, ue->rx_offset, ue->timing_advance, ue->hw_timing_advance); - if( (crash == 1) && (nr_tti_tx == 0) ) - { - LOG_E(PHY,"***** DUMP TX Signal [ulsch_start %d] *****\n",ulsch_start); - write_output("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_subframe,1,1); - } - */ - - } //nb_antennas_tx - -#if UE_TIMING_TRACE - stop_meas(&ue->ofdm_mod_stats); -#endif - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_OUT); - -} - #endif UE_MODE_t get_nrUE_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t gNB_id){ @@ -1424,7 +1263,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_NR_UE *ue, } if (isBad) { - LOG_I(PHY,"Skip PUSCH generation!\n"); + LOG_D(PHY,"Skip PUSCH generation!\n"); ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0; } } @@ -2229,7 +2068,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, memset(ue->common_vars.txdataF[0], 0, sizeof(int)*14*ue->frame_parms.ofdm_symbol_size); - LOG_I(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); + LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); #if UE_TIMING_TRACE start_meas(&ue->phy_proc_tx); @@ -2250,30 +2089,28 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, */ if (get_softmodem_params()->usim_test==0) { - LOG_D(PHY, "Sending PUCCH\n"); + LOG_D(PHY, "Generating PUCCH\n"); pucch_procedures_ue_nr(ue, gNB_id, proc, - TRUE); + FALSE); } - LOG_D(PHY, "Sending data \n"); + LOG_D(PHY, "Sending Uplink data \n"); nr_ue_pusch_common_procedures(ue, - harq_pid, slot_tx, - thread_id, - gNB_id, - &ue->frame_parms); + &ue->frame_parms,1); + //ue->ulsch[thread_id][gNB_id][0]->harq_processes[harq_pid]->pusch_pdu.nrOfLayers); } //LOG_M("txdata.m","txs",ue->common_vars.txdata[0],1228800,1,1); /* RACH */ if (get_softmodem_params()->do_ra==1) { - if ((ue->UE_mode[gNB_id] == PRACH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { + if ((ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { nr_ue_prach_procedures(ue, proc, gNB_id, mode); } } - LOG_I(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); + LOG_D(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE @@ -3026,7 +2863,7 @@ void copy_harq_proc_struct(NR_DL_UE_HARQ_t *harq_processes_dest, NR_DL_UE_HARQ_t memcpy(harq_ack_dest, current_harq_ack, sizeof(nr_harq_status_t)); }*/ -void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_id, PDSCH_t pdsch, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1) { +int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_id, PDSCH_t pdsch, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1) { int nr_tti_rx = proc->nr_tti_rx; int m; @@ -3034,9 +2871,9 @@ void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB int first_symbol_flag=0; if (!dlsch0) - return; + return 0; if (dlsch0->active == 0) - return; + return 0; if (!dlsch1) { int harq_pid = dlsch0->current_harq_pid; @@ -3047,7 +2884,7 @@ void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB uint16_t s0 = dlsch0->harq_processes[harq_pid]->start_symbol; uint16_t s1 = dlsch0->harq_processes[harq_pid]->nb_symbols; - LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_tti_rx %d, harq_pid %d, rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n",ue->Mod_id,pdsch,nr_tti_rx,harq_pid,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->harq_processes[harq_pid]->dlDmrsSymbPos); + LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_tti_rx %d, harq_pid %d (%d), rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n",ue->Mod_id,pdsch,nr_tti_rx,harq_pid,dlsch0->harq_processes[harq_pid]->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->harq_processes[harq_pid]->dlDmrsSymbPos); // do channel estimation for first DMRS only for (m = s0; m < 3; m++) { @@ -3081,8 +2918,8 @@ void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB #endif // process DLSCH received in first slot // skip DMRS symbols (will have to check later if PDSCH/DMRS are multiplexed - if (((1<harq_processes[harq_pid]->dlDmrsSymbPos) == 0) - nr_rx_pdsch(ue, + if (((1<harq_processes[harq_pid]->dlDmrsSymbPos) == 0) { + if (nr_rx_pdsch(ue, pdsch, eNB_id, eNB_id_i, @@ -3092,20 +2929,25 @@ void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB first_symbol_flag, dual_stream_UE, i_mod, - dlsch0->current_harq_pid); + dlsch0->current_harq_pid) < 0) + return -1; + } else { // This is to adjust the llr offset in the case of skipping over a dmrs symbol (i.e. in case of no PDSCH REs in DMRS) - if (pdsch == RA_PDSCH) ue->pdsch_vars_ra[eNB_id]->llr_offset[m]=ue->pdsch_vars_ra[eNB_id]->llr_offset[m-1]; - else if (pdsch == PDSCH) nr_rx_pdsch(ue, - pdsch, - eNB_id, - eNB_id_i, - proc->frame_rx, - nr_tti_rx, // nr_tti_rx, - m, - first_symbol_flag, - dual_stream_UE, - i_mod, - dlsch0->current_harq_pid); + if (pdsch == RA_PDSCH) ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->llr_offset[m]=ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->llr_offset[m-1]; + else if (pdsch == PDSCH) { + if (nr_rx_pdsch(ue, + pdsch, + eNB_id, + eNB_id_i, + proc->frame_rx, + nr_tti_rx, // nr_tti_rx, + m, + first_symbol_flag, + dual_stream_UE, + i_mod, + dlsch0->current_harq_pid) < 0) + return -1; + } else AssertFatal(1==0,"not RA_PDSCH or PDSCH\n"); } if (pdsch == PDSCH) LOG_D(PHY,"Done processing symbol %d : llr_offset %d\n",m,ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]->llr_offset[m]); @@ -3124,6 +2966,7 @@ void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB } } // CRNTI active } + return 0; } // WIP fix: @@ -3289,9 +3132,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, NR_UE_PDSCH *pdsch_vars; uint8_t is_cw0_active = 0; uint8_t is_cw1_active = 0; - uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; - uint8_t nb_re_dmrs = (dmrs_type==NFAPI_NR_DMRS_TYPE1)?6:4; // TODO: should changed my mac - uint16_t length_dmrs = 1; //cfg->pdsch_config.dmrs_max_length.value; + uint8_t dmrs_type, nb_re_dmrs; + uint16_t length_dmrs = 1; uint16_t nb_symb_sch = 9; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; @@ -3316,6 +3158,13 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, is_cw0_active = dlsch0->harq_processes[harq_pid]->status; nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; + dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + if (dmrs_type==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; + } + else { + nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; + } if(dlsch1) is_cw1_active = dlsch1->harq_processes[harq_pid]->status; @@ -3335,14 +3184,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, if (1) { switch (pdsch) { case SI_PDSCH: - pdsch_vars = ue->pdsch_vars_SI[eNB_id]; - break; case RA_PDSCH: - pdsch_vars = ue->pdsch_vars_ra[eNB_id]; - break; case P_PDSCH: - pdsch_vars = ue->pdsch_vars_p[eNB_id]; - break; case PDSCH: pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][eNB_id]; break; @@ -3371,6 +3214,9 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } } + // exit dlsch procedures as there are no active dlsch + if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) + return; // start ldpc decode for CW 0 dlsch0->harq_processes[harq_pid]->G = nr_get_G(dlsch0->harq_processes[harq_pid]->nb_rb, @@ -3720,7 +3566,7 @@ void *UE_thread_slot1_dl_processing(void *arg) { int frame_rx; uint8_t nr_tti_rx; - uint8_t pilot0; + uint8_t pilot0; uint8_t pilot1; uint8_t slot1; @@ -4046,6 +3892,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, int coreset_nb_rb=0; int coreset_start_rb=0; + if (pdcch_vars->nb_search_space > 0) get_coreset_rballoc(pdcch_vars->pdcch_config[0].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); @@ -4055,7 +3902,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, if ((ue->decode_MIB == 1) && slot_pbch) { LOG_I(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - for (int i=1; i<4; i++) { nr_slot_fep(ue, @@ -4136,27 +3982,29 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, } else if (ue->dlsch_ra[0]->active == 1){ dlsch = ue->dlsch_ra[0]; } - AssertFatal(dlsch != NULL, "Unsupported mode\n"); - uint8_t harq_pid = dlsch->current_harq_pid; - NR_DL_UE_HARQ_t *dlsch0_harq = dlsch->harq_processes[harq_pid]; - uint16_t nb_symb_sch = dlsch0_harq->nb_symbols; - uint16_t start_symb_sch = dlsch0_harq->start_symbol; - int symb_dmrs = -1; - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - //to update from pdsch config + if (dlsch) { + uint8_t harq_pid = dlsch->current_harq_pid; + NR_DL_UE_HARQ_t *dlsch0_harq = dlsch->harq_processes[harq_pid]; + uint16_t nb_symb_sch = dlsch0_harq->nb_symbols; + uint16_t start_symb_sch = dlsch0_harq->start_symbol; + int symb_dmrs = -1; - for (int i=0;i<4;i++) if (((1<dlDmrsSymbPos) > 0) {symb_dmrs=i;break;} - AssertFatal(symb_dmrs>=0,"no dmrs in 0..3\n"); - LOG_D(PHY,"Initializing dmrs for symb %d DMRS mask %x\n",symb_dmrs,dlsch0_harq->dlDmrsSymbPos); - nr_gold_pdsch(ue,symb_dmrs,0, 1); + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); + //to update from pdsch config + + for (int i=0;i<4;i++) if (((1<dlDmrsSymbPos) > 0) {symb_dmrs=i;break;} + AssertFatal(symb_dmrs>=0,"no dmrs in 0..3\n"); + LOG_D(PHY,"Initializing dmrs for symb %d DMRS mask %x\n",symb_dmrs,dlsch0_harq->dlDmrsSymbPos); + nr_gold_pdsch(ue,symb_dmrs,0, 1); - for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ - nr_slot_fep(ue, + for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ + nr_slot_fep(ue, m, //to be updated from higher layer nr_tti_rx, 0, 0); + } } } else { LOG_D(PHY,"[UE %d] Frame %d, nr_tti_rx %d: No DCIs found\n", ue->Mod_id, frame_rx, nr_tti_rx); @@ -4168,9 +4016,10 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, start_meas(&ue->generic_stat); #endif // do procedures for C-RNTI + int ret_pdsch = 0; 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); - nr_ue_pdsch_procedures(ue, + ret_pdsch = nr_ue_pdsch_procedures(ue, proc, eNB_id, PDSCH, @@ -4265,7 +4114,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); #endif - nr_ue_dlsch_procedures(ue, + if (ret_pdsch >= 0) + nr_ue_dlsch_procedures(ue, proc, eNB_id, PDSCH, @@ -4603,6 +4453,8 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t if (ue->prach_cnt == 3) ue->prach_cnt = 0; + } else if (nr_prach == 2) { + nr_ra_succeeded(mod_id, ue->CC_id, gNB_id); } // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index e0ea4ef2b2..3215718f8e 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -2383,10 +2383,12 @@ void ue_pbch_procedures(uint8_t eNB_id, if (pbch_phase>=4) pbch_phase=0; +if((ue->frame_parms.FeMBMS_active == 0)|| is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || first_run) { + for (pbch_trials=0; pbch_trials<4; pbch_trials++) { //for (pbch_phase=0;pbch_phase<4;pbch_phase++) { //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); - if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { + if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || ue->frame_parms.FeMBMS_active) { pbch_tx_ant = rx_pbch_fembms(&ue->common_vars, ue->pbch_vars[eNB_id], &ue->frame_parms, @@ -2431,9 +2433,10 @@ void ue_pbch_procedures(uint8_t eNB_id, ue->pbch_vars[eNB_id]->pdu_errors_conseq = 0; - if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { + if(is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || ue->frame_parms.FeMBMS_active) { frame_tx = (int)((ue->pbch_vars[eNB_id]->decoded_output[2]&31)<<1); frame_tx += ue->pbch_vars[eNB_id]->decoded_output[1]>>7; + frame_tx = frame_tx<<4; frame_tx +=4*pbch_phase; } else { frame_tx = (((int)(ue->pbch_vars[eNB_id]->decoded_output[2]&0x03))<<8); @@ -2490,7 +2493,7 @@ void ue_pbch_procedures(uint8_t eNB_id, } if (LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)) { - LOG_UI(PHY,"[UE %d] frame %d, subframe %d, Received PBCH (MIB): nb_antenna_ports_eNB %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", + LOG_D(PHY,"[UE %d] frame %d, subframe %d, Received PBCH (MIB): nb_antenna_ports_eNB %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", ue->Mod_id, frame_rx, subframe_rx, @@ -2501,6 +2504,17 @@ void ue_pbch_procedures(uint8_t eNB_id, ue->frame_parms.phich_config_common.phich_duration, ue->frame_parms.phich_config_common.phich_resource); } + LOG_D(PHY,"[UE %d] frame %d, subframe %d, Received PBCH (MIB): nb_antenna_ports_eNB %d, tx_ant %d, frame_tx %d. N_RB_DL %d, phich_duration %d, phich_resource %d/6!\n", + ue->Mod_id, + frame_rx, + subframe_rx, + ue->frame_parms.nb_antenna_ports_eNB, + pbch_tx_ant, + frame_tx, + ue->frame_parms.N_RB_DL, + ue->frame_parms.phich_config_common.phich_duration, + ue->frame_parms.phich_config_common.phich_resource); + } else { if (LOG_DUMPFLAG(DEBUG_UE_PHYPROC)) { LOG_E(PHY,"[UE %d] frame %d, subframe %d, Error decoding PBCH!\n", @@ -2533,6 +2547,8 @@ void ue_pbch_procedures(uint8_t eNB_id, ue->pbch_vars[eNB_id]->pdu_errors_conseq); } +} //if((ue->frame_parms.FeMBMS_active == 0)|| is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || first_run) + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); } @@ -2877,10 +2893,19 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, int l; int ret=0; - if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms)) { + if (is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) || fembms_flag) { // LOG_D(PHY,"ue calling pmch subframe ..\n "); LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation\n", ue->Mod_id,frame_rx,subframe_rx); + if(fembms_flag) + pmch_mcs = ue_query_mch_fembms(ue->Mod_id, + CC_id, + frame_rx, + subframe_rx, + eNB_id, + &sync_area, + &mcch_active); + else pmch_mcs = ue_query_mch(ue->Mod_id, CC_id, frame_rx, @@ -2960,6 +2985,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, LOG_D(PHY,"start turbo decode for MCH %d.%d --> Nl %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->Nl); LOG_D(PHY,"start turbo decode for MCH %d.%d --> G %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->harq_processes[0]->G); LOG_D(PHY,"start turbo decode for MCH %d.%d --> Kmimo %d \n", frame_rx, subframe_rx, ue->dlsch_MCH[0]->Kmimo); + ret = dlsch_decoding(ue, ue->pdsch_vars_MCH[ue->current_thread_id[subframe_rx]][0]->llr[0], &ue->frame_parms, @@ -3007,14 +3033,14 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, // if (subframe_rx==9) // mac_xface->macphy_exit("Why are we exiting here?"); } else { // decoding successful - LOG_D(PHY,"[UE %d] Frame %d, subframe %d: PMCH OK (%d,%d), passing to L2 (TBS %d, iter %d,G %d)\n", + LOG_D(PHY,"[UE %d] Frame %d, subframe %d: PMCH OK (%d,%d), passing to L2 (TBS %d, iter %d,G %d) ret %d\n", ue->Mod_id, frame_rx,subframe_rx, ue->dlsch_mcch_errors[sync_area][0], ue->dlsch_mtch_errors[sync_area][0], ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, ue->dlsch_MCH[0]->max_turbo_iterations, - ue->dlsch_MCH[0]->harq_processes[0]->G); + ue->dlsch_MCH[0]->harq_processes[0]->G,ret); ue_send_mch_sdu(ue->Mod_id, CC_id, frame_rx, @@ -3022,6 +3048,8 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, ue->dlsch_MCH[0]->harq_processes[0]->TBS>>3, eNB_id,// not relevant in eMBMS context sync_area); + //dump_mch(ue,0,ue->dlsch_MCH[0]->harq_processes[0]->G,subframe_rx); + //exit_fun("nothing to add"); if (mcch_active == 1) ue->dlsch_mcch_received[sync_area][0]++; @@ -4429,6 +4457,15 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue, ue_pmch_procedures(ue,proc,eNB_id,abstraction_flag,1); return 0; } else { // this gets closed at end + if (is_fembms_cas_subframe(frame_rx,subframe_rx,&ue->frame_parms) || is_fembms_nonMBSFN_subframe(frame_rx,subframe_rx,&ue->frame_parms) ) { + l=0; + slot_fep(ue, + l, + subframe_rx<<1, + 0, + 0, + 0); + } pmch_flag = is_pmch_subframe(frame_rx,subframe_rx,&ue->frame_parms) ? 1 : 0; if (do_pdcch_flag) { diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index f65e1f9633..94214ab3b3 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -78,6 +78,8 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ +double DS_TDL = .03; + int emulate_rf = 0; int split73=0; void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { @@ -161,7 +163,7 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, // Multipath channel if (awgn_flag == 0) { multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im, - 2*UE->frame_parms.samples_per_tti,hold_channel); + 2*UE->frame_parms.samples_per_tti,hold_channel,0); // printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset); if(abstx==1 && num_rounds>1) @@ -1172,6 +1174,7 @@ int main(int argc, char **argv) { channel_model, N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + DS_TDL, forgetting_factor, rx_sample_offset, 0); @@ -1185,6 +1188,7 @@ int main(int argc, char **argv) { channel_model, N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + DS_TDL, forgetting_factor, rx_sample_offset, 0); diff --git a/openair1/SIMULATION/LTE_PHY/dummy_functions.c b/openair1/SIMULATION/LTE_PHY/dummy_functions.c index 5ec0f6e696..120e4845d9 100644 --- a/openair1/SIMULATION/LTE_PHY/dummy_functions.c +++ b/openair1/SIMULATION/LTE_PHY/dummy_functions.c @@ -67,6 +67,11 @@ int ue_query_mch(module_id_t Mod_id, uint8_t CC_id, uint32_t frame, sub_frame_t subframe, uint8_t eNB_index, uint8_t * sync_area, uint8_t * mcch_active){ return(0);} + +int ue_query_mch_fembms(module_id_t Mod_id, uint8_t CC_id, uint32_t frame, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t * sync_area, uint8_t * mcch_active){ return(0);} + void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync){} diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index 65415e7c68..5073be24f5 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -19,204 +19,1048 @@ * contact@openairinterface.org */ +/*! \file mbmssim.c + \brief Top-level MBMS DL simulator + \authors R. Knopp, J. Morgade + \date 2011 - 2014 (Knopp) / 2020 (Morgade) + \version 0.1 + \company Eurecom + \email: knopp@eurecom.fr, javier.morgade@ieee.org + \note + \warning +*/ + #include #include #include -#include -#include -#include +#include +#include -#include "SIMULATION/TOOLS/defs.h" -#include "SIMULATION/RF/defs.h" +#include "SIMULATION/TOOLS/sim.h" #include "PHY/types.h" -#include "PHY/defs.h" -#include "PHY/vars.h" -#include "SCHED/defs.h" -#include "SCHED/vars.h" -#include "LAYER2/MAC/vars.h" - -#ifdef XFORMS - #include "PHY/TOOLS/lte_phy_scope.h" -#endif //XFORMS +#include "PHY/defs_eNB.h" +#include "PHY/defs_UE.h" +#include "PHY/phy_vars.h" +#include "SCHED/sched_eNB.h" +#include "SCHED/sched_common_vars.h" +#include "LAYER2/MAC/mac_vars.h" #include "OCG_vars.h" +#include "common/utils/LOG/log.h" +#include "UTIL/LISTS/list.h" + #include "unitary_defs.h" -PHY_VARS_eNB *eNB; -PHY_VARS_UE *UE; +#include "PHY/TOOLS/lte_phy_scope.h" + +#include "dummy_functions.c" + +#include "PHY/MODULATION/modulation_common.h" +#include "PHY/MODULATION/modulation_eNB.h" +#include "PHY/MODULATION/modulation_UE.h" +#include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h" +#include "SCHED/sched_eNB.h" +#include "SCHED_UE/sched_UE.h" +#include "common/config/config_load_configmodule.h" +#include "PHY/INIT/phy_init.h" +#include "nfapi/oai_integration/vendor_ext.h" + +#define ENABLE_MBMS_SIM + +int enable_fembms=1; + +void feptx_ofdm(RU_t *ru); +void feptx_prec(RU_t *ru); double cpuf; +#define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) +//#define MCS_COUNT 23//added for PHY abstraction +#include + +int otg_enabled=0; +/*the following parameters are used to control the processing times calculations*/ +double t_tx_max = -1000000000; /*!< \brief initial max process time for tx */ +double t_rx_max = -1000000000; /*!< \brief initial max process time for rx */ +double t_tx_min = 1000000000; /*!< \brief initial min process time for tx */ +double t_rx_min = 1000000000; /*!< \brief initial min process time for rx */ +int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ +int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ + +THREAD_STRUCT thread_struct; + +int emulate_rf = 0; + +void handler(int sig) { + void *array[10]; + size_t size; + // get void*'s for all entries on the stack + size = backtrace(array, 10); + // print out all the frames to stderr + fprintf(stderr, "Error: signal %d:\n", sig); + backtrace_symbols_fd(array, size, 2); + exit(1); +} + + + +//DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_2A[2]; DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_1E[2]; +uint64_t DLSCH_alloc_pdu_1[2]; + #define UL_RB_ALLOC 0x1ff; #define CCCH_RB_ALLOC computeRIV(eNB->frame_parms.N_RB_UL,0,2) +//#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 +//#define DLSCH_RB_ALLOC 0x0001 +void do_OFDM_mod_l(int32_t **txdataF, int32_t **txdata, uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms) { + int aa, slot_offset, slot_offset_F; + slot_offset_F = (next_slot)*(frame_parms->ofdm_symbol_size)*((frame_parms->Ncp==1) ? 6 : 7); + slot_offset = (next_slot)*(frame_parms->samples_per_tti>>1); + + for (aa=0; aanb_antennas_tx; aa++) { + // printf("Thread %d starting ... aa %d (%llu)\n",omp_get_thread_num(),aa,rdtsc()); + if (frame_parms->Ncp == 1) + PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input + &txdata[aa][slot_offset], // output + frame_parms->ofdm_symbol_size, + 6, // number of symbols + frame_parms->nb_prefix_samples, // number of prefix samples + CYCLIC_PREFIX); + else { + normal_prefix_mod(&txdataF[aa][slot_offset_F], + &txdata[aa][slot_offset], + 7, + frame_parms); + } + } +} + +void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, int tx_lev,int hold_channel,int abstx, int num_rounds, int trials, int round, channel_desc_t *eNB2UE[4], + double *s_re[2],double *s_im[2],double *r_re[2],double *r_im[2],FILE *csv_fd) { + int i,u; + int aa,aarx,aatx; + double channelx,channely; + double sigma2_dB,sigma2; + double iqim=0.0; + + // printf("Copying tx ..., nsymb %d (n_tx %d), awgn %d\n",nsymb,eNB->frame_parms.nb_antennas_tx,awgn_flag); + for (i=0; i<2*UE->frame_parms.samples_per_tti; i++) { + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + if (awgn_flag == 0) { + s_re[aa][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]); + s_im[aa][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + } else { + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { + if (aa==0) { + r_re[aarx][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[aarx][i] = ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + } else { + r_re[aarx][i] += ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)]); + r_im[aarx][i] += ((double)(((short *)ru->common.txdata[aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); + } + } + } + } + } + + // Multipath channel + if (awgn_flag == 0) { + multipath_channel(eNB2UE[round],s_re,s_im,r_re,r_im, + 2*UE->frame_parms.samples_per_tti,hold_channel); + + // printf("amc: ****************** eNB2UE[%d]->n_rx = %d,dd %d\n",round,eNB2UE[round]->nb_rx,eNB2UE[round]->channel_offset); + if(abstx==1 && num_rounds>1) + if(round==0 && hold_channel==0) { + random_channel(eNB2UE[1],0); + random_channel(eNB2UE[2],0); + random_channel(eNB2UE[3],0); + } + + if (UE->perfect_ce==1) { + // fill in perfect channel estimates + freq_channel(eNB2UE[round],UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); + /* + LOG_M("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8); + LOG_M("channelF.m","chF",eNB2UE[round]->chF[0],12*UE->frame_parms.N_RB_DL + 1,1,8); + */ + } + } + + if(abstx) { + if (trials==0 && round==0) { + // calculate freq domain representation to compute SINR + freq_channel(eNB2UE[0], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + // snr=pow(10.0,.1*SNR); + fprintf(csv_fd,"%f,",SNR); + + for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) { + for (aarx=0; aarxnb_rx; aarx++) { + for (aatx=0; aatxnb_tx; aatx++) { + channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].x; + channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + + if(num_rounds>1) { + freq_channel(eNB2UE[1], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + + for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) { + for (aarx=0; aarxnb_rx; aarx++) { + for (aatx=0; aatxnb_tx; aatx++) { + channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].x; + channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + + freq_channel(eNB2UE[2], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + + for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) { + for (aarx=0; aarxnb_rx; aarx++) { + for (aatx=0; aatxnb_tx; aatx++) { + channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].x; + channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + + freq_channel(eNB2UE[3], ru->frame_parms.N_RB_DL,2*ru->frame_parms.N_RB_DL + 1); + + for (u=0; u<2*ru->frame_parms.N_RB_DL; u++) { + for (aarx=0; aarxnb_rx; aarx++) { + for (aatx=0; aatxnb_tx; aatx++) { + channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].x; + channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].y; + fprintf(csv_fd,"%e+i*(%e),",channelx,channely); + } + } + } + } + } + } + + //AWGN + // tx_lev is the average energy over the whole subframe + // but SNR should be better defined wrt the energy in the reference symbols + sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)ru->frame_parms.ofdm_symbol_size/(double)(ru->frame_parms.N_RB_DL*12)) - SNR; + sigma2 = pow(10,sigma2_dB/10); + + for (i=0; i<2*UE->frame_parms.samples_per_tti; i++) { + for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { + //printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]); + ((short *) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] = + (short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + ((short *) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] = + (short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); + } + } +} + +uint16_t +fill_tx_req(nfapi_tx_request_body_t *tx_req_body, + uint16_t absSF, + uint16_t pdu_length, + uint16_t pdu_index, + uint8_t *pdu) { + nfapi_tx_request_pdu_t *TX_req = &tx_req_body->tx_pdu_list[tx_req_body->number_of_pdus]; + LOG_D(MAC, "Filling TX_req %d for pdu length %d\n", + tx_req_body->number_of_pdus, pdu_length); + TX_req->pdu_length = pdu_length; + TX_req->pdu_index = pdu_index; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = pdu_length; + TX_req->segments[0].segment_data = pdu; + tx_req_body->tl.tag = NFAPI_TX_REQUEST_BODY_TAG; + tx_req_body->number_of_pdus++; + return (((absSF / 10) << 4) + (absSF % 10)); +} + +void +fill_mch_config(nfapi_dl_config_request_body_t *dl_req, + uint16_t length, + uint16_t pdu_index, + uint16_t rnti, + uint8_t resource_allocation_type, + uint16_t resource_block_coding, + uint8_t modulation, + uint16_t transmission_power, + uint8_t mbsfn_area_id){ + nfapi_dl_config_request_pdu_t *dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_MCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_mch_pdu)); + dl_config_pdu->mch_pdu.mch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG; + dl_config_pdu->mch_pdu.mch_pdu_rel8.length = length; + dl_config_pdu->mch_pdu.mch_pdu_rel8.pdu_index = pdu_index; + dl_config_pdu->mch_pdu.mch_pdu_rel8.rnti = rnti; + dl_config_pdu->mch_pdu.mch_pdu_rel8.resource_allocation_type = resource_allocation_type; + dl_config_pdu->mch_pdu.mch_pdu_rel8.resource_block_coding = resource_block_coding; + dl_config_pdu->mch_pdu.mch_pdu_rel8.modulation = modulation; + dl_config_pdu->mch_pdu.mch_pdu_rel8.transmission_power = transmission_power; + dl_config_pdu->mch_pdu.mch_pdu_rel8.mbsfn_area_id = mbsfn_area_id; + dl_req->number_pdu++; +} + +void +fill_dlsch_config(nfapi_dl_config_request_body_t *dl_req, + uint16_t length, + uint16_t pdu_index, + uint16_t rnti, + uint8_t resource_allocation_type, + uint8_t virtual_resource_block_assignment_flag, + uint16_t resource_block_coding, + uint8_t modulation, + uint8_t redundancy_version, + uint8_t transport_blocks, + uint8_t transport_block_to_codeword_swap_flag, + uint8_t transmission_scheme, + uint8_t number_of_layers, + uint8_t number_of_subbands, + // uint8_t codebook_index, + uint8_t ue_category_capacity, + uint8_t pa, + uint8_t delta_power_offset_index, + uint8_t ngap, + uint8_t nprb, + uint8_t transmission_mode, + uint8_t num_bf_prb_per_subband, + uint8_t num_bf_vector) { + nfapi_dl_config_request_pdu_t *dl_config_pdu = + &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length = length; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index = pdu_index; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = rnti; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = resource_allocation_type; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = virtual_resource_block_assignment_flag; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = resource_block_coding; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation = modulation; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version = redundancy_version; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks = transport_blocks; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag = transport_block_to_codeword_swap_flag; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme = transmission_scheme; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers = number_of_layers; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands = number_of_subbands; + // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index = codebook_index; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity = ue_category_capacity; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa = pa; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index = delta_power_offset_index; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap = ngap; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb = nprb; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = transmission_mode; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = num_bf_prb_per_subband; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = num_bf_vector; + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io = 0xFFFF; + dl_req->number_pdu++; +} + +void fill_MCH(PHY_VARS_eNB *eNB, + int frame, + int subframe, + Sched_Rsp_t *sched_resp, + uint8_t input_buffer[NUMBER_OF_UE_MAX][20000], + int n_rnti, + int common_flag, + int NB_RB, + int TPC, + int mcs1){ + + nfapi_dl_config_request_body_t *dl_req=&sched_resp->DL_req->dl_config_request_body; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_body_t *TX_req=&sched_resp->TX_req->tx_request_body; + int NB_RB4TBS = common_flag == 0 ? NB_RB : (2+TPC); + dl_req->number_dci=0; + dl_req->number_pdu=0; + TX_req->number_of_pdus=0; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + fill_mch_config( + dl_req, + get_TBS_DL(mcs1,NB_RB4TBS), + 0, + 0xfffd, + 0, + get_Qm(mcs1), + mcs1, + 6000, //equal to RS power + 0 //mbsfn_area_id + ); + + fill_tx_req(TX_req, + (frame * 10) + subframe, + get_TBS_DL(mcs1,NB_RB4TBS), + 0, + input_buffer[0]); +} + +void fill_DCI(PHY_VARS_eNB *eNB, + int frame, + int subframe, + Sched_Rsp_t *sched_resp, + uint8_t input_buffer[NUMBER_OF_UE_MAX][20000], + int n_rnti, + int n_users, + int transmission_mode, + int retrans, + int common_flag, + int NB_RB, + int DLSCH_RB_ALLOC, + int TPC, + int mcs1, + int mcs2, + int ndi, + int rv, + int pa, + int *num_common_dci, + int *num_ue_spec_dci, + int *num_dci) { + int k; + nfapi_dl_config_request_body_t *dl_req=&sched_resp->DL_req->dl_config_request_body; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_body_t *TX_req=&sched_resp->TX_req->tx_request_body; + int NB_RB4TBS = common_flag == 0 ? NB_RB : (2+TPC); + dl_req->number_dci=0; + dl_req->number_pdu=0; + TX_req->number_of_pdus=0; + + for(k=0; kdl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = (common_flag == 0) ? NFAPI_DL_DCI_FORMAT_1 : NFAPI_DL_DCI_FORMAT_1A; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = 4; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = (common_flag == 0) ? n_rnti+k : SI_RNTI; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (common_flag ==0 ) ? 1: 2; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = TPC; // dont adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = (common_flag == 0) ? ndi : 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = rv; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = (common_flag == 0) ? DLSCH_RB_ALLOC : computeRIV(eNB->frame_parms.N_RB_DL,0,NB_RB); + //deactivate second codeword + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = 0; + dl_req->number_dci++; + dl_req->number_pdu++; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + AssertFatal(TPC>=0 && TPC<2, "TPC should be 0 or 1\n"); + if(1){ + fill_mch_config( + dl_req, + get_TBS_DL(mcs1,NB_RB4TBS), + 0, + 0xfffd, + 0, + get_Qm(mcs1), + mcs1, + 6000, //equal to RS power + 0 //mbsfn_area_id + ); + + fill_tx_req(TX_req, + (frame * 10) + subframe, + get_TBS_DL(mcs1,NB_RB4TBS), + 0, + input_buffer[0]); + + }else{ + fill_dlsch_config(dl_req, + get_TBS_DL(mcs1,NB_RB4TBS), + (retrans > 0) ? -1 : 0, /* retransmission, no pdu_index */ + (common_flag == 0) ? n_rnti : SI_RNTI, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + DLSCH_RB_ALLOC, // resource_block_coding, + get_Qm(mcs1), + rv, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + transmission_mode == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + pa, // pa + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + transmission_mode, + 0, //number of PRBs treated as one subband, not used here + 0 // number of beamforming vectors, not used here + ); + fill_tx_req(TX_req, + (frame * 10) + subframe, + get_TBS_DL(mcs1,NB_RB4TBS), + 0, + input_buffer[k]); + } + break; + + case 3: + if (common_flag == 0) { + if (eNB->frame_parms.nb_antennas_tx == 2) { + if (eNB->frame_parms.frame_type == TDD) { + } else { + } + } + } + + break; + + case 4: + if (common_flag == 0) { + if (eNB->frame_parms.nb_antennas_tx == 2) { + if (eNB->frame_parms.frame_type == TDD) { + } else { + } + } else if (eNB->frame_parms.nb_antennas_tx == 4) { + } + } else { + } + + break; + + case 5: + case 6: + break; + + default: + printf("Unsupported Transmission Mode %d!!!\n",transmission_mode); + exit(-1); + break; + } + } + + *num_dci = dl_req->number_dci; + *num_ue_spec_dci = dl_req->number_dci; + *num_common_dci = 0; +} + +int n_users = 1; +int subframe=7; +int num_common_dci=0,num_ue_spec_dci=0,num_dci=0,num_pdcch_symbols=1; +uint16_t n_rnti=0x1234; + +int abstx=0; +int Nid_cell=0; +int N_RB_DL=25; +int tdd_config=3; +int dci_flag=0; +int threequarter_fs=0; +double snr_step=1,input_snr_step=1, snr_int=30; +double forgetting_factor=0.0; //in [0,1] 0 means a new channel every time, 1 means keep the same channel +int test_perf=0; +int n_frames; +int n_ch_rlz = 1; +int rx_sample_offset = 0; +int xforms=0; +int dump_table=0; +int loglvl=OAILOG_WARNING; +int mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0; +int two_thread_flag=0; +int num_rounds = 4;//,fix_rounds=0; +int perfect_ce = 0; +int extended_prefix_flag=0; +int verbose=0, help=0; +double SNR,snr0=-2.0,snr1,rate = 0; +int print_perf=0; + int main(int argc, char **argv) { - char c; - int i,l,l2,aa,aarx,k; - double sigma2, sigma2_dB=0,SNR,snr0=-2.0,snr1=0.0; - uint8_t snr1set=0; - double snr_step=1,input_snr_step=1; - int **txdata; - double s_re0[2*30720],s_im0[2*30720],s_re1[2*30720],s_im1[2*30720]; - double r_re0[2*30720],r_im0[2*30720],r_re1[2*30720],r_im1[2*30720]; - double *s_re[2]= {s_re0,s_re1},*s_im[2]= {s_im0,s_im1},*r_re[2]= {r_re0,r_re1},*r_im[2]= {r_im0,r_im1}; - double iqim = 0.0; - int subframe=1; - char fname[40];//, vname[40]; - uint8_t transmission_mode = 1,n_tx=1,n_rx=2; - uint16_t Nid_cell=0; - FILE *fd; - int eNB_id = 0; - unsigned char mcs=0,awgn_flag=0,round; - int n_frames=1; - channel_desc_t *eNB2UE; - uint32_t nsymb,tx_lev,tx_lev_dB; - uint8_t extended_prefix_flag=1; + int k,i,j,aa; + int re; + int s,Kr,Kr_bytes; LTE_DL_FRAME_PARMS *frame_parms; + double s_re0[30720*2],s_im0[30720*2],r_re0[30720*2],r_im0[30720*2]; + double s_re1[30720*2],s_im1[30720*2],r_re1[30720*2],r_im1[30720*2]; + double *s_re[2]= {s_re0,s_re1}; + double *s_im[2]= {s_im0,s_im1}; + double *r_re[2]= {r_re0,r_re1}; + double *r_im[2]= {r_im0,r_im1}; + uint8_t transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2; + int eNB_id = 0; + unsigned char round; + unsigned char i_mod = 2; + int NB_RB; + SCM_t channel_model=Rayleigh1; + // unsigned char *input_data,*decoded_output; + DCI_ALLOC_t da; + DCI_ALLOC_t *dci_alloc = &da; + unsigned int coded_bits_per_codeword=0,nsymb; //,tbs=0; + unsigned int tx_lev=0,tx_lev_dB=0,trials; + unsigned int errs[4],errs2[4],round_trials[4],dci_errors[4];//,num_layers; + memset(errs,0,4*sizeof(unsigned int)); + memset(errs2,0,4*sizeof(unsigned int)); + memset(round_trials,0,4*sizeof(unsigned int)); + memset(dci_errors,0,4*sizeof(unsigned int)); + //int re_allocated; + char fname[32],vname[32]; + FILE *bler_fd; + char bler_fname[256]; + FILE *time_meas_fd; + char time_meas_fname[256]; + // FILE *tikz_fd; + // char tikz_fname[256]; + FILE *input_trch_fd=NULL; + unsigned char input_trch_file=0; + FILE *input_fd=NULL; + unsigned char input_file=0; + channel_desc_t *eNB2UE[4]; + //uint8_t num_pdcch_symbols_2=0; + //char stats_buffer[4096]; + //int len; + //int u; + int n=0; + //int iii; + int ch_realization; + //int pmi_feedback=0; int hold_channel=0; - uint16_t NB_RB=25; - int tdd_config=3; - SCM_t channel_model=MBSFN; - unsigned char *input_buffer; - unsigned short input_buffer_length; - unsigned int ret; - unsigned int trials,errs[4]= {0,0,0,0}; //,round_trials[4]={0,0,0,0}; - uint8_t N_RB_DL=25,osf=1; - uint32_t perfect_ce = 0; - lte_frame_type_t frame_type = FDD; - uint32_t Nsoft = 1827072; - /* - #ifdef XFORMS - FD_lte_phy_scope_ue *form_ue; + // void *data; + // int ii; + // int bler; + double blerr[4]; + short *uncoded_ber_bit=NULL; + int osf=1; + frame_t frame_type = FDD; + FD_lte_phy_scope_ue *form_ue = NULL; char title[255]; + int numCCE=0; + //int dci_length_bytes=0,dci_length=0; + //double channel_bandwidth = 5.0, sampling_rate=7.68; + int common_flag=0,TPC=0; + double cpu_freq_GHz; + // time_stats_t ts;//,sts,usts; + int avg_iter,iter_trials; + int rballocset=0; + int test_passed=0; + double effective_rate=0.0; + char channel_model_input[10]="I"; + int TB0_active = 1; + // LTE_DL_UE_HARQ_t *dlsch0_ue_harq; + // LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq; + uint8_t Kmimo; + uint8_t ue_category=4; + uint32_t Nsoft; + int sf; + int CCE_table[800]; + opp_enabled=1; // to enable the time meas + FILE *csv_fd=NULL; + char csv_fname[FILENAME_MAX]; + int DLSCH_RB_ALLOC = 0; + int dci_received; + PHY_VARS_eNB *eNB; + RU_t *ru; + PHY_VARS_UE *UE=NULL; + nfapi_dl_config_request_t DL_req; + nfapi_ul_config_request_t UL_req; + nfapi_hi_dci0_request_t HI_DCI0_req; + nfapi_dl_config_request_pdu_t dl_config_pdu_list[MAX_NUM_DL_PDU]; + nfapi_tx_request_pdu_t tx_pdu_list[MAX_NUM_TX_REQUEST_PDU]; + nfapi_tx_request_t TX_req; + Sched_Rsp_t sched_resp; + int pa=dB0; +#if defined(__arm__) + FILE *proc_fd = NULL; + char buf[64]; + memset(buf,0,sizeof(buf)); + proc_fd = fopen("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq", "r"); - fl_initialize (&argc, argv, NULL, 0, 0); - form_ue = create_lte_phy_scope_ue(); - sprintf (title, "LTE DL SCOPE UE"); - fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); - #endif - */ - cpuf = get_cpu_freq_GHz(); - logInit(); - number_of_cards = 1; + if(!proc_fd) + printf("cannot open /sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq"); + else { + while(fgets(buf, 63, proc_fd)) + printf("%s", buf); + } - while ((c = getopt (argc, argv, "ahA:Cp:n:s:S:t:x:y:z:N:F:R:O:dm:i:Y")) != -1) { - switch (c) { + fclose(proc_fd); + cpu_freq_GHz = ((double)atof(buf))/1e6; +#else + cpu_freq_GHz = get_cpu_freq_GHz(); +#endif + printf("Detected cpu_freq %f GHz\n",cpu_freq_GHz); + memset((void *)&sched_resp,0,sizeof(sched_resp)); + sched_resp.DL_req = &DL_req; + sched_resp.UL_req = &UL_req; + sched_resp.HI_DCI0_req = &HI_DCI0_req; + sched_resp.TX_req = &TX_req; + memset((void *)&DL_req,0,sizeof(DL_req)); + memset((void *)&UL_req,0,sizeof(UL_req)); + memset((void *)&HI_DCI0_req,0,sizeof(HI_DCI0_req)); + memset((void *)&TX_req,0,sizeof(TX_req)); + DL_req.dl_config_request_body.dl_config_pdu_list = dl_config_pdu_list; + TX_req.tx_request_body.tx_pdu_list = tx_pdu_list; + set_parallel_conf("PARALLEL_SINGLE_THREAD"); + cpuf = cpu_freq_GHz; + //signal(SIGSEGV, handler); + //signal(SIGABRT, handler); + // default parameters + n_frames = 1000; + snr0 = 0; + // num_layers = 1; + perfect_ce = 0; + static paramdef_t options[] = { + { "awgn", "Use AWGN channel and not multipath", PARAMFLAG_BOOL, strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL }, + { "Abstx", "Turns on calibration mode for abstraction.", PARAMFLAG_BOOL, iptr:&abstx, defintval:0, TYPE_INT, 0 }, + { "bTDD", "Set the tdd configuration mode",0, iptr:&tdd_config, defintval:3, TYPE_INT, 0 }, + { "BnbRBs", "The LTE bandwith in RBs (100 is 20MHz)",0, iptr:&N_RB_DL, defintval:25, TYPE_INT, 0 }, + { "cPdcch", "Number of PDCCH symbols",0, iptr:&num_pdcch_symbols, defintval:1, TYPE_INT, 0 }, + { "CnidCell", "The cell id ",0, iptr:&Nid_cell, defintval:0, TYPE_INT, 0 }, + { "dciFlag", "Transmit the DCI and compute its error statistics", PARAMFLAG_BOOL, iptr:&dci_flag, defintval:0, TYPE_INT, 0 }, + { "Dtdd", "Enable tdd", PARAMFLAG_BOOL, strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL }, + { "eRounds", "Number of rounds",0, iptr:NULL, defintval:25, TYPE_INT, 0 }, + { "EsubSampling","three quarters sub-sampling",PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0 }, + { "f_snr_step", "step size of SNR, default value is 1.",0, dblptr:&input_snr_step, defdblval:1, TYPE_DOUBLE, 0 }, + { "Forgetting", "forgetting factor (0 new channel every trial, 1 channel constant)",0, dblptr:&forgetting_factor, defdblval:0.0, TYPE_DOUBLE, 0 }, + { "input_file", "input IQ data file",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + { "Input_file_trch", " Input filename for TrCH data (binary)",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + { "WtwoThreads", "two_thread_flag", PARAMFLAG_BOOL, iptr:&two_thread_flag, defintval:0, TYPE_INT, 0 }, + { "lMuMimo", "offset_mumimo_llr_drange_fix",0, u8ptr:&offset_mumimo_llr_drange_fix, defintval:0, TYPE_UINT8, 0 }, + { "mcs1", "The MCS for TB 1", 0, iptr:&mcs1, defintval:0, TYPE_INT, 0 }, + { "Mcs2", "The MCS for TB 2", 0, iptr:&mcs2, defintval:0, TYPE_INT, 0 }, + { "Operf", "Set the percenatge of effective rate to testbench the modem performance (typically 30 and 70, range 1-100)",0, iptr:&test_perf, defintval:0, TYPE_INT, 0 }, + { "tmcs_i", "MCS of interfering UE",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + { "nb_frame", "number of frame in a test",0, iptr:&n_frames, defintval:1, TYPE_INT, 0 }, + { "offsetRxSample", "Sample offset for receiver", 0, iptr:&rx_sample_offset, defintval:0, TYPE_INT, 0 }, + { "rballocset", "ressource block allocation (see section 7.1.6.3 in 36.213)",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + { "snr", "Starting SNR, runs from SNR to SNR+%.1fdB in steps of %.1fdB. If n_frames is 1 then just SNR is simulated and MATLAB/OCTAVE output is generated", dblptr:&snr0, defdblval:-2.0, TYPE_DOUBLE, 0 }, + { "wsnrInterrupt", "snr int ?", 0, dblptr:&snr_int, defdblval:30, TYPE_DOUBLE, 0 }, + { "N_ch_rlzN0", "Determines the number of Channel Realizations in Abstraction mode. Default value is 1",0, iptr:&n_ch_rlz, defintval:1, TYPE_INT, 0 }, + { "prefix_extended","Enable extended prefix", PARAMFLAG_BOOL, iptr:&extended_prefix_flag, defintval:0, TYPE_INT, 0 }, + { "RNumRound", "Number of HARQ rounds (fixed)",0, iptr:&num_rounds, defintval:4, TYPE_INT, 0 }, + { "Subframe", "subframe ",0, iptr:&subframe, defintval:7, TYPE_INT, 0 }, + { "Trnti", "rnti",0, u16ptr:&n_rnti, defuintval:0x1234, TYPE_UINT16, 0 }, + { "vi_mod", "i_mod",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + { "Qparallel", "Enable parallel execution",0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0 }, + { "Performance", "Display CPU perfomance of each L1 piece", PARAMFLAG_BOOL, iptr:&print_perf, defintval:0, TYPE_INT, 0 }, + { "q_tx_port", "Number of TX antennas ports used in eNB",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + { "uEdual", "Enables the Interference Aware Receiver for TM5 (default is normal receiver)",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + { "xTransmission","Transmission mode (1,2,6,7 for the moment)",0, iptr:NULL, defintval:25, TYPE_INT, 0 }, + { "yn_tx_phy","Number of TX antennas used in eNB",0, iptr:NULL, defintval:25, TYPE_INT, 0 }, + { "XForms", "Display the soft scope", PARAMFLAG_BOOL, iptr:&xforms, defintval:0, TYPE_INT, 0 }, + { "Yperfect_ce","Perfect CE", PARAMFLAG_BOOL, iptr:&perfect_ce, defintval:0, TYPE_INT, 0 }, + { "Zdump", "dump table",PARAMFLAG_BOOL, iptr:&dump_table, defintval:0, TYPE_INT, 0 }, + { "Loglvl", "log level",0, iptr:&loglvl, defintval:OAILOG_DEBUG, TYPE_INT, 0 }, + { "zn_rx", "Number of RX antennas used in UE",0, iptr:NULL, defintval:2, TYPE_INT, 0 }, + { "gchannel", "[A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')",0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0 }, + { "verbose", "display debug text", PARAMFLAG_BOOL, iptr:&verbose, defintval:0, TYPE_INT, 0 }, + { "mmse", "Use MMSE whitening", PARAMFLAG_BOOL, strptr:NULL, defintval:0, TYPE_INT, 0, NULL, NULL }, + { "help", "display help and exit", PARAMFLAG_BOOL, iptr:&help, defintval:0, TYPE_INT, 0 }, + { "", "",0, iptr:NULL, defintval:0, TYPE_INT, 0 }, + }; + struct option *long_options = parse_oai_options(options); + int option_index; + int res; + + while ((res=getopt_long_only(argc, argv, "", long_options, &option_index)) == 0) { + if (options[option_index].voidptr != NULL ) { + if (long_options[option_index].has_arg==no_argument) + *(bool *)options[option_index].iptr=1; + else switch (options[option_index].type) { + case TYPE_INT: + *(int *)options[option_index].iptr=atoi(optarg); + break; + + case TYPE_DOUBLE: + *(double *)options[option_index].dblptr=atof(optarg); + break; + + case TYPE_UINT8: + *(uint8_t *)options[option_index].dblptr=atoi(optarg); + break; + + case TYPE_UINT16: + *(uint16_t *)options[option_index].dblptr=atoi(optarg); + break; + + default: + printf("not decoded type.\n"); + exit(1); + } + + continue; + } + + switch (long_options[option_index].name[0]) { case 'a': - awgn_flag=1; + awgn_flag = 1; + channel_model = AWGN; break; - case 'd': - frame_type = 0; + case 'D': + frame_type=TDD; break; - case 'n': - n_frames = atoi(optarg); - break; - - case 'm': - mcs=atoi(optarg); - break; - - case 's': - snr0 = atof(optarg); - msg("Setting SNR0 to %f\n",snr0); + case 'e': + num_rounds=1; + common_flag = 1; + TPC = atoi(optarg); break; case 'i': - input_snr_step = atof(optarg); + input_fd = fopen(optarg,"r"); + input_file=1; + dci_flag = 1; break; - case 'S': - snr1 = atof(optarg); - snr1set=1; - msg("Setting SNR1 to %f\n",snr1); + case 'I': + input_trch_fd = fopen(optarg,"r"); + input_trch_file=1; break; - case 'p': // subframe no; - subframe=atoi(optarg); + case 't': + mcs_i = atoi(optarg); + i_mod = get_Qm(mcs_i); + break; + + case 'r': + DLSCH_RB_ALLOC = atoi(optarg); + rballocset = 1; + break; + + case 'g': + strncpy(channel_model_input,optarg,9); + struct tmp { + char opt; + int m; + int M; + } + tmp[]= { + {'A',SCM_A,2}, + {'B',SCM_B,3}, + {'C',SCM_C,4}, + {'D',SCM_D,5}, + {'E',EPA,6}, + {'F',EVA,6}, + {'G',ETU,8}, + {'H',Rayleigh8,9}, + {'I',Rayleigh1,10}, + {'J',Rayleigh1_corr,11}, + {'K',Rayleigh1_anticorr,12}, + {'L',Rice8,13}, + {'M',Rice1,14}, + {'N',AWGN,1}, + {0,0,0} + }; + struct tmp *ptr; + + for (ptr=tmp; ptr->opt!=0; ptr++) + if ( ptr->opt == optarg[0] ) { + channel_model=ptr->m; + break; + } + + AssertFatal(ptr->opt != 0, "Unsupported channel model: %s !\n", optarg ); + break; + + case 'u': + dual_stream_UE=1; + + if (UE != NULL) + UE->use_ia_receiver = 1; + else { + printf("UE is NULL\n"); + exit(-1); + } + + if ((n_tx_port!=2) || (transmission_mode!=5)) { + printf("IA receiver only supported for TM5!"); + exit(-1); + } + + break; + + case 'v': + i_mod = atoi(optarg); + + if (i_mod!=2 && i_mod!=4 && i_mod!=6) { + printf("Wrong i_mod %d, should be 2,4 or 6\n",i_mod); + exit(-1); + } + + break; + + case 'q': + n_tx_port=atoi(optarg); + + if ((n_tx_port==0) || ((n_tx_port>2))) { + printf("Unsupported number of cell specific antennas ports %d\n",n_tx_port); + exit(-1); + } + + break; + + case 'x': + transmission_mode=atoi(optarg); + + if ((transmission_mode!=1) && + (transmission_mode!=2) && + (transmission_mode!=3) && + (transmission_mode!=4) && + (transmission_mode!=5) && + (transmission_mode!=6) && + (transmission_mode!=7)) { + printf("Unsupported transmission mode %d\n",transmission_mode); + exit(-1); + } + + if (transmission_mode>1 && transmission_mode<7) { + n_tx_port = 2; + } + + break; + + case 'y': + n_tx_phy=atoi(optarg); + + if (n_tx_phy < n_tx_port) { + printf("n_tx_phy mush not be smaller than n_tx_port"); + exit(-1); + } + + if ((transmission_mode>1 && transmission_mode<7) && n_tx_port<2) { + printf("n_tx_port must be >1 for transmission_mode %d\n",transmission_mode); + exit(-1); + } + + if (transmission_mode==7 && (n_tx_phy!=1 && n_tx_phy!=2 && n_tx_phy!=4 && n_tx_phy!=8 && n_tx_phy!=16 && n_tx_phy!=64 && n_tx_phy!=128)) { + printf("Physical number of antennas not supported for TM7.\n"); + 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); + printf("Unsupported number of rx antennas %d\n",n_rx); exit(-1); } break; - case 'N': - Nid_cell = atoi(optarg); - break; - - case 'R': - N_RB_DL = atoi(optarg); - - if ((N_RB_DL!=6) && (N_RB_DL!=25) && (N_RB_DL!=50) && (N_RB_DL!=100)) { - printf("Unsupported Bandwidth %d\n",N_RB_DL); - exit(-1); - } - - break; - - case 'O': - osf = atoi(optarg); - break; - - case 'Y': - perfect_ce = 1; + case 'Q': + set_parallel_conf(optarg); break; default: - case 'h': - printf("%s -h(elp) -p(subframe) -N cell_id -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -i snr increment -z RXant \n",argv[0]); - printf("-h This message\n"); - printf("-a Use AWGN Channel\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("-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); + printf("Wrong option: %s\n",long_options[option_index].name); + exit(1); break; } } - if (awgn_flag == 1) - channel_model = AWGN; - - // check that subframe is legal for eMBMS - - if ((subframe == 0) || (subframe == 5) || // TDD and FDD SFn 0,5; - ((frame_type == FDD) && ((subframe == 4) || (subframe == 9))) || // FDD SFn 4,9; - ((frame_type == TDD ) && ((subframe<3) || (subframe==6)))) { // TDD SFn 1,2,6; - printf("Illegal subframe %d for eMBMS transmission (frame_type %d)\n",subframe,frame_type); - exit(-1); + if ( res != -1 ) { + printf("A wrong option has been found\n"); + exit(1); } - if (transmission_mode==2) - n_tx=2; + if (help || verbose ) + display_options_values(options, true); - lte_param_init(n_tx, - n_tx, + if (help) + exit(0); + if (thread_struct.parallel_conf != PARALLEL_SINGLE_THREAD) + set_worker_conf("WORKER_ENABLE"); + + if (transmission_mode>1) pa=dBm3; + + printf("dlsim: tmode %d, pa %d\n",transmission_mode,pa); + AssertFatal(load_configmodule(argc,argv, CONFIG_ENABLECMDLINEONLY) != NULL, + "cannot load configuration module, exiting\n"); + logInit(); + set_glog_onlinelog(true); + // enable these lines if you need debug info + set_glog(loglvl); + SET_LOG_DEBUG(UE_TIMING); + // moreover you need to init itti with the following line + // however itti will catch all signals, so ctrl-c won't work anymore + // alternatively you can disable ITTI completely in CMakeLists.txt + //itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, NULL); + + if (common_flag == 0) { + switch (N_RB_DL) { + case 6: + if (rballocset==0) DLSCH_RB_ALLOC = 0x3f; + + num_pdcch_symbols = 3; + break; + + case 25: + if (rballocset==0) DLSCH_RB_ALLOC = 0x1fff; + + break; + + case 50: + if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffff; + + break; + + case 100: + if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffffff; + + break; + } + + NB_RB = conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL); + } else { + if (rballocset==0) NB_RB = 8; + else NB_RB = DLSCH_RB_ALLOC; + + AssertFatal(NB_RB <= N_RB_DL,"illegal NB_RB %d\n",NB_RB); + } + + if (xforms==1) { + fl_initialize (&argc, argv, NULL, 0, 0); + form_ue = create_lte_phy_scope_ue(); + sprintf (title, "LTE PHY SCOPE eNB"); + fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + + if (!dual_stream_UE==0) { + if (UE) { + UE->use_ia_receiver = 1; + fl_set_button(form_ue->button_0,1); + fl_set_object_label(form_ue->button_0, "IA Receiver ON"); + fl_set_object_color(form_ue->button_0, FL_GREEN, FL_GREEN); + } else { + printf("UE is NULL\n"); + exit(-1); + } + } + } + + if (transmission_mode==5) { + n_users = 2; + printf("dual_stream_UE=%d\n", dual_stream_UE); + } + + RC.nb_L1_inst = 1; + RC.nb_RU = 1; + lte_param_init(&eNB,&UE,&ru, + n_tx_port, + n_tx_phy, + 1, n_rx, transmission_mode, extended_prefix_flag, @@ -224,281 +1068,1251 @@ int main(int argc, char **argv) { Nid_cell, tdd_config, N_RB_DL, - 0, + pa, + threequarter_fs, osf, perfect_ce); + RC.eNB = (PHY_VARS_eNB ** *)malloc(sizeof(PHY_VARS_eNB **)); + RC.eNB[0] = (PHY_VARS_eNB **)malloc(sizeof(PHY_VARS_eNB *)); + RC.ru = (RU_t **)malloc(sizeof(RC.ru)); + RC.eNB[0][0] = eNB; + RC.ru[0] = ru; + printf("lte_param_init done\n"); - if (snr1set==0) { - if (n_frames==1) - snr1 = snr0+.1; - else - snr1 = snr0+5.0; + if ((transmission_mode==1) || (transmission_mode==7)) { + for (aa=0; aanb_tx; aa++) + for (re=0; reframe_parms.ofdm_symbol_size; re++) + ru->beam_weights[0][0][aa][re] = 0x00007fff/eNB->frame_parms.nb_antennas_tx; } + if (transmission_mode<7) + ru->do_precoding=0; + else + ru->do_precoding=1; + + eNB->mac_enabled=1; + + +#ifdef ENABLE_MBMS_SIM + //eNB->pbch_configured=1; + eNB_MAC_INST ** mac; + mac = malloc16(1 * sizeof(eNB_MAC_INST *)); + for (int ii = 0;ii < 1; ii++) { + mac[ii] = malloc16(sizeof(eNB_MAC_INST)); + bzero(mac[ii], sizeof(eNB_MAC_INST)); + } + RC.mac = mac; + COMMON_channels_t *cc = &RC.mac[0]->common_channels[0]; + cc->MCH_pdu.mcs = 9; + cc->MCH_pdu.Pdu_size = get_TBS_DL(cc->MCH_pdu.mcs,N_RB_DL); + printf("MCH_pdu.Pdu_size %d\n",cc->MCH_pdu.Pdu_size); + cc->MCH_pdu.sync_area =0; + for(int ii=0; ii < cc->MCH_pdu.Pdu_size; ii++) + cc->MCH_pdu.payload[ii] = (char)(taus() & 0xff); + eNB->frame_parms.Nid_cell_mbsfn=0; +#endif + + + if(get_thread_worker_conf() == WORKER_ENABLE) { + extern void init_td_thread(PHY_VARS_eNB *); + extern void init_te_thread(PHY_VARS_eNB *); + init_td_thread(eNB); + init_te_thread(eNB); + } + + // callback functions required for phy_procedures_tx + // eNB_id_i = UE->n_connected_eNB; + printf("Setting mcs1 = %d\n",mcs1); + printf("Setting mcs2 = %d\n",mcs2); + printf("NPRB = %d\n",NB_RB); + printf("n_frames = %d\n",n_frames); + printf("Transmission mode %d with %dx%d antenna configuration, Extended Prefix %d\n",transmission_mode,n_tx_phy,n_rx,extended_prefix_flag); + snr1 = snr0+snr_int; printf("SNR0 %f, SNR1 %f\n",snr0,snr1); + uint8_t input_buffer[NUMBER_OF_UE_MAX][20000]; + + for (i=0; iframe_parms; + nsymb = (eNB->frame_parms.Ncp == 0) ? 14 : 12; + printf("Channel Model= (%s,%d)\n",channel_model_input, channel_model); + printf("SCM-A=%d, SCM-B=%d, SCM-C=%d, SCM-D=%d, EPA=%d, EVA=%d, ETU=%d, Rayleigh8=%d, Rayleigh1=%d, Rayleigh1_corr=%d, Rayleigh1_anticorr=%d, Rice1=%d, Rice8=%d\n", + SCM_A, SCM_B, SCM_C, SCM_D, EPA, EVA, ETU, Rayleigh8, Rayleigh1, Rayleigh1_corr, Rayleigh1_anticorr, Rice1, Rice8); - if (awgn_flag == 0) - sprintf(fname,"embms_%d_%d.m",mcs,N_RB_DL); + if(transmission_mode==5) + sprintf(bler_fname,"bler_tx%d_chan%d_nrx%d_mcs%d_mcsi%d_u%d_imod%d.csv",transmission_mode,channel_model,n_rx,mcs1,mcs_i,dual_stream_UE,i_mod); else - sprintf(fname,"embms_awgn_%d_%d.m",mcs,N_RB_DL); + sprintf(bler_fname,"bler_tx%d_chan%d_nrx%d_mcs%d.csv",transmission_mode,channel_model,n_rx,mcs1); - if (!(fd = fopen(fname,"w"))) { - printf("Cannot open %s, check permissions\n",fname); + bler_fd = fopen(bler_fname,"w"); + + if (bler_fd==NULL) { + fprintf(stderr,"Cannot create file %s!\n",bler_fname); exit(-1); } - if (awgn_flag==0) - fprintf(fd,"SNR_%d_%d=[];errs_mch_%d_%d=[];mch_trials_%d_%d=[];\n", - mcs,N_RB_DL, - mcs,N_RB_DL, - mcs,N_RB_DL); - else - fprintf(fd,"SNR_awgn_%d_%d=[];errs_mch_awgn_%d_%d=[];mch_trials_awgn_%d_%d=[];\n", - mcs,N_RB_DL, - mcs,N_RB_DL, - mcs,N_RB_DL); + fprintf(bler_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n"); - fflush(fd); - txdata = eNB->common_vars.txdata[0]; - nsymb = 12; - printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Symbols per subframe %d, AWGN %d\n",NUMBER_OF_OFDM_CARRIERS, - frame_parms->Ncp,frame_parms->samples_per_tti,nsymb,awgn_flag); - eNB2UE = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, - UE->frame_parms.nb_antennas_rx, - channel_model, - N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), - N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), - 0, - 0, - 0); - // Create transport channel structures for 2 transport blocks (MIMO) - eNB->dlsch_MCH = new_eNB_dlsch(1,8,Nsoft,N_RB_DL,0,&eNB->frame_parms); + if (test_perf != 0) { + char hostname[1024]; + hostname[1023] = '\0'; + gethostname(hostname, 1023); + printf("Hostname: %s\n", hostname); + //char dirname[FILENAME_MAX]; + //sprintf(dirname, "%s/SIMU/USER/pre-ci-logs-%s", getenv("OPENAIR_TARGETS"),hostname ); + sprintf(time_meas_fname,"time_meas_prb%d_mcs%d_anttx%d_antrx%d_pdcch%d_channel%s_tx%d.csv", + N_RB_DL,mcs1,n_tx_phy,n_rx,num_pdcch_symbols,channel_model_input,transmission_mode); + //mkdir(dirname,0777); + time_meas_fd = fopen(time_meas_fname,"w"); - if (!eNB->dlsch_MCH) { - printf("Can't get eNB dlsch structures\n"); - exit(-1); + if (time_meas_fd==NULL) { + fprintf(stderr,"Cannot create file %s!\n",time_meas_fname); + exit(-1); + } } - UE->dlsch_MCH[0] = new_ue_dlsch(1,8,Nsoft,MAX_TURBO_ITERATIONS_MBSFN,N_RB_DL,0); - eNB->frame_parms.num_MBSFN_config = 1; - eNB->frame_parms.MBSFN_config[0].radioframeAllocationPeriod = 0; - eNB->frame_parms.MBSFN_config[0].radioframeAllocationOffset = 0; - eNB->frame_parms.MBSFN_config[0].fourFrames_flag = 0; - eNB->frame_parms.MBSFN_config[0].mbsfn_SubframeConfig=0xff; // activate all possible subframes - UE->frame_parms.num_MBSFN_config = 1; - UE->frame_parms.MBSFN_config[0].radioframeAllocationPeriod = 0; - UE->frame_parms.MBSFN_config[0].radioframeAllocationOffset = 0; - UE->frame_parms.MBSFN_config[0].fourFrames_flag = 0; - UE->frame_parms.MBSFN_config[0].mbsfn_SubframeConfig=0xff; // activate all possible subframes - fill_eNB_dlsch_MCH(eNB,mcs,1,0); - fill_UE_dlsch_MCH(UE,mcs,1,0,0); + if(abstx) { + // CSV file + sprintf(csv_fname,"dataout_tx%d_u2%d_mcs%d_chan%d_nsimus%d_R%d.m",transmission_mode,dual_stream_UE,mcs1,channel_model,n_frames,num_rounds); + csv_fd = fopen(csv_fname,"w"); - if (is_pmch_subframe(0,subframe,&eNB->frame_parms)==0) { - printf("eNB is not configured for MBSFN in subframe %d\n",subframe); - exit(-1); - } else if (is_pmch_subframe(0,subframe,&UE->frame_parms)==0) { - printf("UE is not configured for MBSFN in subframe %d\n",subframe); - exit(-1); - } - - input_buffer_length = eNB->dlsch_MCH->harq_processes[0]->TBS/8; - input_buffer = (unsigned char *)malloc(input_buffer_length+4); - memset(input_buffer,0,input_buffer_length+4); - - for (i=0; iproc.proc_rxtx[0].frame_tx=0; - eNB->proc.proc_rxtx[0].frame_tx=0; - eNB->proc.proc_rxtx[0].subframe_tx=subframe; - errs[0]=0; - errs[1]=0; - errs[2]=0; - errs[3]=0; - /* - round_trials[0] = 0; - round_trials[1] = 0; - round_trials[2] = 0; - round_trials[3] = 0;*/ - printf("********************** SNR %f (step %f)\n",SNR,snr_step); - - for (trials = 0; trialsfirst_run = 1; - eNB2UE->first_run = 1; - memset(&eNB->common_vars.txdataF[0][0][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); - generate_mch(eNB,&eNB->proc.proc_rxtx[0],input_buffer); - PHY_ofdm_mod(eNB->common_vars.txdataF[0][0], // input, - txdata[0], // output - frame_parms->ofdm_symbol_size, - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); - - if (n_frames==1) { - LOG_M("txsigF0.m","txsF0", &eNB->common_vars.txdataF[0][0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size], - nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); - //if (eNB->frame_parms.nb_antennas_tx>1) - //LOG_M("txsigF1.m","txsF1", &eNB->lte_eNB_common_vars.txdataF[eNB_id][1][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); - } - - tx_lev = 0; - - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - tx_lev += signal_energy(&eNB->common_vars.txdata[eNB_id][aa] - [subframe*eNB->frame_parms.samples_per_tti], - eNB->frame_parms.samples_per_tti); - } - - tx_lev_dB = (unsigned int) dB_fixed(tx_lev); - - if (n_frames==1) { - printf("tx_lev = %d (%d dB)\n",tx_lev,tx_lev_dB); - // LOG_M("txsig0.m","txs0", &eNB->common_vars.txdata[0][0][subframe* eNB->frame_parms.samples_per_tti], - // eNB->frame_parms.samples_per_tti,1,1); - } - - for (i=0; i<2*frame_parms->samples_per_tti; i++) { - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - s_re[aa][i] = ((double)(((short *)eNB->common_vars.txdata[0][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) + (i<<1)]); - s_im[aa][i] = ((double)(((short *)eNB->common_vars.txdata[0][aa]))[(2*subframe*UE->frame_parms.samples_per_tti) +(i<<1)+1]); - } - } - - //Multipath channel - multipath_channel(eNB2UE,s_re,s_im,r_re,r_im, - 2*frame_parms->samples_per_tti,hold_channel); - //AWGN - sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)eNB->frame_parms.ofdm_symbol_size/(NB_RB*12)) - SNR; - sigma2 = pow(10,sigma2_dB/10); - - if (n_frames==1) - printf("Sigma2 %f (sigma2_dB %f)\n",sigma2,sigma2_dB); - - for (i=0; i<2*frame_parms->samples_per_tti; i++) { - for (aa=0; aaframe_parms.nb_antennas_rx; aa++) { - //printf("s_re[0][%d]=> %f , r_re[0][%d]=> %f\n",i,s_re[aa][i],i,r_re[aa][i]); - ((short *) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i] = - (short) (r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); - ((short *) UE->common_vars.rxdata[aa])[(2*subframe*UE->frame_parms.samples_per_tti)+2*i+1] = - (short) (r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0)); - } - } - - for (l=2; l<12; l++) { - slot_fep_mbsfn(UE, - l, - subframe%10, - 0, - 0); - - if (UE->perfect_ce==1) { - // fill in perfect channel estimates - freq_channel(eNB2UE,UE->frame_parms.N_RB_DL,12*UE->frame_parms.N_RB_DL + 1); - - for(k=0; knb_antennas_tx; aa++) { - for (aarx=0; aarxnb_antennas_rx; aarx++) { - for (i=0; iN_RB_DL*12; i++) { - ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[k][(aa<<1)+aarx])[2*i+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(eNB2UE->chF[aarx+ - (aa*frame_parms->nb_antennas_rx)][i].x*AMP); - ((int16_t *) UE->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[k][(aa<<1)+aarx])[2*i+1+(l*frame_parms->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)*2]=(int16_t)(eNB2UE->chF[aarx+ - (aa*frame_parms->nb_antennas_rx)][i].y*AMP); - } - } - } - } - } - - if (l==6) - for (l2=2; l2<7; l2++) - rx_pmch(UE, - 0, - subframe%10, - l2); - - if (l==6) - for (l2=2; l2<7; l2++) - rx_pmch(UE, - 0, - subframe%10, - l2); - - if (l==11) - for (l2=7; l2<12; l2++) - rx_pmch(UE, - 0, - subframe%10, - l2); - } - - UE->dlsch_MCH[0]->harq_processes[0]->G = get_G(&UE->frame_parms, - UE->dlsch_MCH[0]->harq_processes[0]->nb_rb, - UE->dlsch_MCH[0]->harq_processes[0]->rb_alloc_even, - get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs), - 1,2, - UE->proc.proc_rxtx[0].frame_tx,subframe,0); - UE->dlsch_MCH[0]->harq_processes[0]->Qm = get_Qm(UE->dlsch_MCH[0]->harq_processes[0]->mcs); - dlsch_unscrambling(&UE->frame_parms,1,UE->dlsch_MCH[0], - UE->dlsch_MCH[0]->harq_processes[0]->G, - UE->pdsch_vars_MCH[0]->llr[0],0,subframe<<1); - ret = dlsch_decoding(UE, - UE->pdsch_vars_MCH[0]->llr[0], - &UE->frame_parms, - UE->dlsch_MCH[0], - UE->dlsch_MCH[0]->harq_processes[0], - trials, - subframe, - 0,0,0); - - if (n_frames==1) - printf("MCH decoding returns %u\n",ret); - - if (ret == (1+UE->dlsch_MCH[0]->max_turbo_iterations)) - errs[0]++; - - UE->proc.proc_rxtx[0].frame_tx++; - eNB->proc.proc_rxtx[0].frame_tx++; + if (csv_fd==NULL) { + fprintf(stderr,"Cannot create file %s!\n",csv_fname); + exit(-1); } - printf("errors %u/%u (Pe %e)\n",errs[round],trials,(double)errs[round]/trials); + fprintf(csv_fd,"data_all%d=[",mcs1); + } - if (awgn_flag==0) - fprintf(fd,"SNR_%d_%d = [SNR_%d_%d %f]; errs_mch_%d_%d =[errs_mch_%d_%d %u]; mch_trials_%d_%d =[mch_trials_%d_%d %u];\n", - mcs,N_RB_DL,mcs,N_RB_DL,SNR, - mcs,N_RB_DL,mcs,N_RB_DL,errs[0], - mcs,N_RB_DL,mcs,N_RB_DL,trials); - else - fprintf(fd,"SNR_awgn_%d = [SNR_awgn_%d %f]; errs_mch_awgn_%d =[errs_mch_awgn_%d %u]; mch_trials_awgn_%d =[mch_trials_awgn_%d %u];\n", - N_RB_DL,N_RB_DL,SNR, - N_RB_DL,N_RB_DL,errs[0], - N_RB_DL,N_RB_DL,trials); + /* + //sprintf(tikz_fname, "second_bler_tx%d_u2=%d_mcs%d_chan%d_nsimus%d.tex",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames); + sprintf(tikz_fname, "second_bler_tx%d_u2%d_mcs%d_chan%d_nsimus%d",transmission_mode,dual_stream_UE,mcs,channel_model,n_frames); + tikz_fd = fopen(tikz_fname,"w"); + //fprintf(tikz_fd,"\\addplot[color=red, mark=o] plot coordinates {"); + switch (mcs) + { + case 0: + fprintf(tikz_fd,"\\addplot[color=blue, mark=star] plot coordinates {"); + break; + case 1: + fprintf(tikz_fd,"\\addplot[color=red, mark=star] plot coordinates {"); + break; + case 2: + fprintf(tikz_fd,"\\addplot[color=green, mark=star] plot coordinates {"); + break; + case 3: + fprintf(tikz_fd,"\\addplot[color=yellow, mark=star] plot coordinates {"); + break; + case 4: + fprintf(tikz_fd,"\\addplot[color=black, mark=star] plot coordinates {"); + break; + case 5: + fprintf(tikz_fd,"\\addplot[color=blue, mark=o] plot coordinates {"); + break; + case 6: + fprintf(tikz_fd,"\\addplot[color=red, mark=o] plot coordinates {"); + break; + case 7: + fprintf(tikz_fd,"\\addplot[color=green, mark=o] plot coordinates {"); + break; + case 8: + fprintf(tikz_fd,"\\addplot[color=yellow, mark=o] plot coordinates {"); + break; + case 9: + fprintf(tikz_fd,"\\addplot[color=black, mark=o] plot coordinates {"); + break; + case 10: + fprintf(tikz_fd,"\\addplot[color=blue, mark=square] plot coordinates {"); + break; + case 11: + fprintf(tikz_fd,"\\addplot[color=red, mark=square] plot coordinates {"); + break; + case 12: + fprintf(tikz_fd,"\\addplot[color=green, mark=square] plot coordinates {"); + break; + case 13: + fprintf(tikz_fd,"\\addplot[color=yellow, mark=square] plot coordinates {"); + break; + case 14: + fprintf(tikz_fd,"\\addplot[color=black, mark=square] plot coordinates {"); + break; + case 15: + fprintf(tikz_fd,"\\addplot[color=blue, mark=diamond] plot coordinates {"); + break; + case 16: + fprintf(tikz_fd,"\\addplot[color=red, mark=diamond] plot coordinates {"); + break; + case 17: + fprintf(tikz_fd,"\\addplot[color=green, mark=diamond] plot coordinates {"); + break; + case 18: + fprintf(tikz_fd,"\\addplot[color=yellow, mark=diamond] plot coordinates {"); + break; + case 19: + fprintf(tikz_fd,"\\addplot[color=black, mark=diamond] plot coordinates {"); + break; + case 20: + fprintf(tikz_fd,"\\addplot[color=blue, mark=x] plot coordinates {"); + break; + case 21: + fprintf(tikz_fd,"\\addplot[color=red, mark=x] plot coordinates {"); + break; + case 22: + fprintf(tikz_fd,"\\addplot[color=green, mark=x] plot coordinates {"); + break; + case 23: + fprintf(tikz_fd,"\\addplot[color=yellow, mark=x] plot coordinates {"); + break; + case 24: + fprintf(tikz_fd,"\\addplot[color=black, mark=x] plot coordinates {"); + break; + case 25: + fprintf(tikz_fd,"\\addplot[color=blue, mark=x] plot coordinates {"); + break; + case 26: + fprintf(tikz_fd,"\\addplot[color=red, mark=+] plot coordinates {"); + break; + case 27: + fprintf(tikz_fd,"\\addplot[color=green, mark=+] plot coordinates {"); + break; + case 28: + fprintf(tikz_fd,"\\addplot[color=yellow, mark=+] plot coordinates {"); + break; + } + */ + UE->pdcch_vars[UE->current_thread_id[subframe]][0]->crnti = n_rnti; + UE->n_connected_eNB = 1; + printf("Allocating %dx%d eNB->UE channel descriptor\n",eNB->frame_parms.nb_antennas_tx,UE->frame_parms.nb_antennas_rx); + eNB2UE[0] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, + channel_model, + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + forgetting_factor, + rx_sample_offset, + 0); + reset_meas(&eNB2UE[0]->random_channel); + reset_meas(&eNB2UE[0]->interp_time); - fflush(fd); + if(num_rounds>1) { + for(n=1; n<4; n++) { + eNB2UE[n] = new_channel_desc_scm(eNB->frame_parms.nb_antennas_tx, + UE->frame_parms.nb_antennas_rx, + channel_model, + N_RB2sampling_rate(eNB->frame_parms.N_RB_DL), + N_RB2channel_bandwidth(eNB->frame_parms.N_RB_DL), + forgetting_factor, + rx_sample_offset, + 0); + reset_meas(&eNB2UE[n]->random_channel); + reset_meas(&eNB2UE[n]->interp_time); + } + } - if (errs[0] == 0) + if (eNB2UE[0]==NULL) { + printf("Problem generating channel model. Exiting.\n"); + exit(-1); + } + + if ((transmission_mode == 3) || (transmission_mode==4)) + Kmimo=2; + else + Kmimo=1; + + switch (ue_category) { + case 1: + Nsoft = 250368; + break; + + case 2: + case 3: + Nsoft = 1237248; + break; + + case 4: + Nsoft = 1827072; + break; + + default: + printf("Unsupported UE category %d\n",ue_category); + exit(-1); break; } - if (n_frames==1) { - printf("Dumping PMCH files ( G %d)\n",UE->dlsch_MCH[0]->harq_processes[0]->G); - dump_mch(UE,0, - UE->dlsch_MCH[0]->harq_processes[0]->G, - subframe); + for (k=0; kdlsch[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms); + + if (!eNB->dlsch[k][i]) { + printf("Can't get eNB dlsch structures\n"); + exit(-1); + } + + eNB->dlsch[k][i]->rnti = n_rnti+k; + } } - printf("Freeing dlsch structures\n"); - free_eNB_dlsch(eNB->dlsch_MCH); - free_ue_dlsch(UE->dlsch_MCH[0]); - fclose(fd); - return(0); -} +#ifdef ENABLE_MBMS_SIM + eNB->dlsch_MCH = new_eNB_dlsch(1,8,Nsoft,N_RB_DL, 0, &eNB->frame_parms); +#endif + + /* allocate memory for both subframes (only one is really used + * but there is now "copy_harq_proc_struct" which needs both + * to be valid) + * TODO: refine this somehow (necessary?) + */ + for (sf = 0; sf < 2; sf++) { + for (i=0; i<2; i++) { + UE->dlsch[sf][0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + + if (!UE->dlsch[sf][0][i]) { + printf("Can't get ue dlsch structures\n"); + exit(-1); + } + + UE->dlsch[sf][0][i]->rnti = n_rnti; + } + } + +#ifdef ENABLE_MBMS_SIM + UE->dlsch_MCH[0] = new_ue_dlsch(1,8,Nsoft,MAX_TURBO_ITERATIONS_MBSFN,N_RB_DL,0); + UE->dlsch_MCH[0]->active = 1; + UE->dlsch_MCH[0]->harq_processes[0]->mcs = mcs1; +#endif + + UE->dlsch_SI[0] = new_ue_dlsch(1,1,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->dlsch_ra[0] = new_ue_dlsch(1,1,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); + UE->ulsch[0] = new_ue_ulsch(N_RB_DL,0); + // structure for SIC at UE + UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0,&eNB->frame_parms); + + if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { + eNB->UE_stats[0].DL_pmi_single = (unsigned short)(taus()&0xffff); + + if (n_users>1) + eNB->UE_stats[1].DL_pmi_single = (eNB->UE_stats[0].DL_pmi_single ^ 0x1555); //opposite PMI + } else { + eNB->UE_stats[0].DL_pmi_single = 0; + + if (n_users>1) + eNB->UE_stats[1].DL_pmi_single = 0; + } + + L1_rxtx_proc_t *proc_eNB = &eNB->proc.L1_proc; + + if (input_fd==NULL) { + DL_req.dl_config_request_body.number_pdcch_ofdm_symbols = num_pdcch_symbols; + DL_req.sfn_sf = (proc_eNB->frame_tx<<4)+subframe; + TX_req.sfn_sf = (proc_eNB->frame_tx<<4)+subframe; + // UE specific DCI + fill_DCI(eNB, + proc_eNB->frame_tx,subframe, + &sched_resp, + input_buffer, + n_rnti, + n_users, + transmission_mode, + 0, + common_flag, + NB_RB, + DLSCH_RB_ALLOC, + TPC, + mcs1, + mcs2, + 1, + 0, + pa, + &num_common_dci, + &num_ue_spec_dci, + &num_dci); + numCCE = get_nCCE(num_pdcch_symbols,&eNB->frame_parms,get_mi(&eNB->frame_parms,subframe)); + + if (n_frames==1) printf("num_pdcch_symbols %d, numCCE %d, num_dci %d/%d/%d\n",num_pdcch_symbols,numCCE, num_dci,num_ue_spec_dci,num_common_dci); + } + + eNB->frame_parms.Nid_cell_mbsfn=0; + if(enable_fembms){ + lte_gold_mbsfn_khz_1dot25 (&eNB->frame_parms, eNB->lte_gold_mbsfn_khz_1dot25_table, eNB->frame_parms.Nid_cell_mbsfn); + eNB->frame_parms.NonMBSFN_config_flag=1; + }else{ + lte_gold_mbsfn (&eNB->frame_parms, eNB->lte_gold_mbsfn_table, eNB->frame_parms.Nid_cell_mbsfn); + eNB->frame_parms.num_MBSFN_config=1; + eNB->frame_parms.MBSFN_config[0].radioframeAllocationPeriod=0; + eNB->frame_parms.MBSFN_config[0].fourFrames_flag=0; + eNB->frame_parms.MBSFN_config[0].radioframeAllocationOffset=0; + //eNB->frame_parms.MBSFN_config[0].mbsfn_SubframeConfig=0xC0; + eNB->frame_parms.MBSFN_config[0].mbsfn_SubframeConfig=0xFC; + } + + + + snr_step = input_snr_step; + UE->high_speed_flag = 1; + UE->ch_est_alpha=0; + + for (ch_realization=0; ch_realizationproc.proc_rxtx[UE->current_thread_id[subframe]].frame_rx=0; + errs[0]=0; + errs[1]=0; + errs[2]=0; + errs[3]=0; + errs2[0]=0; + errs2[1]=0; + errs2[2]=0; + errs2[3]=0; + round_trials[0] = 0; + round_trials[1] = 0; + round_trials[2] = 0; + round_trials[3] = 0; + dci_errors[0]=0; + dci_errors[1]=0; + dci_errors[2]=0; + dci_errors[3]=0; + // avg_ber = 0; + round=0; + avg_iter = 0; + iter_trials=0; + reset_meas(&eNB->phy_proc_tx); // total eNB tx + reset_meas(&eNB->dlsch_scrambling_stats); + reset_meas(&UE->dlsch_unscrambling_stats); + reset_meas(&eNB->ofdm_mod_stats); + reset_meas(&eNB->dlsch_modulation_stats); + reset_meas(&eNB->dlsch_encoding_stats); + reset_meas(&eNB->dlsch_interleaving_stats); + reset_meas(&eNB->dlsch_rate_matching_stats); + reset_meas(&eNB->dlsch_turbo_encoding_stats); + reset_meas(&eNB->dlsch_common_and_dci); + reset_meas(&eNB->dlsch_ue_specific); + + for (int i=0; iphy_proc_rx[i]); // total UE rx + reset_meas(&UE->ue_front_end_stat[i]); + reset_meas(&UE->pdsch_procedures_stat[i]); + reset_meas(&UE->dlsch_procedures_stat[i]); + reset_meas(&UE->dlsch_decoding_stats[i]); + reset_meas(&UE->dlsch_llr_stats_parallelization[i][0]); + reset_meas(&UE->dlsch_llr_stats_parallelization[i][1]); + } + + reset_meas(&UE->ofdm_demod_stats); + reset_meas(&UE->crnti_procedures_stats); + reset_meas(&UE->dlsch_channel_estimation_stats); + reset_meas(&UE->dlsch_freq_offset_estimation_stats); + reset_meas(&UE->rx_dft_stats); + reset_meas(&UE->dlsch_decoding_stats[0]); + reset_meas(&UE->dlsch_decoding_stats[1]); + reset_meas(&UE->dlsch_turbo_decoding_stats); + reset_meas(&UE->dlsch_deinterleaving_stats); + reset_meas(&UE->dlsch_rate_unmatching_stats); + reset_meas(&UE->dlsch_tc_init_stats); + reset_meas(&UE->dlsch_tc_alpha_stats); + reset_meas(&UE->dlsch_tc_beta_stats); + reset_meas(&UE->dlsch_tc_gamma_stats); + reset_meas(&UE->dlsch_tc_ext_stats); + reset_meas(&UE->dlsch_tc_intl1_stats); + reset_meas(&UE->dlsch_tc_intl2_stats); + // initialization + // initialization + varArray_t *table_tx=initVarArray(1000,sizeof(double)); + varArray_t *table_tx_ifft=initVarArray(1000,sizeof(double)); + varArray_t *table_tx_mod=initVarArray(1000,sizeof(double)); + varArray_t *table_tx_enc=initVarArray(1000,sizeof(double)); + varArray_t *table_rx=initVarArray(1000,sizeof(double)); + time_stats_t phy_proc_rx_tot; + time_stats_t pdsch_procedures_tot; + time_stats_t dlsch_procedures_tot; + time_stats_t dlsch_decoding_tot; + time_stats_t dlsch_llr_tot; + time_stats_t ue_front_end_tot; + varArray_t *table_rx_fft=initVarArray(1000,sizeof(double)); + varArray_t *table_rx_demod=initVarArray(1000,sizeof(double)); + varArray_t *table_rx_dec=initVarArray(1000,sizeof(double)); + + for (trials = 0; trialsfirst_run = 1; + UE->dlsch[UE->current_thread_id[subframe]][eNB_id][0]->harq_ack[subframe].ack = 0; + UE->dlsch[UE->current_thread_id[subframe]][eNB_id][1]->harq_ack[subframe].ack = 0; + + while ((round < num_rounds) && (UE->dlsch[UE->current_thread_id[subframe]][eNB_id][0]->harq_ack[subframe].ack == 0)) { + // printf("Trial %d, round %d\n",trials,round); + round_trials[round]++; + + //if(transmission_mode>=5) + // pmi_feedback=1; + //else + // pmi_feedback=0; + + if (abstx) { + if (trials==0 && round==0 && SNR==snr0) //generate a new channel + hold_channel = 0; + else + hold_channel = 1; + } else + hold_channel = 0;//(round==0) ? 0 : 1; + + //PMI_FEEDBACK: + + // printf("Trial %d : Round %d, pmi_feedback %d \n",trials,round,pmi_feedback); + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + memset(&eNB->common_vars.txdataF[aa][0],0,FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t)); + } + + if (input_fd==NULL) { + // Simulate HARQ procedures!!! + memset(CCE_table,0,800*sizeof(int)); + + if (/*common_flag == 0*/ 1) { + num_dci=0; + num_common_dci=0; + num_ue_spec_dci=0; + + if (round == 0) { // First round + TB0_active = 1; + eNB->dlsch[0][0]->harq_processes[0]->rvidx = round&3; + DL_req.sfn_sf = (proc_eNB->frame_tx<<4)+subframe; + TX_req.sfn_sf = (proc_eNB->frame_tx<<4)+subframe; + fill_DCI(eNB,proc_eNB->frame_tx,subframe,&sched_resp,input_buffer,n_rnti,n_users,transmission_mode,0,common_flag,NB_RB,DLSCH_RB_ALLOC,TPC, + mcs1,mcs2,!(trials&1),round&3,pa,&num_common_dci,&num_ue_spec_dci,&num_dci); + } else { + DL_req.sfn_sf = (proc_eNB->frame_tx<<4)+subframe; + TX_req.sfn_sf = (proc_eNB->frame_tx<<4)+subframe; + fill_DCI(eNB,proc_eNB->frame_tx,subframe,&sched_resp,input_buffer,n_rnti,n_users,transmission_mode,1,common_flag,NB_RB,DLSCH_RB_ALLOC,TPC, + (TB0_active==1)?mcs1:0,mcs2,!(trials&1),(TB0_active==1)?round&3:0,pa,&num_common_dci,&num_ue_spec_dci,&num_dci); + } + } + +//#ifdef ENABLE_MBMS_SIM +// eNB->frame_parms.Nid_cell_mbsfn=0; +// lte_gold_mbsfn (&eNB->frame_parms, eNB->lte_gold_mbsfn_table, eNB->frame_parms.Nid_cell_mbsfn); +//#endif + + UE->measurements.n0_power_tot_dB = 10*log10((double)tx_lev) +10*log10((double)ru->frame_parms.ofdm_symbol_size/(double)(ru->frame_parms.N_RB_DL*12)) - SNR; + UE->measurements.n0_power_tot = pow(10,( 10*log10((double)tx_lev) +10*log10((double)ru->frame_parms.ofdm_symbol_size/(double)(ru->frame_parms.N_RB_DL*12)) - SNR)/10); + + proc_eNB->subframe_tx = subframe; + sched_resp.subframe=subframe; + sched_resp.frame=proc_eNB->frame_tx; + eNB->abstraction_flag=0; + schedule_response(&sched_resp); + phy_procedures_eNB_TX(eNB,proc_eNB,1); + + if (uncoded_ber_bit == NULL) { + // this is for user 0 only + printf("nb_rb %d, rb_alloc %x, mcs %d\n", + eNB->dlsch[0][0]->harq_processes[0]->nb_rb, + eNB->dlsch[0][0]->harq_processes[0]->rb_alloc[0], + eNB->dlsch[0][0]->harq_processes[0]->mcs); + coded_bits_per_codeword = get_G(&eNB->frame_parms, + eNB->dlsch[0][0]->harq_processes[0]->nb_rb, + eNB->dlsch[0][0]->harq_processes[0]->rb_alloc, + get_Qm(eNB->dlsch[0][0]->harq_processes[0]->mcs), + eNB->dlsch[0][0]->harq_processes[0]->Nl, + num_pdcch_symbols, + 0, + subframe, + transmission_mode>=7?transmission_mode:0); + uncoded_ber_bit = (short *) malloc(sizeof(short)*coded_bits_per_codeword); + printf("uncoded_ber_bit=%p\n",uncoded_ber_bit); + } + + + + start_meas(&eNB->ofdm_mod_stats); + ru->proc.subframe_tx=subframe; + LOG_W(PHY,"eNB %d\n",eNB->frame_parms.num_MBSFN_config); + LOG_W(PHY,"eNB %d\n",eNB->frame_parms.NonMBSFN_config_flag); + memcpy((void *)&ru->frame_parms,(void *)&eNB->frame_parms,sizeof(LTE_DL_FRAME_PARMS)); + LOG_W(PHY,"RU %d\n",ru->frame_parms.num_MBSFN_config); + LOG_W(PHY,"RU %d\n",ru->frame_parms.NonMBSFN_config_flag); + feptx_prec(ru); + feptx_ofdm(ru); + stop_meas(&eNB->ofdm_mod_stats); + // generate next subframe for channel estimation + DL_req.dl_config_request_body.number_dci=0; + DL_req.dl_config_request_body.number_pdu=0; + TX_req.tx_request_body.number_of_pdus=0; + proc_eNB->subframe_tx = subframe+1; + sched_resp.subframe=subframe+1; + schedule_response(&sched_resp); + + phy_procedures_eNB_TX(eNB,proc_eNB,0); + ru->proc.subframe_tx=(subframe+1)%10; + feptx_prec(ru); + feptx_ofdm(ru); + proc_eNB->frame_tx++; + tx_lev = 0; + + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + tx_lev += signal_energy(&ru->common.txdata[aa] + [subframe*eNB->frame_parms.samples_per_tti], + eNB->frame_parms.samples_per_tti); + } + + tx_lev_dB = (unsigned int) dB_fixed(tx_lev); + + if (n_frames==1) { + printf("tx_lev = %u (%u dB)\n",tx_lev,tx_lev_dB); + LOG_M("txsig0.m","txs0", &ru->common.txdata[0][subframe* eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti,1,1); + + if (transmission_mode<7) { + LOG_M("txsigF0.m","txsF0x", &ru->common.txdataF_BF[0][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); + } else if (transmission_mode == 7) { + LOG_M("txsigF0.m","txsF0", &ru->common.txdataF_BF[5][subframe*nsymb*eNB->frame_parms.ofdm_symbol_size],nsymb*eNB->frame_parms.ofdm_symbol_size,1,1); + LOG_M("txsigF0_BF.m","txsF0_BF", &ru->common.txdataF_BF[0][0],eNB->frame_parms.ofdm_symbol_size,1,1); + } + } + } + + DL_channel(ru,UE,subframe,awgn_flag,SNR,tx_lev,hold_channel,abstx,num_rounds,trials,round,eNB2UE,s_re,s_im,r_re,r_im,csv_fd); + UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[UE->current_thread_id[subframe]]; + proc->subframe_rx = subframe; + UE->UE_mode[0] = PUSCH; + // first symbol has to be done separately in one-shot mode + slot_fep(UE, + 0, + (proc->subframe_rx<<1), + UE->rx_offset, + 0, + 0); + + if (n_frames==1) printf("Running phy_procedures_UE_RX\n"); + + if (dci_flag==0) { + memcpy(dci_alloc,eNB->pdcch_vars[subframe&1].dci_alloc,num_dci*sizeof(DCI_ALLOC_t)); + UE->pdcch_vars[UE->current_thread_id[proc->subframe_rx]][eNB_id]->num_pdcch_symbols = num_pdcch_symbols; + + if (n_frames==1) + printf("bypassing PDCCH/DCI detection\n"); + + if (generate_ue_dlsch_params_from_dci(proc->frame_rx, + proc->subframe_rx, + (void *)&dci_alloc[0].dci_pdu, + common_flag == 0 ? n_rnti : SI_RNTI, + dci_alloc[0].format, + UE->pdcch_vars[UE->current_thread_id[proc->subframe_rx]][eNB_id], + UE->pdsch_vars[UE->current_thread_id[proc->subframe_rx]][eNB_id], + UE->dlsch[UE->current_thread_id[proc->subframe_rx]][0], + &UE->frame_parms, + UE->pdsch_config_dedicated, + SI_RNTI, + 0, + P_RNTI, + UE->transmission_mode[eNB_id]<7?0:UE->transmission_mode[eNB_id], + 0)==0) { + dump_dci(&UE->frame_parms, &dci_alloc[0]); + //UE->dlsch[UE->current_thread_id[proc->subframe_rx]][eNB_id][0]->active = 1; + //UE->dlsch[UE->current_thread_id[proc->subframe_rx]][eNB_id][1]->active = 1; + UE->pdcch_vars[UE->current_thread_id[proc->subframe_rx]][eNB_id]->num_pdcch_symbols = num_pdcch_symbols; + UE->dlsch_received[eNB_id]++; + } else { + LOG_E(PHY,"Problem in DCI!\n"); + } + } + + + UE->frame_parms.Nid_cell_mbsfn=0; + if(enable_fembms){ + lte_gold_mbsfn_khz_1dot25 (&UE->frame_parms, UE->lte_gold_mbsfn_khz_1dot25_table, UE->frame_parms.Nid_cell_mbsfn); + UE->frame_parms.NonMBSFN_config_flag=1; + }else{ + lte_gold_mbsfn (&UE->frame_parms, UE->lte_gold_mbsfn_table, UE->frame_parms.Nid_cell_mbsfn); + UE->frame_parms.num_MBSFN_config=1; + UE->frame_parms.MBSFN_config[0].radioframeAllocationPeriod=0; + UE->frame_parms.MBSFN_config[0].fourFrames_flag=0; + UE->frame_parms.MBSFN_config[0].radioframeAllocationOffset=0; + UE->frame_parms.MBSFN_config[0].mbsfn_SubframeConfig=0xC0; + } + + + + + dci_received = UE->pdcch_vars[UE->current_thread_id[proc->subframe_rx]][eNB_id]->dci_received; + phy_procedures_UE_RX(UE,proc,0,0,dci_flag,normal_txrx); + dci_received = dci_received - UE->pdcch_vars[UE->current_thread_id[proc->subframe_rx]][eNB_id]->dci_received; + + if (dci_flag && (dci_received == 0)) { + printf("DCI not received\n"); + dci_errors[round]++; + LOG_M("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); + LOG_M("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); + LOG_M("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[0][eNB_id]->rxdataF_comp[0],4*300,1,1); + LOG_M("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[0][eNB_id]->llr,2400,1,4); + LOG_M("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); + LOG_M("rxsigF0.m","rxsF0", &UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + exit(-1); + } + + int bit_errors=0; + + if ((test_perf ==0 ) && (n_frames==1)) { + dlsch_unscrambling(&eNB->frame_parms, + 0, + UE->dlsch[UE->current_thread_id[subframe]][0][0], + coded_bits_per_codeword, + UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0], + 0, + subframe<<1); + + for (i=0; idlsch[0][0]->harq_processes[0]->e[i]==1 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] > 0)|| + (eNB->dlsch[0][0]->harq_processes[0]->e[i]==0 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] < 0)) { + uncoded_ber_bit[bit_errors++] = 1; + printf("error in pos %d : %d => %d\n",i, + eNB->dlsch[0][0]->harq_processes[0]->e[i], + UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i]); + } else { + /* + printf("no error in pos %d : %d => %d\n",i, + eNB->dlsch[0][0]->harq_processes[0]->e[i], + UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i]); + */ + } + + LOG_M("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); + LOG_M("ch0.m","ch0",eNB2UE[0]->ch[0],eNB2UE[0]->channel_length,1,8); + + if (eNB->frame_parms.nb_antennas_tx>1) + LOG_M("ch1.m","ch1",eNB2UE[0]->ch[eNB->frame_parms.nb_antennas_rx],eNB2UE[0]->channel_length,1,8); + + //common vars + LOG_M("rxsig0.m","rxs0", &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); + LOG_M("rxsigF0.m","rxsF0", &UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + + if (UE->frame_parms.nb_antennas_rx>1) { + LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1); + LOG_M("rxsigF1.m","rxsF1", UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].rxdataF[1],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + } + + LOG_M("dlsch00_r0.m","dl00_r0", + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][0][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + + if (UE->frame_parms.nb_antennas_rx>1) + LOG_M("dlsch01_r0.m","dl01_r0", + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][1][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + + if (eNB->frame_parms.nb_antennas_tx>1) + LOG_M("dlsch10_r0.m","dl10_r0", + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][2][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + + if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) + LOG_M("dlsch11_r0.m","dl11_r0", + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][3][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); + + //pdsch_vars + printf("coded_bits_per_codeword %u\n",coded_bits_per_codeword); + dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round, UE->dlsch[UE->current_thread_id[subframe]][0][0]->current_harq_pid); + LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + //pdcch_vars + LOG_M("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); + LOG_M("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); + LOG_M("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[0][eNB_id]->rxdataF_comp[0],4*300,1,1); + LOG_M("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[0][eNB_id]->llr,2400,1,4); + } + + if (UE->dlsch[UE->current_thread_id[subframe]][eNB_id][0]->harq_ack[subframe].ack == 1) { + avg_iter += UE->dlsch[UE->current_thread_id[subframe]][eNB_id][0]->last_iteration_cnt; + iter_trials++; + + if (n_frames==1) + printf("No DLSCH errors found (round %d),uncoded ber %f\n",round,(double)bit_errors/coded_bits_per_codeword); + + UE->total_TBS[eNB_id] = UE->total_TBS[eNB_id] + UE->dlsch[UE->current_thread_id[subframe]][eNB_id][0]->harq_processes[UE->dlsch[UE->current_thread_id[subframe]][eNB_id][0]->current_harq_pid]->TBS; + TB0_active = 0; + } // DLSCH received ok + else { + errs[round]++; + avg_iter += UE->dlsch[UE->current_thread_id[subframe]][eNB_id][0]->last_iteration_cnt-1; + iter_trials++; + + if (n_frames==1) { + //if ((n_frames==1) || (SNR>=30)) { + printf("DLSCH errors found (round %d), uncoded ber %f\n",round,(double)bit_errors/coded_bits_per_codeword); + + for (s=0; sdlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->C; s++) { + if (sdlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Cminus) + Kr = UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kminus; + else + Kr = UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kplus; + + Kr_bytes = Kr>>3; + printf("Decoded_output (Segment %d):\n",s); + + for (i=0; idlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->c[s][i], + UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->c[s][i]^eNB->dlsch[0][0]->harq_processes[0]->c[s][i]); + } + + sprintf(fname,"rxsig0_r%d.m",round); + sprintf(vname,"rxs0_r%d",round); + LOG_M(fname,vname, &UE->common_vars.rxdata[0][0],10*UE->frame_parms.samples_per_tti,1,1); + sprintf(fname,"rxsigF0_r%d.m",round); + sprintf(vname,"rxs0F_r%d",round); + LOG_M(fname,vname, &UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].rxdataF[0][0],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + + if (UE->frame_parms.nb_antennas_rx>1) { + sprintf(fname,"rxsig1_r%d.m",round); + sprintf(vname,"rxs1_r%d.m",round); + LOG_M(fname,vname, UE->common_vars.rxdata[1],UE->frame_parms.samples_per_tti,1,1); + sprintf(fname,"rxsigF1_r%d.m",round); + sprintf(vname,"rxs1F_r%d.m",round); + LOG_M(fname,vname, UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].rxdataF[1],UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + } + + sprintf(fname,"dlsch00_r%d.m",round); + sprintf(vname,"dl00_r%d",round); + LOG_M(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][0][0]), + UE->frame_parms.ofdm_symbol_size*nsymb,1,1); + + if (UE->frame_parms.nb_antennas_rx>1) { + sprintf(fname,"dlsch01_r%d.m",round); + sprintf(vname,"dl01_r%d",round); + LOG_M(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][1][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); + } + + if (eNB->frame_parms.nb_antennas_tx>1) { + sprintf(fname,"dlsch10_r%d.m",round); + sprintf(vname,"dl10_r%d",round); + LOG_M(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][2][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); + } + + if ((UE->frame_parms.nb_antennas_rx>1) && (eNB->frame_parms.nb_antennas_tx>1)) { + sprintf(fname,"dlsch11_r%d.m",round); + sprintf(vname,"dl11_r%d",round); + LOG_M(fname,vname, + &(UE->common_vars.common_vars_rx_data_per_thread[UE->current_thread_id[subframe]].dl_ch_estimates[eNB_id][3][0]), + UE->frame_parms.ofdm_symbol_size*nsymb/2,1,1); + } + + //pdsch_vars + dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round, UE->dlsch[UE->current_thread_id[subframe]][0][0]->current_harq_pid); + //LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + //LOG_M("dlsch_ber_bit.m","ber_bit",uncoded_ber_bit,coded_bits_per_codeword,1,0); + //LOG_M("dlsch_w.m","w",eNB->dlsch[0][0]->harq_processes[0]->w[0],3*(tbs+64),1,4); + //LOG_M("dlsch_w.m","w",UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->w[0],3*(tbs+64),1,0); + //pdcch_vars + LOG_M("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); + LOG_M("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); + LOG_M("pdcch_rxF_comp0.m","pdcch0_rxF_comp0",UE->pdcch_vars[0][eNB_id]->rxdataF_comp[0],4*300,1,1); + LOG_M("pdcch_rxF_llr.m","pdcch_llr",UE->pdcch_vars[0][eNB_id]->llr,2400,1,4); + + if (round == 3) exit(-1); + } + + // printf("round %d errors %d/%d\n",round,errs[round],trials); + round++; + // UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->round++; + } + + if (xforms==1) { + phy_scope_UE(form_ue, + UE, + eNB_id, + 0,// UE_id + subframe); + } + + UE->proc.proc_rxtx[UE->current_thread_id[subframe]].frame_rx++; + } //round + + // printf("\n"); + + if ((errs[0]>=n_frames/10) && (trials>(n_frames/2))) + break; + + //len = chbch_stats_read(stats_buffer,NULL,0,4096); + //printf("%s\n\n",stats_buffer); + + if (UE->proc.proc_rxtx[UE->current_thread_id[subframe]].frame_rx % 10 == 0) { + UE->bitrate[eNB_id] = (UE->total_TBS[eNB_id] - UE->total_TBS_last[eNB_id])*10; + LOG_D(PHY,"[UE %d] Calculating bitrate: total_TBS = %d, total_TBS_last = %d, bitrate = %d kbits/s\n",UE->Mod_id,UE->total_TBS[eNB_id],UE->total_TBS_last[eNB_id], + UE->bitrate[eNB_id]/1000); + UE->total_TBS_last[eNB_id] = UE->total_TBS[eNB_id]; + } + + /* calculate the total processing time for each packet, + * get the max, min, and number of packets that exceed t>2000us + */ + double t_tx = inMicroS(eNB->phy_proc_tx.p_time); + double t_tx_ifft = inMicroS(eNB->ofdm_mod_stats.p_time); + double t_rx = inMicroS(UE->phy_proc_rx[UE->current_thread_id[subframe]].p_time); + sumUpStats(&phy_proc_rx_tot, UE->phy_proc_rx, UE->current_thread_id[subframe]); + sumUpStats(&ue_front_end_tot, UE->ue_front_end_stat, UE->current_thread_id[subframe]); + sumUpStats(&pdsch_procedures_tot, UE->pdsch_procedures_stat, UE->current_thread_id[subframe]); + sumUpStats(&dlsch_procedures_tot, UE->dlsch_procedures_stat, UE->current_thread_id[subframe]); + sumUpStats(&dlsch_decoding_tot, UE->dlsch_decoding_stats, UE->current_thread_id[subframe]); + sumUpStatsSlot(&dlsch_llr_tot, UE->dlsch_llr_stats_parallelization, UE->current_thread_id[subframe]); + double t_rx_fft = inMicroS(UE->ofdm_demod_stats.p_time); + double t_rx_demod = inMicroS(UE->dlsch_rx_pdcch_stats.p_time); + double t_rx_dec = inMicroS(UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].p_time); + + if (t_tx > 2000 )// 2ms is too much time for a subframe + n_tx_dropped++; + + if (t_rx > 2000 ) + n_rx_dropped++; + + appendVarArray(table_tx, &t_tx); + appendVarArray(table_tx_ifft, &t_tx_ifft); + appendVarArray(table_rx, &t_rx ); + appendVarArray(table_rx_fft, &t_rx_fft ); + appendVarArray(table_rx_demod, &t_rx_demod ); + appendVarArray(table_rx_dec, &t_rx_dec ); + } //trials + + // round_trials[0]: number of code word : goodput the protocol + // sort table + qsort (dataArray(table_tx), table_tx->size, table_tx->atomSize, &cmpdouble); + qsort (dataArray(table_tx_ifft), table_tx_ifft->size, table_tx_ifft->atomSize, &cmpdouble); + qsort (dataArray(table_tx_mod), table_tx_mod->size, table_tx_mod->atomSize, &cmpdouble); + qsort (dataArray(table_tx_enc), table_tx_enc->size, table_tx_enc->atomSize, &cmpdouble); + qsort (dataArray(table_rx), table_rx->size, table_rx->atomSize, &cmpdouble); + qsort (dataArray(table_rx_fft), table_rx_fft->size, table_rx_fft->atomSize, &cmpdouble); + qsort (dataArray(table_rx_demod), table_rx_demod->size, table_rx_demod->atomSize, &cmpdouble); + qsort (dataArray(table_rx_dec), table_rx_dec->size, table_rx_dec->atomSize, &cmpdouble); + + if (dump_table == 1 ) { + set_component_filelog(SIM); // file located in /tmp/usim.txt + LOG_UDUMPMSG(SIM,table_tx,table_tx->size,LOG_DUMP_DOUBLE,"The transmitter raw data: \n"); + LOG_UDUMPMSG(SIM,table_rx,table_rx->size,LOG_DUMP_DOUBLE,"Thereceiver raw data: \n"); + } + + effective_rate = 1.0-((double)(errs[0]+errs[1]+errs[2]+errs[3])/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3])); + printf("\n**********************SNR = %f dB (tx_lev %f)**************************\n", + SNR, + (double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12))); + printf("Errors (%u(%u)/%u %u/%u %u/%u %u/%u), Pe = (%e,%e,%e,%e), dci_errors %u/%u, Pe = %e => effective rate %f, normalized delay %f (%f)\n", + errs[0], + errs2[0], + round_trials[0], + errs[1], + round_trials[1], + errs[2], + round_trials[2], + errs[3], + round_trials[3], + (double)errs[0]/(round_trials[0]), + (double)errs[1]/(round_trials[1]), + (double)errs[2]/(round_trials[2]), + (double)errs[3]/(round_trials[3]), + dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3], + round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3], + (double)(dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3])/(round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3]), + //rate*effective_rate, + 100*effective_rate, + //rate, + //rate*get_Qm(UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[UE->dlsch[UE->current_thread_id[subframe]][0][0]->current_harq_pid]->mcs), + (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ + (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, + (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); + double timeBase=1/(1000*cpu_freq_GHz); + + if (print_perf==1) { + printf("\neNB TX function statistics (per 1ms subframe)\n"); + printDistribution(&eNB->phy_proc_tx,table_tx,"PHY proc tx"); + printStatIndent(&eNB->dlsch_common_and_dci,"DL common channels and dci time"); + printStatIndent(&eNB->dlsch_ue_specific,"DL per ue part time"); + printStatIndent2(&eNB->dlsch_encoding_stats,"DLSCH encoding time"); + printStatIndent3(&eNB->dlsch_rate_matching_stats,"DLSCH rate matching time"); + printStatIndent3(&eNB->dlsch_turbo_encoding_stats,"DLSCH turbo encoding time"); + printStatIndent3(&eNB->dlsch_interleaving_stats,"DLSCH interleaving time"); + printStatIndent2(&eNB->dlsch_scrambling_stats, "DLSCH scrambling time"); + printStatIndent2(&eNB->dlsch_modulation_stats, "DLSCH modulation time"); + printDistribution(&eNB->ofdm_mod_stats,table_tx_ifft,"OFDM_mod (idft) time"); + printf("\nUE RX function statistics (per 1ms subframe)\n"); + printDistribution(&phy_proc_rx_tot, table_rx,"Total PHY proc rx"); + printStatIndent(&ue_front_end_tot,"Front end processing"); + printStatIndent(&dlsch_llr_tot,"rx_pdsch processing"); + printStatIndent2(&pdsch_procedures_tot,"pdsch processing"); + printStatIndent2(&dlsch_procedures_tot,"dlsch processing"); + printStatIndent2(&UE->crnti_procedures_stats,"C-RNTI processing"); + printStatIndent(&UE->ofdm_demod_stats,"ofdm demodulation"); + printStatIndent(&UE->dlsch_channel_estimation_stats,"DLSCH channel estimation time"); + printStatIndent(&UE->dlsch_freq_offset_estimation_stats,"DLSCH frequency offset estimation time"); + printStatIndent(&dlsch_decoding_tot, "DLSCH Decoding time "); + printStatIndent(&UE->dlsch_unscrambling_stats,"DLSCH unscrambling time"); + printStatIndent(&UE->dlsch_rate_unmatching_stats,"DLSCH Rate Unmatching"); + printf("|__ DLSCH Turbo Decoding(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", + UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Cminus ? + UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kminus : + UE->dlsch[UE->current_thread_id[subframe]][0][0]->harq_processes[0]->Kplus, + UE->dlsch_tc_intl1_stats.trials/(double)UE->dlsch_tc_init_stats.trials, + (double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials*timeBase, + (int)((double)UE->dlsch_turbo_decoding_stats.diff/UE->dlsch_turbo_decoding_stats.trials), + UE->dlsch_turbo_decoding_stats.trials); + printStatIndent2(&UE->dlsch_tc_init_stats,"init"); + printStatIndent2(&UE->dlsch_tc_alpha_stats,"alpha"); + printStatIndent2(&UE->dlsch_tc_beta_stats,"beta"); + printStatIndent2(&UE->dlsch_tc_gamma_stats,"gamma"); + printStatIndent2(&UE->dlsch_tc_ext_stats,"ext"); + printStatIndent2(&UE->dlsch_tc_intl1_stats,"turbo internal interleaver"); + printStatIndent2(&UE->dlsch_tc_intl2_stats,"intl2+HardDecode+CRC"); + } + + if ((transmission_mode != 3) && (transmission_mode != 4)) { + fprintf(bler_fd,"%f;%d;%d;%f;%u;%u;%u;%u;%u;%u;%u;%u;%u\n", + SNR, + mcs1, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + rate, + errs[0], + round_trials[0], + errs[1], + round_trials[1], + errs[2], + round_trials[2], + errs[3], + round_trials[3], + dci_errors[0]); + } else { + fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%u;%u;%u;%u;%u;%u;%u;%u;%u\n", + SNR, + mcs1,mcs2, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, + rate, + errs[0], + round_trials[0], + errs[1], + round_trials[1], + errs[2], + round_trials[2], + errs[3], + round_trials[3], + dci_errors[0]); + } + + if(abstx) { //ABSTRACTION + blerr[0] = (double)errs[0]/(round_trials[0]); + + if(num_rounds>1) { + blerr[1] = (double)errs[1]/(round_trials[1]); + blerr[2] = (double)errs[2]/(round_trials[2]); + blerr[3] = (double)errs[3]/(round_trials[3]); + fprintf(csv_fd,"%e,%e,%e,%e;\n",blerr[0],blerr[1],blerr[2],blerr[3]); + } else { + fprintf(csv_fd,"%e;\n",blerr[0]); + } + } //ABStraction + + if ( (test_perf != 0) && (100 * effective_rate > test_perf )) { + //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; err0; trials0; err1; trials1; err2; trials2; err3; trials3; dci_err\n"); + if ((transmission_mode != 3) && (transmission_mode != 4)) { + fprintf(time_meas_fd,"%f;%d;%d;%f;%u;%u;%u;%u;%u;%u;%u;%u;%u;", + SNR, + mcs1, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + rate, + errs[0], + round_trials[0], + errs[1], + round_trials[1], + errs[2], + round_trials[2], + errs[3], + round_trials[3], + dci_errors[0]); + //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); + fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%u;%u;%u;%u;%u;%u;%u;%u;%e;%e;%e;%e;%u;%u;%e;%f;%f;", + SNR, + mcs1, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + rate*effective_rate, + 100*effective_rate, + rate, + (double)avg_iter/iter_trials, + errs[0], + round_trials[0], + errs[1], + round_trials[1], + errs[2], + round_trials[2], + errs[3], + round_trials[3], + (double)errs[0]/(round_trials[0]), + (double)errs[1]/(round_trials[0]), + (double)errs[2]/(round_trials[0]), + (double)errs[3]/(round_trials[0]), + dci_errors[0], + round_trials[0], + (double)dci_errors[0]/(round_trials[0]), + (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ + (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, + (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); + } else { + fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%u;%u;%u;%u;%u;%u;%u;%u;%u;", + SNR, + mcs1,mcs2, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, + rate, + errs[0], + round_trials[0], + errs[1], + round_trials[1], + errs[2], + round_trials[2], + errs[3], + round_trials[3], + dci_errors[0]); + //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); + fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%u;%u;%u;%u;%u;%u;%u;%u;%e;%e;%e;%e;%u;%u;%e;%f;%f;", + SNR, + mcs1,mcs2, + eNB->dlsch[0][0]->harq_processes[0]->TBS, + eNB->dlsch[0][1]->harq_processes[0]->TBS, + rate*effective_rate, + 100*effective_rate, + rate, + (double)avg_iter/iter_trials, + errs[0], + round_trials[0], + errs[1], + round_trials[1], + errs[2], + round_trials[2], + errs[3], + round_trials[3], + (double)errs[0]/(round_trials[0]), + (double)errs[1]/(round_trials[0]), + (double)errs[2]/(round_trials[0]), + (double)errs[3]/(round_trials[0]), + dci_errors[0], + round_trials[0], + (double)dci_errors[0]/(round_trials[0]), + (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ + (double)eNB->dlsch[0][0]->harq_processes[0]->TBS, + (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); + } + + //fprintf(time_meas_fd,"eNB_PROC_TX(%d); OFDM_MOD(%d); DL_MOD(%d); DL_SCR(%d); DL_ENC(%d); UE_PROC_RX(%d); OFDM_DEMOD_CH_EST(%d); RX_PDCCH(%d); CH_COMP_LLR(%d); DL_USCR(%d); DL_DECOD(%d);\n", + fprintf(time_meas_fd,"%d; %d; %d; %d; %d; %d; %d; %d; %d; %d; %d;", + eNB->phy_proc_tx.trials, + eNB->ofdm_mod_stats.trials, + eNB->dlsch_modulation_stats.trials, + eNB->dlsch_scrambling_stats.trials, + eNB->dlsch_encoding_stats.trials, + phy_proc_rx_tot.trials, + UE->ofdm_demod_stats.trials, + UE->dlsch_rx_pdcch_stats.trials, + UE->dlsch_llr_stats.trials, + UE->dlsch_unscrambling_stats.trials, + UE->dlsch_decoding_stats[UE->current_thread_id[subframe]].trials + ); + fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;", + get_time_meas_us(&eNB->phy_proc_tx), + get_time_meas_us(&eNB->ofdm_mod_stats), + get_time_meas_us(&eNB->dlsch_modulation_stats), + get_time_meas_us(&eNB->dlsch_scrambling_stats), + get_time_meas_us(&eNB->dlsch_encoding_stats), + get_time_meas_us(&phy_proc_rx_tot), + nsymb*get_time_meas_us(&UE->ofdm_demod_stats), + get_time_meas_us(&UE->dlsch_rx_pdcch_stats), + 3*get_time_meas_us(&UE->dlsch_llr_stats), + get_time_meas_us(&UE->dlsch_unscrambling_stats), + get_time_meas_us(&UE->dlsch_decoding_stats[UE->current_thread_id[subframe]]) + ); + //fprintf(time_meas_fd,"eNB_PROC_TX_STD;eNB_PROC_TX_MAX;eNB_PROC_TX_MIN;eNB_PROC_TX_MED;eNB_PROC_TX_Q1;eNB_PROC_TX_Q3;eNB_PROC_TX_DROPPED;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;",squareRoot(&UE->phy_proc_tx), t_tx_max, t_tx_min, median(table_tx), q1(table_tx), q3(table_tx), n_tx_dropped); + //fprintf(time_meas_fd,"IFFT;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", + squareRoot(&eNB->ofdm_mod_stats), + median(table_tx_ifft),q1(table_tx_ifft),q3(table_tx_ifft)); + //fprintf(time_meas_fd,"MOD;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", + squareRoot(&eNB->dlsch_modulation_stats), + median(table_tx_mod), q1(table_tx_mod), q3(table_tx_mod)); + //fprintf(time_meas_fd,"ENC;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", + squareRoot(&eNB->dlsch_encoding_stats), + median(table_tx_enc),q1(table_tx_enc),q3(table_tx_enc)); + //fprintf(time_meas_fd,"eNB_PROC_RX_STD;eNB_PROC_RX_MAX;eNB_PROC_RX_MIN;eNB_PROC_RX_MED;eNB_PROC_RX_Q1;eNB_PROC_RX_Q3;eNB_PROC_RX_DROPPED;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;%f;%f;%d;", + squareRoot(&phy_proc_rx_tot), t_rx_max, t_rx_min, + median(table_rx), q1(table_rx), q3(table_rx), n_rx_dropped); + //fprintf(time_meas_fd,"FFT;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", + squareRoot(&UE->ofdm_demod_stats), + median(table_rx_fft), q1(table_rx_fft), q3(table_rx_fft)); + //fprintf(time_meas_fd,"DEMOD;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f;", + squareRoot(&UE->dlsch_demodulation_stats), + median(table_rx_demod), q1(table_rx_demod), q3(table_rx_demod)); + //fprintf(time_meas_fd,"DEC;\n"); + fprintf(time_meas_fd,"%f;%f;%f;%f\n", + squareRoot(&UE->dlsch_decoding_stats[subframe]), + median(table_rx_dec), q1(table_rx_dec), q3(table_rx_dec)); + printf("[passed] effective rate : %f (%2.1f%%,%f)): log and break \n",rate*effective_rate, 100*effective_rate, rate ); + test_passed = 1; + break; + } else if (test_perf !=0 ) { + printf("[continue] effective rate : %f (%2.1f%%,%f)): increase snr \n",rate*effective_rate, 100*effective_rate, rate); + test_passed = 0; + } + + if (((double)errs[0]/(round_trials[0]))<(10.0/n_frames)) + break; + }// SNR + } //ch_realization + + fclose(bler_fd); + + if (test_perf !=0) + fclose (time_meas_fd); + + //fprintf(tikz_fd,"};\n"); + //fclose(tikz_fd); + + if (input_trch_file==1) + fclose(input_trch_fd); + + if (input_file==1) + fclose(input_fd); + + if(abstx) { // ABSTRACTION + fprintf(csv_fd,"];"); + fclose(csv_fd); + } + + if (uncoded_ber_bit) + free(uncoded_ber_bit); + + uncoded_ber_bit = NULL; + printf("Freeing dlsch structures\n"); + + for (i=0; i<2; i++) { + printf("eNB %d\n",i); + free_eNB_dlsch(eNB->dlsch[0][i]); + printf("UE %d\n",i); + free_ue_dlsch(UE->dlsch[UE->current_thread_id[subframe]][0][i]); + } + + if (test_perf && !test_passed) + return(-1); + else + return(0); +} +/* temporary dummy implem of get_softmodem_optmask, till basic simulators implemented as device */ +uint64_t get_softmodem_optmask(void) { + return 0; +} diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index c950d6f4da..37ce3a65d6 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -729,6 +729,7 @@ int main(int argc, char **argv) { channel_model, N_RB2sampling_rate(eNB->frame_parms.N_RB_UL), N_RB2channel_bandwidth(eNB->frame_parms.N_RB_UL), + 30e-9, forgetting_factor, delay, 0); @@ -1086,7 +1087,7 @@ int main(int argc, char **argv) { if (awgn_flag == 0) { if (UE2eNB->max_Doppler == 0) { multipath_channel(UE2eNB,s_re,s_im,r_re,r_im, - eNB->frame_parms.samples_per_tti,hold_channel); + eNB->frame_parms.samples_per_tti,hold_channel,0); } else { multipath_tv_channel(UE2eNB,s_re,s_im,r_re,r_im, 2*eNB->frame_parms.samples_per_tti,hold_channel); diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 9374050e58..957495181a 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -37,7 +37,6 @@ #include "PHY/INIT/phy_init.h" #include "PHY/MODULATION/modulation_eNB.h" #include "PHY/MODULATION/modulation_UE.h" -#include "PHY/NR_REFSIG/nr_mod_table.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" @@ -59,7 +58,8 @@ double cpuf; uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; - +uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; +uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; // needed for some functions PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } }; @@ -114,7 +114,7 @@ int main(int argc, char **argv) uint16_t nb_rb = 50; uint8_t Imcs = 9; uint8_t mcs_table = 0; - + double DS_TDL = .03; cpuf = get_cpu_freq_GHz(); if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) { @@ -337,6 +337,7 @@ int main(int argc, char **argv) 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), + DS_TDL, 0, 0, 0); if (gNB2UE == NULL) { @@ -478,8 +479,9 @@ int main(int argc, char **argv) harq_process->Qm = mod_order; harq_process->rvidx = rvidx; harq_process->R = rate; - harq_process->dmrsConfigType = 1; + harq_process->dmrsConfigType = NFAPI_NR_DMRS_TYPE1; harq_process->dlDmrsSymbPos = 4; + harq_process->n_dmrs_cdm_groups = 1; printf("harq process ue mcs = %d Qm = %d, symb %d\n", harq_process->mcs, harq_process->Qm, nb_symb_sch); unsigned char *test_input; test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8); @@ -499,7 +501,7 @@ int main(int argc, char **argv) //printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32)); // generate signal if (input_fd == NULL) { - nr_dlsch_encoding(test_input, frame, slot, dlsch, frame_parms,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + nr_dlsch_encoding(gNB, test_input, frame, slot, dlsch, frame_parms,NULL,NULL,NULL,NULL,NULL,NULL,NULL); } for (SNR = snr0; SNR < snr1; SNR += snr_step) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 137c358d7f..38400cab51 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -38,9 +38,10 @@ #include "PHY/types.h" #include "PHY/INIT/phy_init.h" #include "PHY/MODULATION/modulation_eNB.h" +#include "PHY/MODULATION/nr_modulation.h" #include "PHY/MODULATION/modulation_UE.h" -#include "PHY/NR_REFSIG/nr_mod_table.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "SCHED_NR/fapi_nr_l1.h" @@ -123,7 +124,7 @@ int generate_dlsch_header(unsigned char *mac_header, unsigned char *ue_cont_res_id, unsigned char short_padding, unsigned short post_padding){return 0;} -void nr_ip_over_LTE_DRB_preconfiguration(void){} +void nr_DRB_preconfiguration(void){} // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; @@ -181,7 +182,7 @@ int main(int argc, char **argv) //unsigned char frame_type = 0; - int frame=0,slot=1; + int frame=1,slot=1; int frame_length_complex_samples; int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; @@ -192,7 +193,8 @@ int main(int argc, char **argv) int cyclic_prefix_type = NFAPI_CP_NORMAL; int run_initial_sync=0; int do_pdcch_flag=1; - + int pusch_tgt_snrx10 = 200; + int pucch_tgt_snrx10 = 200; int loglvl=OAILOG_INFO; float target_error_rate = 0.01; @@ -529,9 +531,9 @@ int main(int argc, char **argv) AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; // common configuration - rrc_mac_config_req_gNB(0,0,1,scc,0,0,NULL); + rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL); // UE dedicated configuration - rrc_mac_config_req_gNB(0,0,1,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); + rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); phy_init_nr_gNB(gNB,0,0); N_RB_DL = gNB->frame_parms.N_RB_DL; // stub to configure frame_parms @@ -572,6 +574,7 @@ int main(int argc, char **argv) channel_model, fs, bw, + 30e-9, 0, 0, 0); @@ -714,12 +717,16 @@ int main(int argc, char **argv) reset_meas(&gNB->tparity); reset_meas(&gNB->toutput); + clear_pdsch_stats(gNB); + n_errors = 0; effRate = 0; //n_errors2 = 0; //n_alamouti = 0; errors_scrambling=0; n_false_positive = 0; + if (n_trials== 1) num_rounds = 1; + for (trial = 0; trial < n_trials; trial++) { errors_bit = 0; @@ -754,6 +761,7 @@ int main(int argc, char **argv) UE_list->UE_sched_ctrl[0].harq_processes[harq_pid].ndi = !(trial&1); + UE_list->UE_sched_ctrl[0].harq_processes[harq_pid].round = round; UE_list->UE_sched_ctrl[0].current_harq_pid = harq_pid; gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round; @@ -778,12 +786,12 @@ int main(int argc, char **argv) int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP; if (n_trials==1) { - LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); + LOG_M("txsigF0.m","txsF0", &gNB->common_vars.txdataF[0][txdataF_offset],frame_parms->samples_per_slot_wCP,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("txsigF1.m","txsF1", &gNB->common_vars.txdataF[1][txdataF_offset],frame_parms->samples_per_slot_wCP,1,1); } int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); - if (n_trials==1) printf("samples_per_slot_wCP = %d\n", frame_parms->samples_per_slot_wCP); + if (n_trials==1) printf("tx_offset %d, txdataF_offset %d \n", tx_offset,txdataF_offset); //TODO: loop over slots for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { @@ -795,24 +803,51 @@ int main(int argc, char **argv) 12, frame_parms->nb_prefix_samples, CYCLIC_PREFIX); - } else { + } else {/* nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], &txdata[aa][tx_offset], 14, frame_parms); + */ + PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], + (int*)&txdata[aa][tx_offset], + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + + apply_nr_rotation(frame_parms, + (int16_t*)&txdata[aa][tx_offset], + slot, + 0, + 1, + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0); + PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset+frame_parms->ofdm_symbol_size], + (int*)&txdata[aa][tx_offset+frame_parms->nb_prefix_samples0+frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 13, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + apply_nr_rotation(frame_parms, + (int16_t*)&txdata[aa][tx_offset+frame_parms->nb_prefix_samples0+frame_parms->ofdm_symbol_size], + slot, + 1, + 13, + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); + } } if (n_trials==1) { - LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1); + LOG_M("txsig0.m","txs0", &txdata[0][tx_offset],frame_parms->get_samples_slot_timestamp(slot,frame_parms,0),1,1); if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1); + LOG_M("txsig1.m","txs1", &txdata[1][tx_offset],frame_parms->get_samples_slot_timestamp(slot,frame_parms,0),1,1); } if (output_fd) { printf("writing txdata to binary file\n"); fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd); } - + int txlev = signal_energy(&txdata[0][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); // if (n_trials==1) printf("txlev %d (%f)\n",txlev,10*log10((double)txlev)); @@ -924,25 +959,10 @@ int main(int argc, char **argv) (float) n_errors / (float) n_trials); printf("*****************************************\n"); printf("\n"); + dump_pdsch_stats(gNB); printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %d bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS); printf("\n"); - if (n_trials == 1) { - - LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 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); - LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1); - write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1); - break; - } - - //if ((float)n_errors/(float)n_trials <= target_error_rate) { - if (effRate >= (eff_tp_check*TBS)) { - printf("PDSCH test OK\n"); - break; - } - if (print_perf==1) { printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n", 1000>>*scc->ssbSubcarrierSpacing,dlsch_config.rbSize,dlsch_config.mcsIndex[0], @@ -993,6 +1013,24 @@ int main(int argc, char **argv) printStatIndent2(&UE->dlsch_tc_intl2_stats,"intl2+HardDecode+CRC"); */ } + + if (n_trials == 1) { + + LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 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); + LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1); + write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1); + LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE->current_thread_id[UE_proc.nr_tti_rx]][0]->llr[0],available_bits,1,0); + break; + } + + //if ((float)n_errors/(float)n_trials <= target_error_rate) { + if (effRate >= (eff_tp_check*TBS)) { + printf("PDSCH test OK\n"); + break; + } + snrRun++; } // NSR diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 2144652f86..833b81f853 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -33,7 +33,6 @@ #include "PHY/defs_nr_UE.h" #include "PHY/defs_gNB.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/INIT/phy_init.h" @@ -60,6 +59,10 @@ uint16_t NB_UE_INST = 1; // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; + +uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; +uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; + uint64_t get_softmodem_optmask(void) {return 0;} void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} @@ -105,6 +108,9 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band); nr_init_frame_parms(gNB_config, fp); + + init_symbol_rotation(fp,fp->dl_CarrierFreq); + gNB->configured = 1; LOG_I(PHY,"gNB configured\n"); } @@ -468,6 +474,7 @@ int main(int argc, char **argv) channel_model, fs, bw, + 300e-9, 0, 0, 0); @@ -548,10 +555,35 @@ int main(int argc, char **argv) frame_parms->nb_prefix_samples, CYCLIC_PREFIX); } else { - nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], + /* nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], &txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], 14, - frame_parms); + frame_parms);*/ + PHY_ofdm_mod(gNB->common_vars.txdataF[aa], + (int*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + + apply_nr_rotation(frame_parms, + (int16_t*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)], + slot, + 0, + 1, + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0); + PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][frame_parms->ofdm_symbol_size], + (int*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+frame_parms->nb_prefix_samples0+frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 13, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + apply_nr_rotation(frame_parms, + (int16_t*)&txdata[aa][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+frame_parms->nb_prefix_samples0+frame_parms->ofdm_symbol_size], + slot, + 1, + 13, + frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); } } } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 9aed6a8b3e..891c8f50ae 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -37,7 +37,6 @@ #include "SCHED_NR_UE/phy_frame_config_nr.h" #include "PHY/phy_vars_nr_ue.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/INIT/phy_init.h" @@ -76,7 +75,7 @@ boolean_t pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, const sdu_size_t sdu_buffer_sizeP, mem_block_t *const sdu_buffer_pP) {return(false);} -void nr_ip_over_LTE_DRB_preconfiguration(void){} +void nr_DRB_preconfiguration(void){} void pdcp_layer_init(void) {} int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;} @@ -97,6 +96,7 @@ int main(int argc, char **argv){ uint8_t N_RA_slot; uint8_t config_period; int prachOccasion = 0; + double DS_TDL = .03; // int8_t interf1=-19,interf2=-19; // uint8_t abstraction_flag=0,calibration_flag=0; @@ -559,6 +559,7 @@ int main(int argc, char **argv){ channel_model, fs, bw, + DS_TDL, 0.0, delay, 0); @@ -604,7 +605,7 @@ int main(int argc, char **argv){ /* tx_lev_dB not used later, no need to set */ //tx_lev_dB = (unsigned int) dB_fixed(tx_lev); - prach_start = subframe*frame_parms->samples_per_subframe-UE->N_TA_offset; + prach_start = subframe*frame_parms->samples_per_subframe; #ifdef NR_PRACH_DEBUG LOG_M("txsig0.m", "txs0", &txdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 004a7b8de8..c14a3d7198 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -33,9 +33,9 @@ #include "PHY/defs_nr_UE.h" #include "PHY/defs_gNB.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_ESTIMATION/nr_ul_estimation.h" #include "PHY/INIT/phy_init.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -55,6 +55,8 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; +uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; +uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; // needed for some functions PHY_VARS_NR_UE * PHY_vars_UE_g[1][1]={{NULL}}; @@ -78,11 +80,11 @@ int main(int argc, char **argv) //int freq_offset; //int subframe_offset; //char fname[40], vname[40]; - int trial,n_trials=100,n_errors=0,ack_nack_errors=0; + int trial,n_trials=100,n_errors=0,ack_nack_errors=0,sr_errors=0; uint8_t transmission_mode = 1,n_tx=1,n_rx=1; uint16_t Nid_cell=0; uint64_t SSB_positions=0x01; - channel_desc_t *gNB2UE; + channel_desc_t *UE2gNB; int format=0; //uint8_t extended_prefix_flag=0; FILE *input_fd=NULL; @@ -98,6 +100,8 @@ int main(int argc, char **argv) uint16_t nrofPRB=2; uint8_t timeDomainOCC=0; SCM_t channel_model=AWGN;//Rayleigh1_anticorr; + + double DS_TDL = .03; int N_RB_DL=273,mu=1; float target_error_rate=0.001; @@ -160,6 +164,20 @@ int main(int argc, char **argv) case 'G': channel_model=ETU; break; + case 'H': + channel_model = TDL_C; + DS_TDL = .030; // 30 ns + break; + + case 'I': + channel_model = TDL_C; + DS_TDL = .3; // 300ns + break; + + case 'J': + channel_model=TDL_D; + DS_TDL = .03; + break; default: printf("Unsupported channel model!\n"); @@ -400,9 +418,9 @@ int main(int argc, char **argv) printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO); } - gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, bw, 0, 0, 0); + UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, fs, bw, DS_TDL,0, 0, 0); - if (gNB2UE==NULL) { + if (UE2gNB==NULL) { printf("Problem generating channel model. Exiting.\n"); exit(-1); } @@ -461,20 +479,24 @@ int main(int argc, char **argv) uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0; //t_nrPolar_params *currentPtr; + int shift = 0; + if(format==0){ - // for now we are not considering SR just HARQ-ACK + if (sr_flag) + shift = 1< 11) gNB->uci_polarParams = nr_polar_params(2, nr_bit, nrofPRB, 1, NULL); for(SNR=snr0;SNR<=snr1;SNR=SNR+1){ ack_nack_errors=0; + sr_errors=0; n_errors = 0; for (trial=0; trialofdm_symbol_size*sizeof(int)); @@ -503,6 +525,15 @@ int main(int argc, char **argv) } int rxlev = signal_energy(&rxdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size); + + // noise measurement + gNB->ulmask_symb = startingSymbolIndex; + for (int rb=0; rbrb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + gNB_I0_measurements(gNB); + if (n_trials==1) printf("rxlev %d (%d dB), sigma2 %f dB, SNR %f, TX %f\n",rxlev,dB_fixed(rxlev),sigma2_dB,SNR,10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12)); if(format==0){ nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu; @@ -520,15 +551,23 @@ int main(int argc, char **argv) pucch_pdu.start_symbol_index = startingSymbolIndex; pucch_pdu.prb_start = startingPRB; nr_decode_pucch0(gNB,nr_tti_tx,&uci_pdu,&pucch_pdu); - if(nr_bit==1) - ack_nack_errors+=(actual_payload^uci_pdu.harq->harq_list[0].harq_value); - else - ack_nack_errors+=(((actual_payload&1)^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value)); - free(uci_pdu.harq->harq_list); + if(sr_flag==1){ + if (uci_pdu.sr->sr_indication == 0 || uci_pdu.sr->sr_confidence_level == 1) + sr_errors+=1; + } + if(nr_bit>0){ + if(nr_bit==1) + ack_nack_errors+=(actual_payload^uci_pdu.harq->harq_list[0].harq_value); + else + ack_nack_errors+=(((actual_payload&1)^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value)); + free(uci_pdu.harq->harq_list); + } } else if (format==1) { - - nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,hopping_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,hopping_id, + &(payload_received),frame_parms,amp,nr_tti_tx, + m0,nrofSymbols,startingSymbolIndex,startingPRB, + startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); if(nr_bit==1) ack_nack_errors+=((actual_payload^payload_received)&1); else @@ -567,8 +606,11 @@ int main(int argc, char **argv) } n_errors=((actual_payload^payload_received)&1)+(((actual_payload^payload_received)&2)>>1)+(((actual_payload^payload_received)&4)>>2)+n_errors; } - printf("SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors); - if((float)ack_nack_errors/(float)(n_trials)<=target_error_rate){ + if (sr_flag == 1) + printf("SR: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,sr_errors); + if(nr_bit > 0) + printf("ACK/NACK: SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors); + if((float)(ack_nack_errors+sr_errors)/(float)(n_trials)<=target_error_rate){ printf("PUCCH test OK\n"); break; } diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index b0557ef1b4..f6d33c1d4b 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -34,7 +34,6 @@ #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_proto.h" @@ -56,6 +55,9 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} +uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; +uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; + double cpuf; uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; @@ -97,6 +99,8 @@ int main(int argc, char **argv) uint16_t nb_rb = 50; uint8_t Imcs = 9; + double DS_TDL = .03; + cpuf = get_cpu_freq_GHz(); if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == 0) { @@ -316,13 +320,12 @@ int main(int argc, char **argv) snr1 = snr0 + 10; gNB2UE = new_channel_desc_scm(n_tx, - n_rx, - channel_model, + n_rx, + channel_model, 61.44e6, //N_RB2sampling_rate(N_RB_DL), 40e6, //N_RB2channel_bandwidth(N_RB_DL), - 0, - 0, - 0); + DS_TDL, + 0,0,0); if (gNB2UE == NULL) { printf("Problem generating channel model. Exiting.\n"); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index bcaa967a30..9dd6d61557 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -37,7 +37,6 @@ #include "PHY/MODULATION/modulation_UE.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_REFSIG/dmrs_nr.h" -#include "PHY/NR_REFSIG/nr_mod_table.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" @@ -56,7 +55,6 @@ //#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" - #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) #include "SIMULATION/LTE_PHY/common_sim.h" @@ -97,13 +95,20 @@ boolean_t pdcp_data_ind( ) { return(false);} void pdcp_run (const protocol_ctxt_t *const ctxt_pP) { return;} -void nr_ip_over_LTE_DRB_preconfiguration(void){} +void nr_DRB_preconfiguration(void){} int rrc_init_nr_global_param(void){return(0);} // needed for some functions uint16_t n_rnti = 0x1234; openair0_config_t openair0_cfg[MAX_CARDS]; +//const uint8_t nr_rv_round_map[4] = {0, 2, 1, 3}; + +channel_desc_t *UE2gNB[NUMBER_OF_UE_MAX][NUMBER_OF_gNB_MAX]; +double s_re0[122880],s_im0[122880],r_re0[122880],r_im0[122880]; +double s_re1[122880],s_im1[122880],r_re1[122880],r_im1[122880]; +double r_re2[122880],r_im2[122880]; +double r_re3[122880],r_im3[122880]; int main(int argc, char **argv) { @@ -113,27 +118,35 @@ int main(int argc, char **argv) double sigma, sigma_dB; double snr_step = .2; uint8_t snr1set = 0; - int slot = 8, frame = 0; + int slot = 8, frame = 1; FILE *output_fd = NULL; + double *s_re[2]= {s_re0,s_re1}; + double *s_im[2]= {s_im0,s_im1}; + double *r_re[4]= {r_re0,r_re1,r_re2,r_re3}; + double *r_im[4]= {r_im0,r_im1,r_im2,r_im3}; //uint8_t write_output_file = 0; - int trial, n_trials = 1, n_errors = 0, n_false_positive = 0, delay = 0; + int trial, n_trials = 1, n_false_positive = 0, delay = 0; + double maxDoppler = 0.0; uint8_t n_tx = 1, n_rx = 1; //uint8_t transmission_mode = 1; //uint16_t Nid_cell = 0; - channel_desc_t *gNB2UE; + channel_desc_t *UE2gNB; uint8_t extended_prefix_flag = 0; //int8_t interf1 = -21, interf2 = -21; FILE *input_fd = NULL; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; + double tx_gain=1.0; + double N0=30; + //unsigned char frame_type = 0; NR_DL_FRAME_PARMS *frame_parms; - int loglvl = OAILOG_WARNING; + int loglvl = OAILOG_INFO; //uint64_t SSB_positions=0x01; uint16_t nb_symb_sch = 12; - int start_symbol = 2; + int start_symbol = 0; uint16_t nb_rb = 50; - uint8_t Imcs = 9; + int Imcs = 9; uint8_t precod_nbr_layers = 1; int gNB_id = 0; int ap; @@ -146,10 +159,26 @@ int main(int argc, char **argv) int print_perf = 0; cpuf = get_cpu_freq_GHz(); int msg3_flag = 0; + int rv_index = 0; + float roundStats[50]; + float effRate; + //float eff_tp_check = 0.7; + uint8_t snrRun; + + int enable_ptrs = 0; + int modify_dmrs = 0; + /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */ + int ptrs_arg[2] = {-1,-1};// Invalid values + /* DMRS TYPE = dmrs_arg[0], Add Pos = dmrs_arg[1] */ + int dmrs_arg[2] = {-1,-1};// Invalid values UE_nr_rxtx_proc_t UE_proc; FILE *scg_fd=NULL; + int file_offset = 0; + double DS_TDL = .03; + int pusch_tgt_snrx10 = 200; + int pucch_tgt_snrx10 = 200; int ibwps=24; int ibwp_rboffset=41; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) { @@ -159,7 +188,7 @@ int main(int argc, char **argv) //logInit(); randominit(0); - while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:i:j:kl:m:n:p:r:s:y:z:F:M:N:PR:S:L:")) != -1) { + while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:i:j:kl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:")) != -1) { printf("handling optarg %c\n",c); switch (c) { @@ -228,7 +257,22 @@ int main(int argc, char **argv) case 'G': channel_model = ETU; break; - + + case 'H': + channel_model = TDL_C; + DS_TDL = .030; // 30 ns + break; + + case 'I': + channel_model = TDL_C; + DS_TDL = .3; // 300ns + break; + + case 'J': + channel_model=TDL_D; + DS_TDL = .03; + break; + default: printf("Unsupported channel model!\n"); exit(-1); @@ -273,7 +317,12 @@ int main(int argc, char **argv) snr0 = atof(optarg); printf("Setting SNR0 to %f\n", snr0); break; - + +/* + case 't': + eff_tp_check = (float)atoi(optarg)/100; + break; +*/ /* case 'r': ricean_factor = pow(10,-.1*atof(optarg)); @@ -317,7 +366,15 @@ int main(int argc, char **argv) } break; - + + case 'G': + file_offset = atoi(optarg); + break; + + case 'H': + slot = atoi(optarg); + break; + case 'M': // SSB_positions = atoi(optarg); break; @@ -345,7 +402,21 @@ int main(int argc, char **argv) case 'L': loglvl = atoi(optarg); break; - + + case 'T': + enable_ptrs=1; + for(i=0; i < atoi(optarg); i++){ + ptrs_arg[i] = atoi(argv[optind++]); + } + break; + + case 'U': + modify_dmrs = 1; + for(i=0; i < atoi(optarg); i++){ + dmrs_arg[i] = atoi(argv[optind++]); + } + 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]); @@ -372,8 +443,11 @@ int main(int argc, char **argv) printf("-N Nid_cell\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); printf("-R N_RB_DL\n"); + printf("-t Acceptable effective throughput (in percentage)\n"); printf("-S Ending SNR, runs from SNR0 to SNR1\n"); printf("-P Print ULSCH performances\n"); + printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n"); + printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:3}, e.g. -U 2 0 2 \n"); exit(-1); break; @@ -391,19 +465,34 @@ int main(int argc, char **argv) if (snr1set == 0) snr1 = snr0 + 10; + double sampling_frequency; + double bandwidth; - 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), + if (N_RB_UL >= 217) sampling_frequency = 122.88; + else if (N_RB_UL >= 106) sampling_frequency = 61.44; + else { printf("Need at least 106 PRBs\b"); exit(-1); } + if (N_RB_UL == 273) bandwidth = 100; + else if (N_RB_UL == 217) bandwidth = 80; + else if (N_RB_UL == 106) bandwidth = 40; + else { printf("Add N_RB_UL %d\n",N_RB_UL); exit(-1); } + + if (openair0_cfg[0].threequarter_fs == 1) sampling_frequency*=.75; + + UE2gNB = new_channel_desc_scm(n_tx, n_rx, channel_model, + sampling_frequency, + bandwidth, + DS_TDL, 0, 0, 0); - if (gNB2UE == NULL) { + if (UE2gNB == NULL) { printf("Problem generating channel model. Exiting.\n"); exit(-1); } + UE2gNB->max_Doppler = maxDoppler; + RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); - RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB)); + RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; //gNB_config = &gNB->gNB_config; @@ -447,20 +536,19 @@ int main(int argc, char **argv) 0); fix_scc(scc,ssb_bitmap); - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); + // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; // common configuration - rrc_mac_config_req_gNB(0,0,1,scc,0,0,NULL); + rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL); // UE dedicated configuration - rrc_mac_config_req_gNB(0,0,1,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); + rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); phy_init_nr_gNB(gNB,0,0); N_RB_DL = gNB->frame_parms.N_RB_DL; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; //crcTableInit(); @@ -535,20 +623,16 @@ int main(int argc, char **argv) unsigned char *estimated_output_bit; unsigned char *test_input_bit; uint32_t errors_decoding = 0; - uint32_t errors_scrambling = 0; + test_input_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); estimated_output_bit = (unsigned char *) malloc16(sizeof(unsigned char) * 16 * 68 * 384); nr_scheduled_response_t scheduled_response; fapi_nr_ul_config_request_t ul_config; + fapi_nr_tx_request_t tx_req; + fapi_nr_tx_request_body_t tx_req_body; - unsigned int TBS; - uint16_t number_dmrs_symbols = 0; - unsigned int available_bits; - uint8_t nb_re_dmrs; - unsigned char mod_order; - uint16_t code_rate; uint8_t ptrs_mcs1 = 2; uint8_t ptrs_mcs2 = 4; uint8_t ptrs_mcs3 = 10; @@ -556,59 +640,160 @@ int main(int argc, char **argv) uint16_t n_rb1 = 75; uint8_t mcs_table = 0; uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; // | PUSCH_PDU_BITMAP_PUSCH_PTRS; + uint8_t max_rounds = 4; + uint8_t crc_status = 0; + + unsigned char mod_order = nr_get_Qm_ul(Imcs, 0); + uint16_t code_rate = nr_get_code_rate_ul(Imcs, 0); + + uint8_t mapping_type = typeB; // Default Values + pusch_dmrs_type_t dmrs_config_type = pusch_dmrs_type1; // Default Values + pusch_dmrs_AdditionalPosition_t add_pos = pusch_dmrs_pos0; // Default Values + + /* validate parameters othwerwise default values are used */ + /* -U flag can be used to set DMRS parameters*/ + if(modify_dmrs) + { + if(dmrs_arg[0] == 0) + { + mapping_type = typeA; + } + else if (dmrs_arg[0] == 1) + { + mapping_type = typeB; + } + /* Additional DMRS positions */ + if(dmrs_arg[1] >= 0 && dmrs_arg[1] <=3 ) + { + add_pos = dmrs_arg[1]; + } + printf("NOTE: DMRS config is modified with Mapping Type %d , Additional Position %d \n", mapping_type, add_pos ); + } + + uint8_t length_dmrs = pusch_len1; + uint16_t l_prime_mask = get_l_prime(nb_symb_sch, mapping_type, add_pos, length_dmrs); + uint16_t number_dmrs_symbols = get_dmrs_symbols_in_slot(l_prime_mask, nb_symb_sch); + uint8_t nb_re_dmrs = (dmrs_config_type == pusch_dmrs_type1) ? 6 : 4; + unsigned int available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, number_dmrs_symbols, mod_order, 1); + unsigned int TBS = nr_compute_tbs(mod_order, code_rate, nb_rb, nb_symb_sch, nb_re_dmrs * number_dmrs_symbols, 0, 0, precod_nbr_layers); + + uint8_t ulsch_input_buffer[TBS/8]; + + ulsch_input_buffer[0] = 0x31; + for (i = 1; i < TBS/8; i++) { + ulsch_input_buffer[i] = (unsigned char) rand(); + } - uint8_t length_dmrs = pusch_len1; // [hna] remove dmrs struct - uint16_t l_prime_mask = get_l_prime(nb_symb_sch, typeB, pusch_dmrs_pos0, length_dmrs); // [hna] remove dmrs struct uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, Imcs, mcs_table); uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, nb_rb); + int ptrs_symbols = 0; // to calculate total PTRS RE's in a slot + + double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); + + /* -T option enable PTRS */ + if(enable_ptrs) + { + /* validate parameters othwerwise default values are used */ + if(ptrs_arg[0] == 0 || ptrs_arg[0] == 1 || ptrs_arg[0] == 2 ) + { + ptrs_time_density = ptrs_arg[0]; + } + if(ptrs_arg[1] == 2 || ptrs_arg[1] == 4 ) + { + ptrs_freq_density = ptrs_arg[1]; + } + pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; + printf("NOTE: PTRS Enabled with L %d, K %d \n", ptrs_time_density, ptrs_freq_density ); + } + + if (input_fd != NULL) max_rounds=1; if(1<= nb_symb_sch) pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - for (i = 0; i < nb_symb_sch; i++) { - number_dmrs_symbols += (l_prime_mask >> i) & 0x01; - } - - mod_order = nr_get_Qm_ul(Imcs, 0); - code_rate = nr_get_code_rate_ul(Imcs, 0); - printf("\n"); - for (int i=0;i<16;i++) printf("%f\n",gaussdouble(0.0,1.0)); - for (SNR = snr0; SNR < snr1; SNR += snr_step) { + //for (int i=0;i<16;i++) printf("%f\n",gaussdouble(0.0,1.0)); + snrRun = 0; + int n_errs = 0; - varArray_t *table_rx=initVarArray(1000,sizeof(double)); + int slot_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); + int slot_length = slot_offset - frame_parms->get_samples_slot_timestamp(slot-1,frame_parms,0); + + if (input_fd != NULL) { + AssertFatal(frame_parms->nb_antennas_rx == 1, "nb_ant != 1\n"); + // 800 samples is N_TA_OFFSET for FR1 @ 30.72 Ms/s, + AssertFatal(frame_parms->subcarrier_spacing==30000,"only 30 kHz for file input for now (%d)\n",frame_parms->subcarrier_spacing); + + fseek(input_fd,file_offset*((slot_length<<2)+4000+16),SEEK_SET); + fread((void*)&n_rnti,sizeof(int16_t),1,input_fd); + printf("rnti %x\n",n_rnti); + fread((void*)&nb_rb,sizeof(int16_t),1,input_fd); + printf("nb_rb %d\n",nb_rb); + int16_t dummy; + fread((void*)&start_rb,sizeof(int16_t),1,input_fd); + //fread((void*)&dummy,sizeof(int16_t),1,input_fd); + printf("rb_start %d\n",start_rb); + fread((void*)&nb_symb_sch,sizeof(int16_t),1,input_fd); + //fread((void*)&dummy,sizeof(int16_t),1,input_fd); + printf("nb_symb_sch %d\n",nb_symb_sch); + fread((void*)&start_symbol,sizeof(int16_t),1,input_fd); + printf("start_symbol %d\n",start_symbol); + fread((void*)&Imcs,sizeof(int16_t),1,input_fd); + printf("mcs %d\n",Imcs); + fread((void*)&rv_index,sizeof(int16_t),1,input_fd); + printf("rv_index %d\n",rv_index); + // fread((void*)&harq_pid,sizeof(int16_t),1,input_fd); + fread((void*)&dummy,sizeof(int16_t),1,input_fd); + printf("harq_pid %d\n",harq_pid); + fread((void*)&gNB->common_vars.rxdata[0][slot_offset-delay], + sizeof(int16_t), + slot_length<<1, + input_fd); + for (int i=0;i<16;i+=2) printf("slot_offset %d : %d,%d\n", + slot_offset, + ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i], + ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]); + } + + for (SNR = snr0; SNR < snr1; SNR += snr_step) { + varArray_t *table_rx=initVarArray(1000,sizeof(double)); + int error_flag = 0; + n_false_positive = 0; + effRate = 0; + int n_errors[4] = {0,0,0,0};; + int round_trials[4]={0,0,0,0}; + uint32_t errors_scrambling[4] = {0,0,0,0}; + + clear_pusch_stats(gNB); + for (trial = 0; trial < n_trials; trial++) { + uint8_t round = 0; + + crc_status = 1; + errors_decoding = 0; + memset((void*)roundStats,0,50*sizeof(roundStats[0])); + while (roundharq_processes[harq_pid]->round = round; + gNB->ulsch[0][0]->harq_processes[harq_pid]->round = round; + rv_index = nr_rv_round_map[round]; reset_meas(&gNB->phy_proc_rx); + reset_meas(&gNB->rx_pusch_stats); reset_meas(&gNB->ulsch_decoding_stats); reset_meas(&gNB->ulsch_deinterleaving_stats); reset_meas(&gNB->ulsch_rate_unmatching_stats); reset_meas(&gNB->ulsch_ldpc_decoding_stats); reset_meas(&gNB->ulsch_unscrambling_stats); reset_meas(&gNB->ulsch_channel_estimation_stats); + reset_meas(&gNB->ulsch_ptrs_processing_stats); reset_meas(&gNB->ulsch_llr_stats); + reset_meas(&gNB->ulsch_mrc_stats); reset_meas(&gNB->ulsch_channel_compensation_stats); reset_meas(&gNB->ulsch_rbs_extraction_stats); UE_proc.nr_tti_tx = slot; UE_proc.frame_tx = frame; - // --------- setting parameters for gNB -------- - /* - rel15_ul->rnti = n_rnti; - rel15_ul->ulsch_pdu_rel15.start_rb = start_rb; - rel15_ul->ulsch_pdu_rel15.number_rbs = nb_rb; - rel15_ul->ulsch_pdu_rel15.start_symbol = start_symbol; - rel15_ul->ulsch_pdu_rel15.number_symbols = nb_symb_sch; - rel15_ul->ulsch_pdu_rel15.length_dmrs = length_dmrs; - rel15_ul->ulsch_pdu_rel15.Qm = mod_order; - rel15_ul->ulsch_pdu_rel15.mcs = Imcs; - rel15_ul->ulsch_pdu_rel15.rv = 0; - rel15_ul->ulsch_pdu_rel15.ndi = 0; - rel15_ul->ulsch_pdu_rel15.n_layers = precod_nbr_layers; - rel15_ul->ulsch_pdu_rel15.R = code_rate; - /////////////////////////////////////////////////// - */ - UL_tti_req->SFN = frame; UL_tti_req->Slot = slot; UL_tti_req->n_pdus = 1; @@ -626,7 +811,7 @@ int main(int argc, char **argv) else pusch_pdu->bwp_start = ibwp_start; pusch_pdu->bwp_size = ibwp_size; - start_rb += (ibwp_start - abwp_start); + start_rb = (ibwp_start - abwp_start); printf("msg3: ibwp_size %d, abwp_size %d, ibwp_start %d, abwp_start %d\n", ibwp_size,abwp_size,ibwp_start,abwp_start); } @@ -635,6 +820,7 @@ int main(int argc, char **argv) pusch_pdu->bwp_size = abwp_size; } + pusch_pdu->pusch_data.tb_size = TBS/8; pusch_pdu->pdu_bit_map = pdu_bit_map; pusch_pdu->rnti = n_rnti; pusch_pdu->mcs_index = Imcs; @@ -645,11 +831,11 @@ int main(int argc, char **argv) pusch_pdu->data_scrambling_id = *scc->physCellId; pusch_pdu->nrOfLayers = 1; pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << start_symbol; - pusch_pdu->dmrs_config_type = 0; + pusch_pdu->dmrs_config_type = dmrs_config_type; pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; pusch_pdu->scid = 0; pusch_pdu->dmrs_ports = 1; - pusch_pdu->num_dmrs_cdm_grps_no_data = 1; + pusch_pdu->num_dmrs_cdm_grps_no_data = msg3_flag == 0 ? 1 : 2; pusch_pdu->resource_alloc = 1; pusch_pdu->rb_start = start_rb; pusch_pdu->rb_size = nb_rb; @@ -658,9 +844,9 @@ int main(int argc, char **argv) pusch_pdu->uplink_frequency_shift_7p5khz = 0; pusch_pdu->start_symbol_index = start_symbol; pusch_pdu->nr_of_symbols = nb_symb_sch; - pusch_pdu->pusch_data.rv_index = 0; + pusch_pdu->pusch_data.rv_index = rv_index; pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 0; + pusch_pdu->pusch_data.new_data_indicator = trial & 0x1; pusch_pdu->pusch_data.num_cb = 0; pusch_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density; pusch_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density; @@ -678,7 +864,17 @@ int main(int argc, char **argv) scheduled_response.slot = slot; scheduled_response.dl_config = NULL; scheduled_response.ul_config = &ul_config; - scheduled_response.dl_config = NULL; + scheduled_response.tx_request = &tx_req; + scheduled_response.tx_request->tx_request_body = &tx_req_body; + + // Config UL TX PDU + tx_req.slot = slot; + tx_req.sfn = frame; + // tx_req->tx_config // TbD + tx_req.number_of_pdus = 1; + tx_req_body.pdu_length = TBS/8; + tx_req_body.pdu_index = 0; + tx_req_body.pdu = &ulsch_input_buffer[0]; ul_config.slot = slot; ul_config.number_pdus = 1; @@ -690,38 +886,30 @@ int main(int argc, char **argv) ul_config.ul_config_list[0].pusch_config_pdu.nr_of_symbols = nb_symb_sch; ul_config.ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol; ul_config.ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = l_prime_mask << start_symbol; - ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type = 0; + ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type; ul_config.ul_config_list[0].pusch_config_pdu.mcs_index = Imcs; ul_config.ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table; - ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; - ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0; - ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = 0; + ul_config.ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = msg3_flag == 0 ? 1 : 2; ul_config.ul_config_list[0].pusch_config_pdu.nrOfLayers = precod_nbr_layers; + ul_config.ul_config_list[0].pusch_config_pdu.absolute_delta_PUSCH = 0; + + ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.tb_size = TBS; + ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = trial & 0x1; + ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index; ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_pid; + ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t)); ul_config.ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - //there are plenty of other parameters that we don't seem to be using for now. e.g. - ul_config.ul_config_list[0].pusch_config_pdu.absolute_delta_PUSCH = 0; - - nb_re_dmrs = ((ul_config.ul_config_list[0].pusch_config_pdu.dmrs_config_type == pusch_dmrs_type1) ? 6 : 4); - - available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, number_dmrs_symbols, mod_order, 1); - TBS = nr_compute_tbs(mod_order, code_rate, nb_rb, nb_symb_sch, nb_re_dmrs * number_dmrs_symbols, 0, 0, precod_nbr_layers); - pusch_pdu->pusch_data.tb_size = TBS>>3; - ul_config.ul_config_list[0].pusch_config_pdu.pusch_data.tb_size = TBS; nr_fill_ulsch(gNB,frame,slot,pusch_pdu); - int slot_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);// - (int)(800*factor); - int slot_length = slot_offset - frame_parms->get_samples_slot_timestamp(slot-1,frame_parms,0); for (int i=0;i<(TBS>>3);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff; double scale = 1; if (input_fd == NULL) { - if (SNR==snr0) { // set FAPI parameters for UE, put them in the scheduled response and call nr_ue_scheduled_response(&scheduled_response); @@ -746,57 +934,46 @@ int main(int argc, char **argv) txlev_float = (double)txlev/scale; // output of signal_energy is fixed point representation - //AWGN - } } else n_trials = 1; + if (input_fd == NULL ) { - sigma_dB = 10*log10(txlev_float)-SNR; - sigma = pow(10,sigma_dB/10); - printf("txlev_float %f, sigma_dB %f\n",10*log10(txlev_float),sigma_dB); + sigma_dB = N0; + sigma = pow(10,sigma_dB/10); - n_errors = 0; - n_false_positive = 0; + tx_gain = sqrt(pow(10.0,.1*(N0+SNR))/txlev_float); + if(n_trials==1) printf("txlev_float %f, sigma_dB %f, tx_gain %f tx_offset %d, slot_offset %d\n",10*log10(txlev_float),sigma_dB,tx_gain,tx_offset,slot_offset); - errors_scrambling = 0; - errors_decoding = 0; - - int error_flag; - for (trial = 0; trial < n_trials; trial++) { - - error_flag = 0; - //---------------------------------------------------------- - //------------------------ add noise ----------------------- - //---------------------------------------------------------- - if (input_fd == NULL ) { - for (i=0; inb_antennas_rx; ap++) { - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((double)(((int16_t *)&UE->common_vars.txdata[ap][slot_offset])[(i<<1)])/sqrt(scale) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((double)(((int16_t *)&UE->common_vars.txdata[ap][slot_offset])[(i<<1)+1])/sqrt(scale) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); - } + for (i=0; icommon_vars.txdata[aa][slot_offset]))[(i<<1)]); + s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]); } } - else { - AssertFatal(frame_parms->nb_antennas_rx == 1, "nb_ant != 1\n"); - // 800 samples is N_TA_OFFSET for FR1 @ 30.72 Ms/s, - AssertFatal(frame_parms->subcarrier_spacing==30000,"only 30 kHz for file input for now (%d)\n",frame_parms->subcarrier_spacing); - double factor = 1; - if (openair0_cfg[0].threequarter_fs== 1) factor =.75; - int ta_offset=1600; - if (N_RB_DL <217) ta_offset=800; - else if (N_RB_DL < 106) ta_offset = 400; + - fread((void*)&gNB->common_vars.rxdata[0][slot_offset], - sizeof(int16_t), - slot_length<<1, - input_fd); - for (int i=0;i<16;i+=2) printf("slot_offset %d : %d,%d\n", - slot_offset, - ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i], - ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]); - fclose(input_fd); + if (UE2gNB->max_Doppler == 0) { + multipath_channel(UE2gNB,s_re,s_im,r_re,r_im, + slot_length,0,(n_trials==1)?1:0); + } else { + multipath_tv_channel(UE2gNB,s_re,s_im,r_re,r_im, + 2*slot_length,0); } + for (i=0; inb_antennas_rx; ap++) { + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((tx_gain*r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((tx_gain*r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); + /* Add phase noise if enabled */ + if (pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + phase_noise(ts, &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)], + &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1]); + } + } + } + + } + //////////////////////////////////////////////////////////// //---------------------------------------------------------- @@ -808,111 +985,162 @@ int main(int argc, char **argv) start_meas(&gNB->phy_proc_rx); phy_procedures_gNB_common_RX(gNB, frame, slot); - if (n_trials==1) { - LOG_M("rxsig0.m","rx0",&gNB->common_vars.rxdata[0][0],frame_parms->samples_per_subframe*10,1,1); + phy_procedures_gNB_uespec_RX(gNB, frame, slot); + + if (n_trials==1 && round==0) { + LOG_M("rxsig0.m","rx0",&gNB->common_vars.rxdata[0][slot_offset],slot_length,1,1); LOG_M("rxsigF0.m","rxsF0",gNB->common_vars.rxdataF[0]+start_symbol*frame_parms->ofdm_symbol_size,nb_symb_sch*frame_parms->ofdm_symbol_size,1,1); } - phy_procedures_gNB_uespec_RX(gNB, frame, slot); - if (n_trials == 1) { + + + if (n_trials == 1 && round==0) { +#ifdef __AVX2__ + int off = ((nb_rb&1) == 1)? 4:0; +#else + int off = 0; +#endif + LOG_M("rxsigF0_ext.m","rxsF0_ext", - &gNB->pusch_vars[0]->rxdataF_ext[0][(start_symbol+1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size,1,1); + &gNB->pusch_vars[0]->rxdataF_ext[0][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); LOG_M("chestF0.m","chF0", &gNB->pusch_vars[0]->ul_ch_estimates[0][start_symbol*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); LOG_M("chestF0_ext.m","chF0_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(start_symbol+1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size,1,1); + &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); LOG_M("rxsigF0_comp.m","rxsF0_comp", - &gNB->pusch_vars[0]->rxdataF_comp[0][(start_symbol+1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size,1,1); + &gNB->pusch_vars[0]->rxdataF_comp[0][start_symbol*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("rxsigF0_llr.m","rxsF0_llr", + &gNB->pusch_vars[0]->llr[0],(nb_symb_sch-1)*NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order,1,0); } start_meas(&gNB->phy_proc_rx); //////////////////////////////////////////////////////////// - + if (gNB->ulsch[0][0]->last_iteration_cnt >= gNB->ulsch[0][0]->max_ldpc_iterations+1) { error_flag = 1; - n_errors++; + n_errors[round]++; + crc_status = 1; + } else { + crc_status = 0; } - + if(n_trials==1) printf("end of round %d rv_index %d\n",round, rv_index); + //---------------------------------------------------------- //----------------- count and print errors ----------------- //---------------------------------------------------------- - for (i = 0; i < available_bits; i++) { - - if(((ulsch_ue[0]->g[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) || - ((ulsch_ue[0]->g[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0))) - { - /*if(errors_scrambling == 0) - printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/ - errors_scrambling++; - } + if ((pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) && (SNR==snr0) && (trial==0) && (round==0)) { + ptrs_symbols = 0; + for (int i = pusch_pdu->start_symbol_index; i < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; i++){ + ptrs_symbols += ((gNB->pusch_vars[UE_id]->ptrs_symbols) >> i) & 1; + } + /* 2*5*(50/2), for RB = 50,K = 2 for 5 OFDM PTRS symbols */ + available_bits -= 2 * ptrs_symbols * ((nb_rb + ptrs_freq_density - 1) /ptrs_freq_density); + printf("After PTRS subtraction available_bits are : %u \n", available_bits); } - if (errors_scrambling > 0) { - if (n_trials==1) - printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in unscrambling = %u\n" "\x1B[0m", frame, trial, errors_scrambling); - } - - for (i = 0; i < TBS; i++) { - - estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); - test_input_bit[i] = (ulsch_ue[0]->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); - - if (estimated_output_bit[i] != test_input_bit[i]) { - /*if(errors_decoding == 0) - printf("\x1B[34m""[frame %d][trial %d]\t1st bit in error in decoding = %d\n" "\x1B[0m", frame, trial, i);*/ - errors_decoding++; - } - } - if (n_trials == 1) { - for (int r=0;rharq_processes[harq_pid]->C;r++) - for (int i=0;iharq_processes[harq_pid]->K>>3;i++) { - if ((ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]) != 0) printf("************"); - printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r, - i,ulsch_ue[0]->harq_processes[harq_pid]->c[r][i], - i,ulsch_gNB->harq_processes[harq_pid]->c[r][i], - ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]); + for (i = 0; i < available_bits; i++) { + + if(((ulsch_ue[0]->g[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) || + ((ulsch_ue[0]->g[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0))) + { + /*if(errors_scrambling == 0) + printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/ + errors_scrambling[round]++; } } - if (errors_decoding > 0 && error_flag == 0) { - n_false_positive++; - if (n_trials==1) - printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in decoding = %u\n" "\x1B[0m", frame, trial, errors_decoding); - } - } // trial loop + round++; - printf("*****************************************\n"); - printf("SNR %f: n_errors (negative CRC) = %d/%d, false_positive %d/%d, errors_scrambling %u/%u\n", SNR, n_errors, n_trials, n_false_positive, n_trials, errors_scrambling, available_bits*n_trials); - printf("\n"); - printf("SNR %f: Channel BLER %e, Channel BER %e\n", SNR,(double)n_errors/n_trials,(double)errors_scrambling/available_bits/n_trials); - printf("*****************************************\n"); - printf("\n"); - - if (print_perf==1) { - printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); - printStatIndent(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); - printStatIndent(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); - printStatIndent(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); - printStatIndent(&gNB->ulsch_llr_stats,"ULSCH llr computation"); - printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); - printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); - printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); - printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); - printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); - printf("\n"); - } - - if(n_trials==1) - break; - - if ((float)n_errors/(float)n_trials <= target_error_rate) { - printf("*************\n"); - printf("PUSCH test OK\n"); - printf("*************\n"); - break; - } + } // round + + if (n_trials == 1 && errors_scrambling[0] > 0) { + printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in unscrambling = %u\n" "\x1B[0m", frame, trial, errors_scrambling[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] = (ulsch_ue[0]->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); + + if (estimated_output_bit[i] != test_input_bit[i]) { + /*if(errors_decoding == 0) + printf("\x1B[34m""[frame %d][trial %d]\t1st bit in error in decoding = %d\n" "\x1B[0m", frame, trial, i);*/ + errors_decoding++; + } + } + if (n_trials == 1) { + for (int r=0;rharq_processes[harq_pid]->C;r++) + for (int i=0;iharq_processes[harq_pid]->K>>3;i++) { + /*if ((ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]) != 0) printf("************"); + printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r, + i,ulsch_ue[0]->harq_processes[harq_pid]->c[r][i], + i,ulsch_gNB->harq_processes[harq_pid]->c[r][i], + ulsch_ue[0]->harq_processes[harq_pid]->c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]);*/ + } + } + if (errors_decoding > 0 && error_flag == 0) { + n_false_positive++; + if (n_trials==1) + printf("\x1B[31m""[frame %d][trial %d]\tnumber of errors in decoding = %u\n" "\x1B[0m", frame, trial, errors_decoding); + } + roundStats[snrRun] += ((float)round); + if (!crc_status) effRate += ((float)TBS)/round; + } // trial loop + + roundStats[snrRun]/=((float)n_trials); + effRate /= n_trials; + + printf("*****************************************\n"); + printf("SNR %f: n_errors (%d/%d,%d/%d,%d/%d,%d/%d) (negative CRC), false_positive %d/%d, errors_scrambling (%u/%u,%u/%u,%u/%u,%u/%u\n", SNR, n_errors[0], round_trials[0],n_errors[1], round_trials[1],n_errors[2], round_trials[2],n_errors[3], round_trials[3], n_false_positive, n_trials, errors_scrambling[0],available_bits*n_trials,errors_scrambling[1],available_bits*n_trials,errors_scrambling[2],available_bits*n_trials,errors_scrambling[3],available_bits*n_trials); + printf("\n"); + printf("SNR %f: Channel BLER (%e,%e,%e,%e), Channel BER (%e,%e,%e,%e) Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", + SNR, + (double)n_errors[0]/round_trials[0], + (double)n_errors[1]/round_trials[0], + (double)n_errors[2]/round_trials[0], + (double)n_errors[3]/round_trials[0], + (double)errors_scrambling[0]/available_bits/round_trials[0], + (double)errors_scrambling[1]/available_bits/round_trials[0], + (double)errors_scrambling[2]/available_bits/round_trials[0], + (double)errors_scrambling[3]/available_bits/round_trials[0], + roundStats[snrRun],effRate,effRate/TBS*100,TBS); + + dump_pusch_stats(gNB); + + printf("*****************************************\n"); + printf("\n"); + + if (print_perf==1) { + printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); + printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time"); + printStatIndent2(&gNB->ulsch_channel_estimation_stats,"ULSCH channel estimation time"); + printStatIndent2(&gNB->ulsch_ptrs_processing_stats,"ULSCH PTRS Processing time"); + printStatIndent2(&gNB->ulsch_rbs_extraction_stats,"ULSCH rbs extraction time"); + printStatIndent2(&gNB->ulsch_channel_compensation_stats,"ULSCH channel compensation time"); + printStatIndent2(&gNB->ulsch_mrc_stats,"ULSCH mrc computation"); + printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); + printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); + printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); + printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); + printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); + printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); + printf("\n"); + } + + if(n_trials==1) + break; + + if ((float)n_errors[0]/(float)n_trials <= target_error_rate) { + printf("*************\n"); + printf("PUSCH test OK\n"); + printf("*************\n"); + break; + } + + snrRun++; + n_errs = n_errors[0]; } // SNR loop printf("\n"); @@ -928,5 +1156,5 @@ int main(int argc, char **argv) if (scg_fd) fclose(scg_fd); - return (n_errors); + return (n_errs); } 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 a93f0d48f3..cc8c62a36d 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 @@ -115,6 +115,11 @@ int ue_query_mch(module_id_t Mod_id, uint8_t CC_id, uint32_t frame, sub_frame_t subframe, uint8_t eNB_index, uint8_t * sync_area, uint8_t * mcch_active){ return(0);} + +int ue_query_mch_fembms(module_id_t Mod_id, uint8_t CC_id, uint32_t frame, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t * sync_area, uint8_t * mcch_active){ return(0);} + void dl_phy_sync_success(module_id_t module_idP, frame_t frameP, unsigned char eNB_index, uint8_t first_sync){} diff --git a/openair1/SIMULATION/TOOLS/channel_sim.c b/openair1/SIMULATION/TOOLS/channel_sim.c index c5628fbcef..81949f40e6 100644 --- a/openair1/SIMULATION/TOOLS/channel_sim.c +++ b/openair1/SIMULATION/TOOLS/channel_sim.c @@ -180,7 +180,7 @@ void do_DL_sig(sim_t *sim, //RU2UE[eNB_id][UE_id]->path_loss_dB = 0; multipath_channel(sim->RU2UE[ru_id][UE_id][CC_id],s_re,s_im,r_re0,r_im0, - length,hold_channel); + length,hold_channel,0); #ifdef DEBUG_SIM rx_pwr = signal_energy_fp2(sim->RU2UE[ru_id][UE_id][CC_id]->ch[0], sim->RU2UE[ru_id][UE_id][CC_id]->channel_length)*sim->RU2UE[ru_id][UE_id][CC_id]->channel_length; @@ -394,7 +394,7 @@ void do_UL_sig(sim_t *sim, multipath_channel(sim->UE2RU[UE_id][ru_id][CC_id],s_re,s_im,r_re0,r_im0, - frame_parms->samples_per_tti,hold_channel); + frame_parms->samples_per_tti,hold_channel,0); rx_pwr = signal_energy_fp2(sim->UE2RU[UE_id][ru_id][CC_id]->ch[0], diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index 70227c8e8d..683526a8f0 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -44,7 +44,8 @@ void multipath_channel(channel_desc_t *desc, double rx_sig_re[2][30720*2], double rx_sig_im[2][30720*2], uint32_t length, - uint8_t keep_channel) + uint8_t keep_channel, + int log_channel) { int i,ii,j,l; @@ -150,7 +151,8 @@ void multipath_channel(channel_desc_t *desc, double *rx_sig_re[2], double *rx_sig_im[2], uint32_t length, - uint8_t keep_channel) + uint8_t keep_channel, + int log_channel) { int i,ii,j,l; @@ -196,16 +198,21 @@ void multipath_channel(channel_desc_t *desc, rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y); rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y); + if (i==0 && log_channel == 1) { + printf("channel[%d][%d][%d] = %f dB (%e,%e)\n",ii,j,l,10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].x,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].y,2.0)), + desc->ch[ii+(j*desc->nb_rx)][l].x, + desc->ch[ii+(j*desc->nb_rx)][l].y); + } } //l } // j rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss; rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss; - /* - if ((ii==0)&&((i%32)==0)) { - printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); - } - */ + + /* if ((ii==0)&&((i%32)==0)) { + printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); + }*/ + //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]); diff --git a/openair1/SIMULATION/TOOLS/phase_noise.c b/openair1/SIMULATION/TOOLS/phase_noise.c new file mode 100644 index 0000000000..f243a09c59 --- /dev/null +++ b/openair1/SIMULATION/TOOLS/phase_noise.c @@ -0,0 +1,42 @@ +/* + * 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 "sim.h" + + +/* linear phase noise model */ +void phase_noise(double ts, int16_t * InRe, int16_t * InIm) +{ + double fd = 300;//0.01*30000 + static double i=0; + double real, imag,x ,y; + i++; + real = cos(fd * 2 * M_PI * i * ts); + imag = sin (fd * 2 * M_PI * i * ts); + x = ((real * (double)InRe[0]) - (imag * (double)InIm[0])) ; + y= ((real * (double)InIm[0]) + (imag * (double)InRe[0])) ; + InRe[0]= (int16_t)(x); + InIm[0]= (int16_t)(y); +} diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 41d8551e75..8c063fadc0 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -45,8 +45,12 @@ static mapping channelmod_names[] = { }; static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt); +static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt); +static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt); static telnetshell_cmddef_t channelmod_cmdarray[] = { - {"show","",channelmod_show_cmd}, + {"help","",channelmod_print_help}, + {"show","",channelmod_show_cmd}, + {"modify"," ",channelmod_modify_cmd}, {"","",NULL}, }; @@ -56,14 +60,15 @@ static telnetshell_vardef_t channelmod_vardef[] = { static double snr_dB=25; static double sinr_dB=0; - +static unsigned int max_chan; +static channel_desc_t** defined_channels; void fill_channel_desc(channel_desc_t *chan_desc, uint8_t nb_tx, uint8_t nb_rx, uint8_t nb_taps, uint8_t channel_length, double *amps, - double *delays, + double *delays, struct complex **R_sqrt, double Td, double sampling_rate, @@ -88,6 +93,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, if (delays==NULL) { chan_desc->delays = (double *) malloc(nb_taps*sizeof(double)); + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_DELAY ; delta_tau = Td/nb_taps; for (i=0; iR_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_NTAPS ; for (i = 0; iR_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); - + chan_desc->R_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -140,7 +145,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, } } else { chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); - + for (i = 0; iR_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; @@ -170,9 +175,226 @@ void fill_channel_desc(channel_desc_t *chan_desc, double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58}; double mbsfn_amps_dB[] = {0,-1.5,-1.4,-3.6,-0.6,-7.0,-10,-11.5,-11.4,-13.6,-10.6,-17.0,-20,-21.5,-21.4,-23.6,-20.6,-27}; -double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; +double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; double scm_c_amps_dB[] = {0.00, -2.22, -3.98, -1.86, -4.08, -5.84, -1.08, -3.30, -5.06, -9.08, -11.30, -13.06, -15.14, -17.36, -19.12, -20.64, -22.85, -24.62}; +double tdl_a_delays[] = {0.0000, + 0.3819, + 0.4025, + 0.5868, + 0.4610, + 0.5375, + 0.6708, + 0.5750, + 0.7618, + 1.5375, + 1.8978, + 2.2242, + 2.1718, + 2.4942, + 2.5119, + 3.0582, + 4.0810, + 4.4579, + 4.5695, + 4.7966, + 5.0066, + 5.3043, + 9.6586}; +double tdl_a_amps_dB[] = {-13.4, + 0, + -2.2, + -4, + -6, + -8.2, + -9.9, + -10.5, + -7.5, + -15.9, + -6.6, + -16.7, + -12.4, + -15.2, + -10.8, + -11.3, + -12.7, + -16.2, + -18.3, + -18.9, + -16.6, + -19.9, + -29.7}; +#define TDL_A_PATHS 23 + +double tdl_b_delays[] = {0.0000, + 0.1072, + 0.2155, + 0.2095, + 0.2870, + 0.2986, + 0.3752, + 0.5055, + 0.3681, + 0.3697, + 0.5700, + 0.5283, + 1.1021, + 1.2756, + 1.5474, + 1.7842, + 2.0169, + 2.8294, + 3.0219, + 3.6187, + 4.1067, + 4.2790, + 4.7834}; + +double tdl_b_amps_dB[] = {0, + -2.2, + -4, + -3.2, + -9.8, + -1.2, + -3.4, + -5.2, + -7.6, + -3, + -8.9, + -9, + -4.8, + -5.7, + -7.5, + -1.9, + -7.6, + -12.2, + -9.8, + -11.4, + -14.9, + -9.2, + -11.3}; +#define TDL_B_PATHS 23 + +double tdl_c_delays[] = {0, + 0.2099, + 0.2219, + 0.2329, + 0.2176, + 0.6366, + 0.6448, + 0.6560, + 0.6584, + 0.7935, + 0.8213, + 0.9336, + 1.2285, + 1.3083, + 2.1704, + 2.7105, + 4.2589, + 4.6003, + 5.4902, + 5.6077, + 6.3065, + 6.6374, + 7.0427, + 8.6523}; + +double tdl_c_amps_dB[] = {-4.4, + -1.2, + -3.5, + -5.2, + -2.5, + 0, + -2.2, + -3.9, + -7.4, + -7.1, + -10.7, + -11.1, + -5.1, + -6.8, + -8.7, + -13.2, + -13.9, + -13.9, + -15.8, + -17.1, + -16, + -15.7, + -21.6, + -22.8}; +#define TDL_C_PATHS 24 + +double tdl_d_delays[] = {//0, + 0, + 0.035, + 0.612, + 1.363, + 1.405, + 1.804, + 2.596, + 1.775, + 4.042, + 7.937, + 9.424, + 9.708, + 12.525}; + +double tdl_d_amps_dB[] = {//-0.2, +//-13.5, + -.00147, + -18.8, + -21, + -22.8, + -17.9, + -20.1, + -21.9, + -22.9, + -27.8, + -23.6, + -24.8, + -30.0, + -27.7}; + +#define TDL_D_PATHS 13 +#define TDL_D_RICEAN_FACTOR .046774 + +double tdl_e_delays[] = {0, + 0.5133, + 0.5440, + 0.5630, + 0.5440, + 0.7112, + 1.9092, + 1.9293, + 1.9589, + 2.6426, + 3.7136, + 5.4524, + 12.0034, + 20.6519}; + +double tdl_e_amps_dB[] = {//-0.03, + //-22.03, + -.00433, + -15.8, + -18.1, + -19.8, + -22.9, + -22.4, + -18.6, + -20.8, + -22.6, + -22.3, + -25.6, + -20.2, + -29.8, + -29.2}; + +#define TDL_E_PATHS 14 +#define TDL_E_RICEAN_FACTOR 0.0063096 + double epa_delays[] = { 0,.03,.07,.09,.11,.19,.41}; double epa_amps_dB[] = {0.0,-1.0,-2.0,-3.0,-8.0,-17.2,-20.8}; @@ -277,14 +499,28 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, SCM_t channel_model, double sampling_rate, double channel_bandwidth, + double DS_TDL, double forgetting_factor, int32_t channel_offset, double path_loss_dB) { - channel_desc_t *chan_desc = (channel_desc_t *)malloc(sizeof(channel_desc_t)); + channel_desc_t *chan_desc = (channel_desc_t *)calloc(1,sizeof(channel_desc_t)); + for(int i=0; ichan_idx=i; + break; + } + else { + AssertFatal(i<(max_chan-1), + "No more channel descriptors available, increase channelmod.max_chan parameter above %u\n",max_chan); + } + } uint16_t i,j; double sum_amps; double aoa,ricean_factor,Td,maxDoppler; + int channel_length,nb_taps; + chan_desc->modelid = channel_model; chan_desc->nb_tx = nb_tx; chan_desc->nb_rx = nb_rx; chan_desc->sampling_rate = sampling_rate; @@ -296,6 +532,11 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ip = 0.0; LOG_I(OCM,"Channel Model (inside of new_channel_desc_scm)=%d\n\n", channel_model); + int tdl_paths=0; + double tdl_ricean_factor = 1; + double *tdl_amps_dB; + double *tdl_delays; + switch (channel_model) { case SCM_A: LOG_W(OCM,"channel model not yet supported\n"); @@ -313,7 +554,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -351,9 +592,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; } else { + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - + for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -372,7 +614,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -410,6 +652,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; } else { + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -423,6 +666,100 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } break; + + case TDL_A: + case TDL_B: + case TDL_C: + case TDL_D: + case TDL_E: + if (channel_model == TDL_A) { + tdl_paths=TDL_A_PATHS; + tdl_delays=tdl_a_delays; + tdl_amps_dB=tdl_a_amps_dB; + }else if (channel_model == TDL_B) { + tdl_paths=TDL_B_PATHS; + tdl_delays=tdl_b_delays; + tdl_amps_dB=tdl_b_amps_dB; + } + else if (channel_model == TDL_C) { + tdl_paths=TDL_C_PATHS; + tdl_delays=tdl_c_delays; + tdl_amps_dB=tdl_c_amps_dB; + printf("Initializing TDL_C channel with %d paths\n",TDL_C_PATHS); + } else if (channel_model == TDL_D) { + tdl_paths=TDL_D_PATHS; + tdl_delays=tdl_d_delays; + tdl_amps_dB=tdl_d_amps_dB; + tdl_ricean_factor = TDL_D_RICEAN_FACTOR; + } else if (channel_model == TDL_E) { + tdl_paths=TDL_E_PATHS-1; + tdl_delays=tdl_e_delays+1; + tdl_amps_dB=tdl_e_amps_dB; + tdl_ricean_factor = TDL_E_RICEAN_FACTOR; + } + + int tdl_pathsby3 = tdl_paths/3; + if ((tdl_paths%3)>0) tdl_pathsby3++; + + chan_desc->nb_taps = tdl_paths; + chan_desc->Td = tdl_delays[tdl_paths-1]*DS_TDL; + printf("last path (%d) at %f * %e = %e\n",tdl_paths-1,tdl_delays[tdl_paths-1],DS_TDL,chan_desc->Td); + chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); + printf("TDL : %f Ms/s, nb_taps %d, Td %e, channel_length %d\n",chan_desc->sampling_rate,tdl_paths,chan_desc->Td,chan_desc->channel_length); + sum_amps = 0; + chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); + + for (i = 0; inb_taps; i++) { + chan_desc->amps[i] = pow(10,.1*tdl_amps_dB[i]); + sum_amps += chan_desc->amps[i]; + } + + for (i = 0; inb_taps; i++) { + chan_desc->amps[i] /= sum_amps; + tdl_delays[i] *= DS_TDL; + } + chan_desc->delays = tdl_delays; + chan_desc->ricean_factor = tdl_ricean_factor; + chan_desc->aoa = 0; + chan_desc->random_aoa = 0; + chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); + chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); + chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + + for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + + for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + + for (i = 0; inb_taps; i++) + chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + + chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + + if (nb_tx==2 && nb_rx==2) { + for (i = 0; i<(tdl_pathsby3); i++) + chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + } else if (nb_tx==2 && nb_rx==1) { + for (i = 0; i<(tdl_pathsby3); i++) + chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + } else if (nb_tx==1 && nb_rx==2) { + for (i = 0; i<(tdl_pathsby3); i++) + chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + } else { + for (i = 0; i<(tdl_pathsby3); i++) { + chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + + for (j = 0; jR_sqrt[i][j].x = 1.0; + chan_desc->R_sqrt[i][j].y = 0.0; + } + + LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); + } + } + + break; case EPA: chan_desc->nb_taps = 7; @@ -430,7 +767,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -449,7 +786,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); - + for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); @@ -463,7 +800,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; } else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -484,7 +821,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -530,7 +867,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } }*/ - break; + break; case EPA_high: chan_desc->nb_taps = 7; @@ -538,7 +875,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -592,7 +929,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -646,7 +983,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -679,8 +1016,8 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; } else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); - - for (i = 0; i<6; i++) { + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); for (j = 0; jchannel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -733,7 +1070,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; } else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -754,7 +1091,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -781,7 +1118,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -1292,10 +1629,37 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->nb_paths = 10; return(chan_desc); } - + void free_channel_desc_scm(channel_desc_t *ch) { // Must be made cleanly, a lot of leaks... - free(ch); + defined_channels[ch->chan_idx]=NULL; + if(ch->free_flags&CHANMODEL_FREE_AMPS) + free(ch->amps); + for (int i = 0; inb_tx*ch->nb_rx; i++) { + free(ch->ch[i]); + free(ch->chF[i]); + } + + for (int i = 0; inb_taps; i++) { + free(ch->a[i]); + } + if(ch->free_flags&CHANMODEL_FREE_DELAY) + free(ch->delays); + if(ch->free_flags&CHANMODEL_FREE_RSQRT_6) + for (int i = 0; i<6; i++) + free(ch->R_sqrt[i]); + if(ch->free_flags&CHANMODEL_FREE_RSQRT_NTAPS) + for (int i = 0; inb_taps;i++) + free(ch->R_sqrt[i]); + free(ch->R_sqrt); + free(ch->ch); + free(ch->chF); + free(ch->a); + free(ch); +} + +void set_channeldesc_owner(channel_desc_t *cdesc, uint32_t module_id) { + cdesc->module_id=module_id; } int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { @@ -1408,23 +1772,22 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0; for (l=0; lnb_taps; l++) { - if ((k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET) == 0) + if ((k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset) == 0) s = 1.0; else - s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET))/ - (M_PI*(k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET)); + s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset))/ + (M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset)); desc->ch[aarx+(aatx*desc->nb_rx)][k].x += s*desc->a[l][aarx+(aatx*desc->nb_rx)].x; desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y; - // printf("l %d : desc->ch.x %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x); + // printf("l %d : desc->ch.x %f, s %e, delay %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x,s,desc->delays[l]); } //nb_taps #ifdef DEBUG_CH - k=0; - printf("(%d,%d,%d)->(%f,%f)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].x,desc->ch[aarx+(aatx*desc->nb_rx)][k].y); + printf("(%d,%d,%d)->(%e,%e)\n",k,aarx,aatx,desc->ch[aarx+(aatx*desc->nb_rx)][k].x,desc->ch[aarx+(aatx*desc->nb_rx)][k].y); #endif - } - } //channel_length + } //channel_length + } } //aatx } //aarx @@ -1436,7 +1799,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { return (0); } - + double N_RB2sampling_rate(uint16_t N_RB) { double sampling_rate; @@ -1488,22 +1851,125 @@ double N_RB2channel_bandwidth(uint16_t N_RB) { LOG_E(PHY,"Unknown N_PRB\n"); return(-1); } - return(channel_bandwidth); +} + + +static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt ) { + prnt("channelmod commands can be used to display or modify channel models parameters\n"); + prnt("channelmod show predef: display predefined model algorithms available in oai\n"); + prnt("channelmod show current: display the currently used models in the running executable\n"); + prnt("channelmod modify : set the specified parameters in a current model to the given value\n"); + prnt(" specifies the model, the show current model command can be used to list the current models indexes\n"); + prnt(" can be one of \"riceanf\", \"aoa\", \"randaoa\", \"ploss\", \"offset\", \"forgetf\"\n"); + return CMDSTATUS_FOUND; } + +static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_t prnt) { + char *module_id_str[]=MODULEID_STR_INIT; + if (cd->module_id != 0) { + prnt("model owner: %s\n",module_id_str[cd->module_id]); + } + prnt("nb_tx: %i nb_rx: %i taps: %i bandwidth: %lf sampling: %lf\n",cd->nb_tx, cd->nb_rx, cd->nb_taps, cd->channel_bandwidth, cd->sampling_rate); + prnt("channel length: %i Max path delay: %lf ricean fact.: %lf angle of arrival: %lf (randomized:%s)\n", + cd->channel_length, cd->Td, cd->ricean_factor, cd->aoa, (cd->random_aoa?"Yes":"No")); + prnt("max Doppler: %lf path loss: %lf rchannel offset: %i forget factor; %lf\n", + cd->max_Doppler, cd->path_loss_dB, cd->channel_offset, cd->forgetting_factor); + prnt("Initial phase: %lf nb_path: %i \n", + cd->ip, cd->nb_paths); + for (int i=0; inb_taps ; i++) { + prnt("taps: %i lin. ampli. : %lf delay: %lf \n",i,cd->amps[i], cd->delays[i]); + } +} + + static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) { - for(int i=0; channelmod_names[i].name != NULL ; i++) { - prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i )); - } + char *subcmd=NULL; + int s = sscanf(buff,"%ms\n",&subcmd); - return 0; + if (s>0) { + if ( strcmp(subcmd,"predef") == 0) { + for (int i=0; channelmod_names[i].name != NULL ; i++) { + prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i )); + } + } else if ( strcmp(subcmd,"current") == 0) { + for (int i=0; i < max_chan ; i++) { + if (defined_channels[i] != NULL) { + prnt("model %i %s: \n----------------\n", i, map_int_to_str(channelmod_names,defined_channels[i]->modelid)); + display_channelmodel(defined_channels[i],debug,prnt); + } + } + } else { + channelmod_print_help(buff, debug, prnt); + } + free(subcmd); + } + return CMDSTATUS_FOUND; } -int modelid_fromname(char *modelname) { - int modelid=map_str_to_int(channelmod_names,modelname); - AssertFatal(modelid>0, - "random_channel.c: Error channel model %s unknown\n",modelname); + + +static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt) { + char *param=NULL, *value=NULL; + int cd_id= -1; + int s = sscanf(buff,"%i %ms %ms \n",&cd_id,¶m, &value); + if (cd_id<0 || cd_id >= max_chan) { + prnt("ERROR, %i: Channel model id outof range (0-%i)\n",cd_id,max_chan-1); + return CMDSTATUS_FOUND; + } + if (defined_channels[cd_id]==NULL) { + prnt("ERROR, %i: Channel model has not been set\n",cd_id); + return CMDSTATUS_FOUND; + } + + if (s==3) { + if ( strcmp(param,"riceanf") == 0) { + double dbl = atof(value); + if (dbl <0 || dbl > 1) + prnt("ERROR: ricean factor range: 0 to 1, %lf is outof range\n",dbl); + else + defined_channels[cd_id]->ricean_factor=dbl; + } else if ( strcmp(param,"aoa") == 0) { + double dbl = atof(value); + if (dbl <0 || dbl >6.28) + prnt("ERROR: angle of arrival range: 0 to 2*Pi, %lf is outof range\n",dbl); + else + defined_channels[cd_id]->aoa=dbl; + } else if ( strcmp(param,"randaoa") == 0) { + int i = atoi(value); + if (i!=0 && i!=1) + prnt("ERROR: randaoa is a boolean, must be 0 or 1\n"); + else + defined_channels[cd_id]->random_aoa=i; + } else if ( strcmp(param,"ploss") == 0) { + double dbl = atof(value); + defined_channels[cd_id]->path_loss_dB=dbl; + } else if ( strcmp(param,"offset") == 0) { + int i = atoi(value); + defined_channels[cd_id]->channel_offset=i; + } else if ( strcmp(param,"forgetf") == 0) { + double dbl = atof(value); + if (dbl <0 || dbl > 1) + prnt("ERROR: forgetting factor range: 0 to 1 (disable variation), %lf is outof range\n",dbl); + else + defined_channels[cd_id]->forgetting_factor=dbl; + } else { + prnt("ERROR: %s, unknown channel parameter\n",param); + return CMDSTATUS_FOUND; + } + display_channelmodel(defined_channels[cd_id],debug,prnt); + free(param); + free(value); + random_channel(defined_channels[cd_id],false); + } + return CMDSTATUS_FOUND; +} + +int modelid_fromname(char *modelname) { + int modelid=map_str_to_int(channelmod_names,modelname); + if (modelid < 0) + LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modelname); return modelid; } @@ -1519,6 +1985,9 @@ void init_channelmod(void) { paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC; int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION); AssertFatal(ret >= 0, "configuration couldn't be performed"); + defined_channels=calloc(max_chan,sizeof( channel_desc_t*)); + AssertFatal(defined_channels!=NULL, "couldn't allocate %u channel descriptors\n",max_chan); + /* look for telnet server, if it is loaded, add the channel modeling commands to it */ add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 6071e1e743..d2684b15c1 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -40,6 +40,16 @@ The present clause specifies several numerical functions for testing of digital #define NB_SAMPLES_CHANNEL_OFFSET 4 +typedef enum { + UNSPECIFIED_MODID=0, + RFSIMU_MODULEID=1 +} channelmod_moduleid_t; +#define MODULEID_STR_INIT {"","rfsimulator"} + +#define CHANMODEL_FREE_DELAY 1<<0 +#define CHANMODEL_FREE_RSQRT_6 1<<1 +#define CHANMODEL_FREE_RSQRT_NTAPS 1<<2 +#define CHANMODEL_FREE_AMPS 1<<3 typedef struct { ///Number of tx antennas uint8_t nb_tx; @@ -92,6 +102,14 @@ typedef struct { time_stats_t interp_time; time_stats_t interp_freq; time_stats_t convolution; + /// index in the channel descriptors array + unsigned int chan_idx; + /// id of the channel modeling algorithm + int modelid; + /// identifies channel descriptor owner (the module which created this descriptor) + channelmod_moduleid_t module_id; + /// flags to properly trigger memory free + unsigned int free_flags; } channel_desc_t; typedef struct { @@ -160,6 +178,11 @@ typedef enum { EVA, ETU, MBSFN, + TDL_A, + TDL_B, + TDL_C, + TDL_D, + TDL_E, Rayleigh8, Rayleigh1, Rayleigh1_800, @@ -190,6 +213,11 @@ typedef enum { {"EVA",EVA},\ {"ETU",ETU},\ {"MBSFN",MBSFN},\ + {"TDL_A",TDL_A},\ + {"TDL_B",TDL_B},\ + {"TDL_C",TDL_C},\ + {"TDL_D",TDL_D},\ + {"TDL_E",TDL_E},\ {"Rayleigh8",Rayleigh8},\ {"Rayleigh1",Rayleigh1},\ {"Rayleigh1_800",Rayleigh1_800},\ @@ -214,8 +242,9 @@ typedef enum { #define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n" #define CHANNELMOD_SECTION "channelmod" #define CHANNELMOD_PARAMS_DESC { \ - {"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB , defdblval:25, TYPE_DOUBLE, 0},\ - {"sinr_dB", NULL , 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\ + {"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\ + {"sinr_dB", NULL, 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\ + {"max_chan, CONFIG_HLP_MAX_CHAN", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\ } #include "platform_constants.h" @@ -243,39 +272,27 @@ typedef struct { } sim_t; -/** -\brief This routine initializes a new channel descriptor -\param nb_tx Number of TX antennas -\param nb_rx Number of RX antennas -\param nb_taps Number of taps -\param channel_length Length of the interpolated channel impulse response -\param amps Linear amplitudes of the taps (length(amps)=channel_length). The values should sum up to 1. -\param delays Delays of the taps. If delays==NULL the taps are assumed to be spaced equidistantly between 0 and t_max. -\param R_sqrt Channel correlation matrix. If R_sqrt==NULL, no channel correlation is applied. -\param Td Maximum path delay in mus. -\param BW Channel bandwidth in MHz. -\param ricean_factor Ricean factor applied to all taps. -\param aoa Anlge of arrival -\param forgetting_factor This parameter (0...1) allows for simple 1st order temporal variation -\param max_Doppler This is the maximum Doppler frequency for Jakes' Model -\param channel_offset This is a time delay to apply to channel -\param path_loss_dB This is the path loss in dB -\param random_aoa If set to 1, AoA of ricean component is randomized -*/ - -//channel_desc_t *new_channel_desc(uint8_t nb_tx,uint8_t nb_rx, uint8_t nb_taps, uint8_t channel_length, double *amps, double* delays, struct complex** R_sqrt, double Td, double BW, double ricean_factor, double aoa, double forgetting_factor, double max_Doppler, int32_t channel_offset, double path_loss_dB,uint8_t random_aoa); - channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, uint8_t nb_rx, SCM_t channel_model, - double sampling_rate, + double sampling_rate, double channel_bandwidth, + double TDL_DS, double forgetting_factor, int32_t channel_offset, double path_loss_dB); +/** +\brief free memory allocated for a model descriptor +\param ch points to the model, which cannot be used after calling this fuction +*/ +void free_channel_desc_scm(channel_desc_t *ch); - - +/** +\brief This set the ownerid of a model descriptor, can be later used to check what module created a channel model +\param cdesc points to the model descriptor +\param module_id identifies the channel model. should be define as a macro in simu.h +*/ +void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id); /** \fn void random_channel(channel_desc_t *desc) \brief This routine generates a random channel response (time domain) according to a tapped delay line model. \param desc Pointer to the channel descriptor @@ -288,7 +305,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); double rx_sig_re[2], double rx_sig_im[2], uint32_t length, - uint8_t keep_channel) + uint8_t keep_channel, + int log_channel) \brief This function generates and applys a random frequency selective random channel model. @param desc Pointer to channel descriptor @@ -298,6 +316,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag); @param rx_sig_im output signal (imaginary component) @param length Length of input signal @param keep_channel Set to 1 to keep channel constant for null-B/F +@param log_channel=1 make channel coefficients come out for first sample of input */ void multipath_channel(channel_desc_t *desc, @@ -306,7 +325,8 @@ void multipath_channel(channel_desc_t *desc, double *rx_sig_re[2], double *rx_sig_im[2], uint32_t length, - uint8_t keep_channel); + uint8_t keep_channel, + int log_channel); /* \fn double compute_pbch_sinr(channel_desc_t *desc, channel_desc_t *desc_i1, @@ -440,6 +460,14 @@ void init_channelmod(void) ; double N_RB2sampling_rate(uint16_t N_RB); double N_RB2channel_bandwidth(uint16_t N_RB); +/* Linear phase noise model */ +/*! + \brief This function produce phase noise and add to input signal + \param ts Sampling time + \param *Re *Im Real and Imag part of the signal +*/ +void phase_noise(double ts, int16_t * InRe, int16_t * InIm); + #include "targets/RT/USER/rfsim.h" void do_DL_sig(sim_t *sim, diff --git a/openair2/COMMON/m2ap_messages_def.h b/openair2/COMMON/m2ap_messages_def.h index adad70c9cc..743ca126fb 100644 --- a/openair2/COMMON/m2ap_messages_def.h +++ b/openair2/COMMON/m2ap_messages_def.h @@ -50,6 +50,7 @@ MESSAGE_DEF(M2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, m2ap_der /* M2AP -> SCTP */ MESSAGE_DEF(M2AP_MCE_SCTP_REQ , MESSAGE_PRIORITY_MED, m2ap_mce_sctp_req_t , m2ap_mce_sctp_req) +MESSAGE_DEF(M2AP_ENB_SCTP_REQ , MESSAGE_PRIORITY_MED, m2ap_enb_sctp_req_t , m2ap_enb_sctp_req) //MESSAGE_DEF(M2AP_ENB_SCTP_REQ , MESSAGE_PRIORITY_MED, m2ap_enb_setup_req_t , f1ap_enb_setup_req) /* eNB_DU application layer -> M2AP messages or CU M2AP -> RRC*/ diff --git a/openair2/COMMON/m2ap_messages_types.h b/openair2/COMMON/m2ap_messages_types.h index 501414f296..c70c50fc64 100644 --- a/openair2/COMMON/m2ap_messages_types.h +++ b/openair2/COMMON/m2ap_messages_types.h @@ -480,7 +480,7 @@ typedef struct m2ap_mbms_scheduling_information_s { uint8_t common_sf_allocation_period; uint8_t mbms_area_id; struct{ - uint8_t allocated_sf_end; + uint16_t allocated_sf_end; uint8_t data_mcs; uint8_t mch_scheduling_period; struct{ @@ -533,6 +533,15 @@ typedef struct m2ap_mce_sctp_req_s { uint32_t mce_port_for_M2C; }m2ap_mce_sctp_req_t; +typedef struct m2ap_enb_sctp_req_s { + /* The local MCE IP address to bind */ + net_ip_address_t enb_m2_ip_address; + + /* eNB port for M2C*/ + uint32_t enb_port_for_M2C; +}m2ap_enb_sctp_req_t; + + typedef struct m2ap_mbms_scheduling_information_resp_s { } m2ap_mbms_scheduling_information_resp_t; typedef struct m2ap_session_start_req_s { diff --git a/openair2/COMMON/platform_constants.h b/openair2/COMMON/platform_constants.h index 77f7e26c67..af364437b8 100644 --- a/openair2/COMMON/platform_constants.h +++ b/openair2/COMMON/platform_constants.h @@ -101,9 +101,10 @@ #define NUMBER_OF_NR_DLSCH_MAX 2//16 #define NUMBER_OF_NR_ULSCH_MAX 2//16 -#define NUMBER_OF_NR_PUCCH_MAX 2 +#define NUMBER_OF_NR_SCH_STATS_MAX 16 +#define NUMBER_OF_NR_PUCCH_MAX 16 #define NUMBER_OF_NR_SR_MAX 16 - +#define NUMBER_OF_NR_PDCCH_MAX 16 #define MAX_MANAGED_ENB_PER_MOBILE 2 #define MAX_MANAGED_GNB_PER_MOBILE 2 diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 7582de65ba..0b143fe07e 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -403,8 +403,10 @@ typedef struct NRRrcConfigurationReq_s { uint16_t mnc[PLMN_LIST_MAX_SIZE]; uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; NR_ServingCellConfigCommon_t *scc; - int ssb_SubcarrierOffset; - int pdsch_AntennaPorts; + int ssb_SubcarrierOffset; + int pdsch_AntennaPorts; + int pusch_TargetSNRx10; + int pucch_TargetSNRx10; } gNB_RrcConfigurationReq; diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 7c91e57813..1d001022d2 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -214,7 +214,7 @@ void *eNB_app_task(void *args_p) { long x2_enb_register_retry_timer_id; uint32_t m2_register_enb_pending = 0; uint32_t m2_registered_enb = 0; - long m2_enb_register_retry_timer_id; + //long m2_enb_register_retry_timer_id; MessageDef *msg_p = NULL; instance_t instance; int result; @@ -236,16 +236,11 @@ void *eNB_app_task(void *args_p) { /* Try to register each eNB with MCE each other */ if (is_m2ap_eNB_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) { //eNB_app_register_MBMS_STA(RC.rrc[0]->node_type, enb_id_start, enb_id_end); - //m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end); + m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end); - if (timer_setup (5, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, - NULL, &m2_enb_register_retry_timer_id) < 0) { - //LOG_E(ENB_APP, " Can not start eNB register retry timer, use \"sleep\" instead!\n"); - //sleep(ENB_REGISTER_RETRY_DELAY); - /* Restart the registration process */ - //registered_enb = 0; - //register_enb_pending = eNB_app_register (RC.rrc[0]->node_type,enb_id_start, enb_id_end); - } + //if (timer_setup (5, 0, TASK_ENB_APP, INSTANCE_DEFAULT, TIMER_ONE_SHOT, + // NULL, &m2_enb_register_retry_timer_id) < 0) { + //} } @@ -376,11 +371,11 @@ void *eNB_app_task(void *args_p) { } } /* if (EPC_MODE_ENABLED) */ - if(TIMER_HAS_EXPIRED (msg_p).timer_id == m2_enb_register_retry_timer_id) { - - LOG_I(ENB_APP, " Received %s: timer_id %ld M2 register\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id); - m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end); - } +// if(TIMER_HAS_EXPIRED (msg_p).timer_id == m2_enb_register_retry_timer_id) { +// +// LOG_I(ENB_APP, " Received %s: timer_id %ld M2 register\n", ITTI_MSG_NAME (msg_p), TIMER_HAS_EXPIRED(msg_p).timer_id); +// m2_register_enb_pending = eNB_app_register_m2 (enb_id_start, enb_id_end); +// } break; diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 1d189832b4..4c6a7885c3 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -3052,7 +3052,8 @@ void configure_du_mac(int inst) { (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL ); } diff --git a/openair2/ENB_APP/flexran_agent_extern.h b/openair2/ENB_APP/flexran_agent_extern.h index 5f17cf4841..2a5930e1a8 100644 --- a/openair2/ENB_APP/flexran_agent_extern.h +++ b/openair2/ENB_APP/flexran_agent_extern.h @@ -44,8 +44,6 @@ AGENT_PHY_xface *flexran_agent_get_phy_xface(mid_t mod_id); extern AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]; #define flexran_agent_get_mac_xface(mod_id) (agent_mac_xface[mod_id]) -/* Control module interface for the communication of the RRC Control Module with the agent */ - /* Control module interface for the communication of the RRC Control Module with the agent */ // AGENT_RRC_xface *flexran_agent_get_rrc_xface(mid_t mod_id); extern AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB]; diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index fb9450728b..6953588818 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -306,7 +306,8 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL ); break; } // case @@ -480,7 +481,8 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL ); } diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index bc4c4cf9d9..231aeb34f4 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -38,8 +38,7 @@ /* cell configuration section name */ #define GNB_CONFIG_STRING_GNB_LIST "gNBs" -#define GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET "ssb_SubcarrierOffset" -#define GNB_CONFIG_STRING_PDSCHANTENNAPORTS "pdsch_AntennaPorts" + #define GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON "servingCellConfigCommon" #define GNB_CONFIG_STRING_PHYSCELLID "physCellId" #define GNB_CONFIG_STRING_NTIMINGADVANCEOFFSET "n_TimingAdvanceOffset" @@ -223,9 +222,6 @@ #define GNB_CONFIG_DLCARRIERBANDWIDTH_IDX 10 -#define SSBPARAMS_DESC {{GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET,NULL,0,iptr:&ssb_SubcarrierOffset,defintval:0,TYPE_INT,0}} -#define PDSCHANTENNAPARAMS_DESC {{GNB_CONFIG_STRING_PDSCHANTENNAPORTS,NULL,0,iptr:&pdsch_AntennaPorts,defintval:1,TYPE_INT,0}} - #define SCCPARAMS_DESC(scc) { \ {GNB_CONFIG_STRING_PHYSCELLID,NULL,0,i64ptr:scc->physCellId,defint64val:0,TYPE_INT64,0/*0*/}, \ {GNB_CONFIG_STRING_NTIMINGADVANCEOFFSET,NULL,0,i64ptr:scc->n_TimingAdvanceOffset,defint64val:NR_ServingCellConfigCommon__n_TimingAdvanceOffset_n0,TYPE_INT64,0/*1*/},\ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index d8e00edf2d..540a503921 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -520,17 +520,11 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(NR_ServingCellConfigCommon_t)); - int ssb_SubcarrierOffset = 31; - int pdsch_AntennaPorts = 1; uint64_t ssb_bitmap=0xff; memset((void*)scc,0,sizeof(NR_ServingCellConfigCommon_t)); prepare_scc(scc); paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc); paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; - paramdef_t SSBsParams[] = SSBPARAMS_DESC; - paramlist_def_t SSBsParamList = {GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET, NULL, 0}; - paramdef_t PDSCHANTENNAParams[] = PDSCHANTENNAPARAMS_DESC; - paramlist_def_t PDSCHANTENNAParamList = {GNB_CONFIG_STRING_PDSCHANTENNAPORTS, NULL, 0}; ////////// Physical parameters @@ -579,12 +573,6 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { } sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); - config_getlist(&SSBsParamList, NULL, 0, aprefix); - if (SSBsParamList.numelt > 0) config_get(SSBsParams,sizeof(SSBsParams)/sizeof(paramdef_t),aprefix); - - config_getlist(&PDSCHANTENNAParamList, NULL, 0, aprefix); - if (PDSCHANTENNAParamList.numelt > 0) config_get(PDSCHANTENNAParams,sizeof(PDSCHANTENNAParams)/sizeof(paramdef_t),aprefix); - config_getlist(&SCCsParamList, NULL, 0, aprefix); if (SCCsParamList.numelt > 0) { @@ -660,15 +648,16 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { (NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l] == 3),"BAD MNC DIGIT LENGTH %d", NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l]); } - - // Parse optional physical parameters - sprintf(gnbpath,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k), + printf("SSB SCO %d\n",*GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).ssb_SubcarrierOffset = *GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr; + printf("pdsch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr; + printf("pusch_TargetSNRx10 %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_TARGETPOW_X10_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).pusch_TargetSNRx10 = *GNBParamList.paramarray[i][GNB_PUSCH_TARGETPOW_X10_IDX].iptr; + printf("pucch_TargetSNRx10 %d\n",*GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr); + NRRRC_CONFIGURATION_REQ (msg_p).pucch_TargetSNRx10 = *GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr; + NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; - printf("SSB SCO %d\n",ssb_SubcarrierOffset); - NRRRC_CONFIGURATION_REQ (msg_p).ssb_SubcarrierOffset = ssb_SubcarrierOffset; - printf("pdsch_AntennaPorts %d\n",pdsch_AntennaPorts); - NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = pdsch_AntennaPorts; - NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; }// }//End for (k=0; k 0) { // Output a list of all gNBs. config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); - - - - - + if (GNBParamList.numelt > 0) { for (k = 0; k < GNBParamList.numelt; k++) { if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) { diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 84045fc622..84da1de530 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -113,6 +113,11 @@ typedef enum { #define GNB_CONFIG_STRING_REMOTE_S_PORTC "remote_s_portc" #define GNB_CONFIG_STRING_LOCAL_S_PORTD "local_s_portd" #define GNB_CONFIG_STRING_REMOTE_S_PORTD "remote_s_portd" +#define GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET "ssb_SubcarrierOffset" +#define GNB_CONFIG_STRING_PDSCHANTENNAPORTS "pdsch_AntennaPorts" +#define GNB_CONFIG_STRING_PUSCHTARGETPOWX10 "pusch_TargetSNRx10" +#define GNB_CONFIG_STRING_PUCCHTARGETPOWX10 "pucch_TargetSNRx10" + typedef struct ccparams_nr_x2 { char *frame_type; @@ -156,7 +161,12 @@ typedef struct ccparams_nr_x2 { {GNB_CONFIG_STRING_REMOTE_S_PORTC, NULL, 0, uptr:NULL, defuintval:50000, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defuintval:50001, TYPE_UINT, 0}, \ {GNB_CONFIG_STRING_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defuintval:50001, TYPE_UINT, 0}, \ +{GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET, NULL, 0, iptr:NULL, defintval:31, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_PDSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_PUSCHTARGETPOWX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_PUCCHTARGETPOWX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ } + #define GNB_GNB_ID_IDX 0 #define GNB_CELL_TYPE_IDX 1 #define GNB_GNB_NAME_IDX 2 @@ -171,6 +181,10 @@ typedef struct ccparams_nr_x2 { #define GNB_REMOTE_S_PORTC_IDX 11 #define GNB_LOCAL_S_PORTD_IDX 12 #define GNB_REMOTE_S_PORTD_IDX 13 +#define GNB_SSB_SUBCARRIEROFFSET_IDX 14 +#define GNB_PDSCH_ANTENNAPORTS_IDX 15 +#define GNB_PUSCH_TARGETPOW_X10_IDX 16 +#define GNB_PUCCH_TARGETPOW_X10_IDX 17 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define GNBPARAMS_CHECK { \ diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 49949bd771..781347abaa 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -660,7 +660,7 @@ config_sib2_mbsfn_part( int Mod_idP, if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { phycfg.cfg->embms_mbsfn_config.fourframes_flag[i] = 0; phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i] = mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration - LOG_I (MAC, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i, phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]); + LOG_I (MAC, "[CONFIG] MBSFN_SubframeConfig[%d] oneFrame pattern is %d\n", i, phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]); } else if (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration phycfg.cfg->embms_mbsfn_config.fourframes_flag[i] = 1; phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i] = @@ -668,7 +668,7 @@ config_sib2_mbsfn_part( int Mod_idP, (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| (mbsfn_SubframeConfigListP->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]<<16); - LOG_I(MAC, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %x\n", i, + LOG_I(MAC, "[CONFIG] MBSFN_SubframeConfig[%d] fourFrame pattern is %x\n", i, phycfg.cfg->embms_mbsfn_config.mbsfn_subframeconfig[i]); } } @@ -777,7 +777,8 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, LTE_SchedulingInfo_MBMS_r14_t *schedulingInfo_fembms, struct LTE_NonMBSFN_SubframeConfig_r14 *nonMBSFN_SubframeConfig, LTE_SystemInformationBlockType1_MBMS_r14_t *sib1_mbms_r14_fembms, - LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms + LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms, + LTE_MBSFNAreaConfiguration_r9_t*mbms_AreaConfig ) { int i; int UE_id = -1; @@ -989,6 +990,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, cfg->num_tlv++; //We need to reuse current MCH scheduler //TOCHECK whether we can simply reuse current mbsfn_SubframeConfig stuff + RC.mac[Mod_idP]->common_channels[0].FeMBMS_flag = FeMBMS_Flag; } if (mbsfn_AreaInfoList != NULL) { @@ -1005,6 +1007,21 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, } } + if(mbms_AreaConfig != NULL) { + RC.mac[Mod_idP]->common_channels[0].commonSF_AllocPeriod_r9 = mbms_AreaConfig->commonSF_AllocPeriod_r9; + LOG_I(MAC, "[eNB %d][CONFIG] LTE_MBSFNAreaConfiguration_r9_t(%p) commonSF_AllocPeriod_r9(%d)\n",Mod_idP,mbms_AreaConfig, RC.mac[Mod_idP]->common_channels[0].commonSF_AllocPeriod_r9); + for(i=0; i < mbms_AreaConfig->commonSF_Alloc_r9.list.count; i++){ + RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i] = mbms_AreaConfig->commonSF_Alloc_r9.list.array[i]; + LOG_I(RRC,"[eNB %d][CONFIG] MBSFNArea[%d] commonSF_Alloc_r9: radioframeAllocationPeriod(%ldn),radioframeAllocationOffset(%ld), subframeAllocation(%x,%x,%x)\n" + ,Mod_idP,i + ,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->radioframeAllocationPeriod + ,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->radioframeAllocationOffset + ,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[0] + ,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[1] + ,RC.mac[Mod_idP]->common_channels[0].commonSF_Alloc_r9_mbsfn_SubframeConfig[i]->subframeAllocation.choice.oneFrame.buf[2]); + } + } + if (pmch_InfoList != NULL) { // LOG_I(MAC,"DUY: lcid when entering rrc_mac config_req is %02d\n",(pmch_InfoList->list.array[0]->mbms_SessionInfoList_r9.list.array[0]->logicalChannelIdentity_r9)); LOG_I(MAC, "[CONFIG] Number of PMCH in this MBSFN Area %d\n", diff --git a/openair2/LAYER2/MAC/config_ue.c b/openair2/LAYER2/MAC/config_ue.c index 897afbf62b..1c5e706218 100644 --- a/openair2/LAYER2/MAC/config_ue.c +++ b/openair2/LAYER2/MAC/config_ue.c @@ -530,6 +530,7 @@ rrc_mac_config_req_ue(module_id_t Mod_idP, LOG_I(MAC, "[UE %d] Configuring LTE_NonMBSFN \n", Mod_idP); phy_config_sib1_fembms_ue(Mod_idP, CC_idP, 0, nonMBSFN_SubframeConfig); + UE_mac_inst[Mod_idP].non_mbsfn_SubframeConfig = nonMBSFN_SubframeConfig; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index c46005ee2d..8f5aab99a7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -547,7 +547,7 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { ul_req_tmp->ul_config_request_body.number_of_pdus = 0; if (ul_req->ul_config_request_body.number_of_pdus>0) { - LOG_D(PHY, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus); + LOG_D(MAC, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus); } memcpy((void *)ul_req->ul_config_request_body.ul_config_pdu_list, @@ -556,6 +556,11 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { } } +extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); +extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); + void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, @@ -843,6 +848,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } /* Note: This should not be done in the MAC! */ + /* for (int ii=0; iiulsch[ii]; @@ -862,6 +868,17 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, clean_eNb_dlsch(dlsch); } } + */ + + int id; + + // clean ULSCH entries for rnti + id = find_ulsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST); + if (id>=0) clean_eNb_ulsch(RC.eNB[module_idP][CC_id]->ulsch[id]); + + // clean DLSCH entries for rnti + id = find_dlsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST); + if (id>=0) clean_eNb_dlsch(RC.eNB[module_idP][CC_id]->dlsch[id][0]); for (int j = 0; j < 10; j++) { nfapi_ul_config_request_body_t *ul_req_tmp = NULL; @@ -904,6 +921,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } #endif + int do_fembms_si=0; for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { if (cc[CC_id].MBMS_flag > 0) { start_meas(&RC.mac[module_idP]->schedule_mch); @@ -914,6 +932,10 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } stop_meas(&RC.mac[module_idP]->schedule_mch); } + if (cc[CC_id].FeMBMS_flag > 0) { + do_fembms_si = 1; + } + } static int debug_flag = 0; @@ -935,12 +957,22 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } /* This schedules MIB */ - if ((subframeP == 0) && (frameP & 3) == 0) - schedule_mib(module_idP, frameP, subframeP); + if(!do_fembms_si/*get_softmodem_params()->fembms*/){ + if ((subframeP == 0) && (frameP & 3) == 0) + schedule_mib(module_idP, frameP, subframeP); + }else{ + if ((subframeP == 0) && (frameP & 15) == 0 ){ + schedule_fembms_mib(module_idP, frameP, subframeP); + //schedule_SI_MBMS(module_idP, frameP, subframeP); + } + } if (get_softmodem_params()->phy_test == 0) { /* This schedules SI for legacy LTE and eMTC starting in subframeP */ - schedule_SI(module_idP, frameP, subframeP); + if(!do_fembms_si/*get_softmodem_params()->fembms*/) + schedule_SI(module_idP, frameP, subframeP); + else + schedule_SI_MBMS(module_idP, frameP, subframeP); /* This schedules Paging in subframeP */ schedule_PCH(module_idP,frameP,subframeP); /* This schedules Random-Access for legacy LTE and eMTC starting in subframeP */ diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index 5b99578d57..e4b9a7a65b 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -731,6 +731,7 @@ schedule_SI_MBMS(module_id_t module_idP, frame_t frameP, if (subframeP == 0) { for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { cc = &eNB->common_channels[CC_id]; + //printf("*cc->sib1_MBMS->si_WindowLength_r14 %d \n", *cc->sib1_MBMS->si_WindowLength_r14); vrb_map = (void *) &cc->vrb_map; N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); dl_config_request = &eNB->DL_req[CC_id]; @@ -911,6 +912,64 @@ schedule_SI_MBMS(module_id_t module_idP, frame_t frameP, stop_meas(&eNB->schedule_si_mbms); } +void +schedule_fembms_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { + eNB_MAC_INST *eNB = RC.mac[module_idP]; + COMMON_channels_t *cc; + nfapi_dl_config_request_pdu_t *dl_config_pdu; + nfapi_tx_request_pdu_t *TX_req; + int mib_sdu_length; + int CC_id; + nfapi_dl_config_request_t *dl_config_request; + nfapi_dl_config_request_body_t *dl_req; + uint16_t sfn_sf = frameP << 4 | subframeP; + AssertFatal(subframeP == 0, "Subframe must be 0\n"); + AssertFatal((frameP & 15) == 0, "Frame must be a multiple of 16\n"); + + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + dl_config_request = &eNB->DL_req[CC_id]; + dl_req = &dl_config_request->dl_config_request_body; + cc = &eNB->common_channels[CC_id]; + mib_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MIBCH_MBMS, 0xFFFF, 1, &cc->MIB_pdu.payload[0], 0); // not used in this case + LOG_D(MAC, "Frame %d, subframe %d: BCH PDU length %d\n", frameP, subframeP, mib_sdu_length); + + if (mib_sdu_length > 0) { + LOG_D(MAC, "Frame %d, subframe %d: Adding BCH PDU in position %d (length %d)\n", frameP, subframeP, dl_req->number_pdu, mib_sdu_length); + + if ((frameP & 1023) < 40) + LOG_D(MAC, + "[eNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes (cc->mib->message.schedulingInfoSIB1_BR_r13 %d)\n", + module_idP, frameP, CC_id, mib_sdu_length, + (int) cc->mib->message.schedulingInfoSIB1_BR_r13); + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_BCH_PDU_TYPE, dl_config_pdu->pdu_size = + 2 + sizeof(nfapi_dl_config_bch_pdu); + dl_config_pdu->bch_pdu.bch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG; + dl_config_pdu->bch_pdu.bch_pdu_rel8.length = mib_sdu_length; + dl_config_pdu->bch_pdu.bch_pdu_rel8.pdu_index = eNB->pdu_index[CC_id]; + dl_config_pdu->bch_pdu.bch_pdu_rel8.transmission_power = 6000; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + dl_req->number_pdu++; + dl_config_request->header.message_id = NFAPI_DL_CONFIG_REQUEST; + dl_config_request->sfn_sf = sfn_sf; + LOG_D(MAC, "eNB->DL_req[0].number_pdu %d (%p)\n", dl_req->number_pdu, &dl_req->number_pdu); + // DL request + TX_req = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus]; + TX_req->pdu_length = 3; + TX_req->pdu_index = eNB->pdu_index[CC_id]++; + TX_req->num_segments = 1; + TX_req->segments[0].segment_length = 3; + TX_req->segments[0].segment_data = cc[CC_id].MIB_pdu.payload; + eNB->TX_req[CC_id].tx_request_body.number_of_pdus++; + eNB->TX_req[CC_id].sfn_sf = sfn_sf; + eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG; + eNB->TX_req[CC_id].header.message_id = NFAPI_TX_REQUEST; + } + } +} void schedule_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 00fd40109d..f6220fa46d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -2240,7 +2240,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( uint8_t first_ue_total[MAX_NUM_CCs][20]; uint8_t first_ue_id[MAX_NUM_CCs][20]; uint8_t ul_inactivity_num[MAX_NUM_CCs]; - uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={0}; + uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={{0}}; // LTE_DL_FRAME_PARMS *frame_parms; uint8_t ulsch_ue_max_num[MAX_NUM_CCs]; uint16_t saved_ulsch_dci[MAX_NUM_CCs]; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c index eb5d78fd3f..0c686a6475 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c @@ -66,7 +66,11 @@ get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id, "[eNB %d] CC_id %d MBSFN synchronization area %d out of range\n ", module_idP, CC_id, mbsfn_sync_area); return -1; - } else if (RC.mac[module_idP]-> + }else if (RC.mac[module_idP]-> + common_channels[CC_id].non_mbsfn_SubframeConfig + != NULL) { + return mbsfn_sync_area; + }else if (RC.mac[module_idP]-> common_channels[CC_id].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) { return mbsfn_sync_area; @@ -80,14 +84,30 @@ get_mbsfn_sf_alloction(module_id_t module_idP, uint8_t CC_id, static uint32_t bytes_in_buffer=0; static uint32_t msi_pmch_stop=0; -//static uint8_t msi_active=0; -//static uint8_t msi_pmch_stop2=0; -uint16_t mbms_rab_id = 2047; +uint16_t mbms_rab_id=2047;//[8] = {2047,2047,2047,2047,2047,2047,2047,2047}; static uint32_t msi_sfs=0; //MSI_ELEMENT * ptr =NULL; +static int check_CAS_sf(frame_t frameP,sub_frame_t subframeP){ + if( ((frameP&3)==0) && (subframeP == 0)) + return 1; + else + return 0; +} +static int check_nonMBSFN_sf(frame_t frameP,COMMON_channels_t *cc,int sf){ + uint32_t non_mbsfn_SubframeConfig = (cc->non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | cc->non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]>>7); + if( frameP % (4<non_mbsfn_SubframeConfig->radioFrameAllocationPeriod_r14) == cc->non_mbsfn_SubframeConfig->radioFrameAllocationOffset_r14 ){ + return (non_mbsfn_SubframeConfig & (0x200>>(sf)))==(0x200 >> (sf)); + } + return 0; +} + + +static int x=0; +static int mbms_mch_i=0; + int schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_frame_t subframeP) @@ -99,29 +119,28 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, int mcch_flag = 0, mtch_flag = 0, msi_flag = 0; int mbsfn_period = 0; // 1<<(RC.mac[module_idP]->mbsfn_SubframeConfig[0]->radioframeAllocationPeriod); int mcch_period = 0; //32<<(RC.mac[module_idP]->mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9); + //TOCHECK mtch index here if(RC.mac[module_idP]->common_channels[CC_id]. pmch_Config[0] == NULL ) - return 0; - - - + //TOCHECK mtch index here int mch_scheduling_period = 8 << (RC.mac[module_idP]->common_channels[CC_id]. pmch_Config[0]->mch_SchedulingPeriod_r9); + unsigned char mcch_sdu_length; unsigned char header_len_mcch = 0, header_len_msi = 0, header_len_mtch = 0, header_len_mtch_temp = 0, header_len_mcch_temp = 0, header_len_msi_temp = 0; - int ii = 0, msi_pos = 0; + int ii = 0, msi_pos = -1; int mcch_mcs = -1; + int shifted_sf = 0; uint16_t TBS, j = -1, padding = 0, post_padding = 0; mac_rlc_status_resp_t rlc_status; - //mac_rlc_status_resp_t rlc_status2; - int num_mtch; + int num_mtch=0; int msi_length=0, i, k; - //uint8_t l =0; + unsigned char sdu_lcids[11], num_sdus = 0, offset = 0; uint16_t sdu_lengths[11], sdu_length_total = 0; unsigned char mch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; // check the max value, this is for dlsch only @@ -136,358 +155,535 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, return 0; } - mbsfn_period = - 1 << (cc->mbsfn_SubframeConfig[j]->radioframeAllocationPeriod); - mcch_period = - 32 << (cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_RepetitionPeriod_r9); - msi_pos = 0; - ii = 0; - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d subframeP %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n", - module_idP, CC_id, frameP, subframeP, i, - cc->num_active_mbsfn_area, j, cc->num_sf_allocation_pattern, - mbsfn_period, mcch_period); + if(cc->non_mbsfn_SubframeConfig){ + int alloc_offset=0; + uint32_t period; + uint32_t non_mbsfn_SubframeConfig = (cc->non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | cc->non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]>>7); + long mcch_offset = cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9; - switch (cc->mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) { - case 0: - mcch_mcs = 2; - break; + period = 4<non_mbsfn_SubframeConfig->radioFrameAllocationPeriod_r14; + alloc_offset = cc->non_mbsfn_SubframeConfig->radioFrameAllocationOffset_r14; + mcch_period = 32 << cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_RepetitionPeriod_r9; + + // get the real MCS value + switch (cc->mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) { + case 0: + mcch_mcs = 2; + break; - case 1: - mcch_mcs = 7; - break; + case 1: + mcch_mcs = 7; + break; - case 2: - mcch_mcs = 13; - break; + case 2: + mcch_mcs = 13; + break; - case 3: - mcch_mcs = 19; - break; - } + case 3: + mcch_mcs = 19; + break; + } + + if (cc->pmch_Config[0]) { + mch_scheduling_period = 8 << cc->pmch_Config[0]->mch_SchedulingPeriod_r9; + } - // 1st: Check the MBSFN subframes from SIB2 info (SF allocation pattern i, max 8 non-overlapping patterns exist) - if (frameP % mbsfn_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP - if (cc->mbsfn_SubframeConfig[j]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format - - // Find the first subframeP in this MCH to transmit MSI - if (frameP % mch_scheduling_period == - cc->mbsfn_SubframeConfig[j]-> - radioframeAllocationOffset) { - while (ii == 0) { - ii = cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & (0x80 >> msi_pos); + LOG_D(MAC,"frameP %d subframe %d period %d alloc_offset %d mcch_mcs %d mcch_period %d mcch_offset %ld buf %x mch_scheduling_period %d\n",frameP, subframeP, period, alloc_offset,mcch_mcs, mcch_period, mcch_offset,(cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0]),mch_scheduling_period); + //if( (frameP % (4 << cc->commonSF_AllocPeriod_r9) ) == 0 ){ + // if((subframeP==0)){ + // x=0; + // mbms_mch_i=0; + // } + //} + //if (frameP % (4 << cc->commonSF_AllocPeriod_r9 ) == 0) { + // if((subframeP==0)){ + // x=0; + // mbms_mch_i=0; + // } + //} + if (cc->pmch_Config[0]) { + // Find the first subframe in this MCH to transmit MSI + if (frameP % 1 == 0) { + if (frameP % mch_scheduling_period == 0) { + msi_pos=0; + if((frameP&3)==0) msi_pos++; - } + while((non_mbsfn_SubframeConfig & (0x100 >> msi_pos)) == (0x100>>msi_pos)) + msi_pos++; + mbms_mch_i=0; - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d subframeP %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n", - module_idP, CC_id, frameP, subframeP, i, j, - cc->mbsfn_SubframeConfig[j]-> - subframeAllocation.choice.oneFrame.buf[0], - msi_pos); + if((subframeP==0)){ + x=0; + mbms_mch_i=0; + } + } - // Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 - switch (subframeP) { - case 1: - if (cc->tdd_Config == NULL) { - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == - MBSFN_FDD_SF1) { - if (msi_pos == 1) { - msi_flag = 1; - } + } + } - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_FDD_SF1) == - MBSFN_FDD_SF1)) { - mcch_flag = 1; - } + if(cc->pmch_Config[mbms_mch_i+1]!=NULL){ + if( x == cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9+shifted_sf){ - mtch_flag = 1; - } - } - - break; - - case 2: - if (cc->tdd_Config == NULL) { - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == - MBSFN_FDD_SF2) { - if (msi_pos == 2) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_FDD_SF2) == - MBSFN_FDD_SF2)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } - - break; - - case 3: - if (cc->tdd_Config != NULL) { // TDD - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == - MBSFN_TDD_SF3) { - if (msi_pos == 1) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_TDD_SF3) == - MBSFN_TDD_SF3)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } else { // FDD - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == - MBSFN_FDD_SF3) { - if (msi_pos == 3) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_FDD_SF3) == - MBSFN_FDD_SF3)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } - - break; - - case 4: - if (cc->tdd_Config != NULL) { - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == - MBSFN_TDD_SF4) { - if (msi_pos == 2) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_TDD_SF4) == - MBSFN_TDD_SF4)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } - - break; - - case 6: - if (cc->tdd_Config == NULL) { - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == - MBSFN_FDD_SF6) { - if (msi_pos == 4) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_FDD_SF6) == - MBSFN_FDD_SF6)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } - - break; - - case 7: - if (cc->tdd_Config != NULL) { // TDD - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == - MBSFN_TDD_SF7) { - if (msi_pos == 3) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_TDD_SF7) == - MBSFN_TDD_SF7)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } else { // FDD - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == - MBSFN_FDD_SF7) { - if (msi_pos == 5) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_FDD_SF7) == - MBSFN_FDD_SF7)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } - - break; - - case 8: - if (cc->tdd_Config != NULL) { //TDD - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == - MBSFN_TDD_SF8) { - if (msi_pos == 4) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_TDD_SF8) == - MBSFN_TDD_SF8)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } else { // FDD - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == - MBSFN_FDD_SF8) { - if (msi_pos == 6) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_FDD_SF8) == - MBSFN_FDD_SF8)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } - - break; - - case 9: - if (cc->tdd_Config != NULL) { - if ((cc-> - mbsfn_SubframeConfig[j]->subframeAllocation. - choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == - MBSFN_TDD_SF9) { - if (msi_pos == 5) { - msi_flag = 1; - } - - if ((frameP % mcch_period == - cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.mcch_Offset_r9) - && - ((cc->mbsfn_AreaInfo[i]-> - mcch_Config_r9.sf_AllocInfo_r9. - buf[0] & MBSFN_TDD_SF9) == - MBSFN_TDD_SF9)) { - mcch_flag = 1; - } - - mtch_flag = 1; - } - } - - break; - } // end switch - - // sf allocation is non-overlapping - if ((msi_flag == 1) || (mcch_flag == 1) - || (mtch_flag == 1)) { - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", - module_idP, CC_id, frameP, subframeP, i, j, - msi_flag, mcch_flag, mtch_flag); - break; + shifted_sf = check_nonMBSFN_sf(frameP,cc,subframeP)+check_CAS_sf(frameP,subframeP); + msi_pos=subframeP+shifted_sf; + if(shifted_sf==0) + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d shifted_sf %d\n",frameP, subframeP, msi_pos,mbms_mch_i,shifted_sf); } - } else { // four-frameP format } - } - } // end of for loop + + // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 + switch (subframeP) { + case 0: + if (msi_pos == 0) { + msi_flag = 1; + } + mtch_flag = 1; + break; + case 1: + if (msi_pos == 1) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && ((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1)) { + mcch_flag = 1; + } + mtch_flag = 1; + break; + + case 2: + if (msi_pos == 2) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && ((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2)) { + mcch_flag = 1; + } + mtch_flag = 1; + + break; + + case 3: + if (msi_pos == 3) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && ((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3)) { + mcch_flag = 1; + } + mtch_flag = 1; + break; + + case 4: + if (msi_pos == 4) { + msi_flag = 1; + } + mtch_flag = 1; + break; + + case 5: + if (msi_pos == 5) { + msi_flag = 1; + } + mtch_flag = 1; + break; + + case 6: + if (msi_pos == 6) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && ((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6)) { + mcch_flag = 1; + } + mtch_flag = 1; + break; + + case 7: + if (msi_pos == 7) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && ((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7)) { + mcch_flag = 1; + } + mtch_flag = 1; + break; + + case 8: + if (msi_pos == 8) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && ((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8)) { + mcch_flag = 1; + } + mtch_flag = 1; + break; + + case 9: + if (msi_pos == 9) { + msi_flag = 1; + } + mtch_flag = 1; + break; + }// end switch + + if ((msi_flag == 1) || (mcch_flag == 1) || (mtch_flag == 1)) { + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", + module_idP, CC_id, frameP, subframeP, i, j, + msi_flag, mcch_flag, mtch_flag); + } + + //TODO quitar la subframe 0 del otro switch ... está mal interpretado ? + // if((frameP&3) == 0){ + // mtch_flag=0;mcch_flag=0;msi_flag=0; + // } + + if((frameP % period ) == alloc_offset){ + LOG_D(MAC,"non_mbsfn_SubframeConfig %x\n",non_mbsfn_SubframeConfig); + switch(subframeP){ + case 0:{ + mtch_flag=0;mcch_flag=0;msi_flag=0; + } + break; + case 1:{ + if ((non_mbsfn_SubframeConfig & 0x100) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 2:{ + if ((non_mbsfn_SubframeConfig & 0x80) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 3:{ + if ((non_mbsfn_SubframeConfig & 0x40) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 4:{ + if ((non_mbsfn_SubframeConfig & 0x20) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 5:{ + if ((non_mbsfn_SubframeConfig & 0x10) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 6:{ + if ((non_mbsfn_SubframeConfig & 0x8) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 7:{ + if ((non_mbsfn_SubframeConfig & 0x4) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 8:{ + if ((non_mbsfn_SubframeConfig & 0x2) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + case 9:{ + if ((non_mbsfn_SubframeConfig & 0x1) > 0) + {mtch_flag=0;mcch_flag=0;msi_flag=0;} + } + break; + } + } + // sf allocation is non-overlapping + if ((msi_flag == 1) || (mcch_flag == 1) || (mtch_flag == 1)) { + x++; + //if( (msi_flag!=1 && mcch_flag!=1) || (msi_flag!=1 && mcch_flag!=1 && mtch_flag!=1) ){ + //x++; + //} + + if(msi_flag==1){ + if ( (/*AJ*/ (/*V*/ ( /*U*/ (frameP %( 4 << cc->commonSF_AllocPeriod_r9)) ) / 8 ) % ((8 << cc->pmch_Config[mbms_mch_i]->mch_SchedulingPeriod_r9) / 8 ) ) != 0 ){ + msi_flag=0; + LOG_D(MAC,"frameP %d subframeP %d reset(%d)\n",frameP, subframeP, mbms_mch_i); + } + + } + + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d, x %d\n", + module_idP, CC_id, frameP, subframeP, i, j, + msi_flag, mcch_flag, mtch_flag,x); + break; + } + + + }else if(cc->mbsfn_SubframeConfig[j]){ + + mbsfn_period = + 1 << (cc->mbsfn_SubframeConfig[j]->radioframeAllocationPeriod); + mcch_period = + 32 << (cc->mbsfn_AreaInfo[i]-> + mcch_Config_r9.mcch_RepetitionPeriod_r9); + msi_pos = 0; + ii = 0; + LOG_D(MAC, "[eNB %d] CC_id %d Frame %d subframeP %d : Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d)\n", + module_idP, CC_id, frameP, subframeP, i, + cc->num_active_mbsfn_area, j, cc->num_sf_allocation_pattern, + mbsfn_period, mcch_period); + + switch (cc->mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) { + case 0: + mcch_mcs = 2; + break; + + case 1: + mcch_mcs = 7; + break; + + case 2: + mcch_mcs = 13; + break; + + case 3: + mcch_mcs = 19; + break; + } + + // 1st: Check the MBSFN subframes from SIB2 info (SF allocation pattern i, max 8 non-overlapping patterns exist) + if (frameP % mbsfn_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP + if (cc->mbsfn_SubframeConfig[j]->subframeAllocation.present == LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format + // Find the first subframeP in this MCH to transmit MSI + if (frameP % mch_scheduling_period == cc->mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { + while (ii == 0) { + ii = cc-> + mbsfn_SubframeConfig[j]->subframeAllocation. + choice.oneFrame.buf[0] & (0x80 >> msi_pos); + msi_pos++; + } + LOG_D(MAC, "[eNB %d] CC_id %d Frame %d subframeP %d : sync area %d sf allocation pattern %d sf alloc %x msi pos is %d \n", + module_idP, CC_id, frameP, subframeP, i, j, + cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0], + msi_pos); + if((subframeP==1)){ + x=0; + mbms_mch_i=0; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframeP, msi_pos,mbms_mch_i); + } + } + + // Check if the subframeP is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 + switch (subframeP) { + case 1: + if (cc->tdd_Config == NULL) { + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { + if(cc->pmch_Config[mbms_mch_i+1]!=NULL){ + if( x == cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=1; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframeP, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 1) { + msi_flag = 1; + } + if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + && ( (cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) ) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + case 2: + if (cc->tdd_Config == NULL) { + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { + if(cc->pmch_Config[mbms_mch_i+1]!=NULL){ + if( x == cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=2; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframeP, msi_pos,mbms_mch_i); + } + } + + if (msi_pos == 2) { + msi_flag = 1; + } + if ( (frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + && ((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + case 3: + if (cc->tdd_Config != NULL) { + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) { + if (msi_pos == 1) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } else { // FDD + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) { + if(cc->pmch_Config[mbms_mch_i+1]!=NULL){ + if( x == cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=3; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframeP, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 3) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + case 4: + if (cc->tdd_Config != NULL) { + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) { + if (msi_pos == 2) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + case 6: + if (cc->tdd_Config == NULL) { + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { + if(cc->pmch_Config[mbms_mch_i+1]!=NULL){ + if( x == cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=4; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframeP, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 4) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + case 7: + if (cc->tdd_Config != NULL) { // TDD + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) { + if (msi_pos == 3) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } else { // FDD + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) { + if(cc->pmch_Config[mbms_mch_i+1]!=NULL){ + if( x == cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=5; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframeP, msi_pos,mbms_mch_i); + } + } + + if (msi_pos == 5) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + case 8: + if (cc->tdd_Config != NULL) { //TDD + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) { + if (msi_pos == 4) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } else { // FDD + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) { + if(cc->pmch_Config[mbms_mch_i+1]!=NULL){ + if( x == cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=6; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframeP, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 6) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + case 9: + if (cc->tdd_Config != NULL) { + if ((cc->mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) { + if (msi_pos == 5) { + msi_flag = 1; + } + if ((frameP % mcch_period == cc->mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) + &&((cc->mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9)) { + mcch_flag = 1; + } + mtch_flag = 1; + } + } + break; + } // end switch + // sf allocation is non-overlapping + if ((msi_flag == 1) || (mcch_flag == 1) || (mtch_flag == 1)) { + x++; + //if( (msi_flag!=1 && mcch_flag!=1) || (msi_flag!=1 && mcch_flag!=1 && mtch_flag!=1) ){ + //x++; + //} + if(msi_flag==1){ + if ( (/*AJ*/ (/*V*/ ( /*U*/ (frameP %( 4 << cc->commonSF_AllocPeriod_r9)) ) / 8 ) % ((8 << cc->pmch_Config[mbms_mch_i]->mch_SchedulingPeriod_r9) / 8 ) ) != 0 ){ + msi_flag=0; + LOG_D(MAC,"frameP %d subframeP %d reset(%d)\n",frameP, subframeP, mbms_mch_i); + } + + } + + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d x %d\n", + module_idP, CC_id, frameP, subframeP, i, j, + msi_flag, mcch_flag, mtch_flag,x); + break; + } + } else {// four-frameP format + printf("Hola\n"); + AssertFatal(1==0,"four-frameP format: not implemented yet\n"); + } + } + } // MBMS format + }// end of for loop cc->msi_active = 0; cc->mcch_active = 0; @@ -497,7 +693,7 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, if ((msi_flag == 1) || (mcch_flag == 1)) { cc->MCH_pdu.mcs = mcch_mcs; } else if (mtch_flag == 1) { // only MTCH in this subframeP - cc->MCH_pdu.mcs = cc->pmch_Config[0]->dataMCS_r9; + cc->MCH_pdu.mcs = cc->pmch_Config[mbms_mch_i]->dataMCS_r9; } @@ -510,26 +706,14 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, // there is MSI (MCH Scheduling Info) uint16_t msi_control_element[29], *msi_ptr; + // MSI buffer pointer char *buffer_pointer=NULL; if (msi_flag == 1) { // Create MSI here - //uint16_t msi_control_element[29], *msi_ptr; - msi_ptr = &msi_control_element[0]; - //((MSI_ELEMENT *) msi_ptr)->lcid = MCCH_LCHANID; //MCCH - - //if (mcch_flag == 1) { - // ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; - // ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0; - //} else { // no mcch for this MSP - // ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7; // stop value is 2047 - // ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xff; - //} - - //msi_ptr += sizeof(MSI_ELEMENT); //Header for MTCHs - num_mtch = cc->mbms_SessionList[0]->list.count; + num_mtch = cc->mbms_SessionList[mbms_mch_i]->list.count; TBS = get_TBS_DL(cc->MCH_pdu.mcs, to_prb(cc->mib->message.dl_Bandwidth)); @@ -537,7 +721,7 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, for (k = 0; k < num_mtch; k++) { // loop for all session in this MCH (MCH[0]) at this moment - ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[0]->list.array[k]->logicalChannelIdentity_r9; //mtch_lcid; + ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[mbms_mch_i]->list.array[k]->logicalChannelIdentity_r9; //mtch_lcid; if( msi_sfs != 0 ) msi_pmch_stop = msi_sfs-1; @@ -546,22 +730,15 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, msi_pmch_stop = msi_sfs; - //if( msi_pmch_stop > cc->pmch_Config[0]->sf_AllocEnd_r9) - //LOG_W(MAC,"e-MBMS Buffer Overflow\n"); - if(msi_pmch_stop>=num_sf_alloc /*&& msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9*/) { - ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframeP of this mtch (only one mtch now) & stop_sf limited to 256 - //((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = msi_pmch_stop; - ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9); - msi_pmch_stop = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9); + ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = (((msi_pmch_stop <=cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9) >> 8) & 0x7f); + ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = ((msi_pmch_stop <=cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9) & 0xff); + msi_pmch_stop = (msi_pmch_stop <=cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9); }else{ ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7; // last subframeP of this mtch (only one mtch now) ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xFF; msi_pmch_stop=0; } - - - msi_ptr += sizeof(MSI_ELEMENT); } @@ -573,15 +750,11 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, header_len_msi = 3; } - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes TBS %d, bytes in buffer %d stop_sf_LSB %d msi_sfs %d cc->pmch_Config[0]->sf_AllocEnd_r9 %ld\n", - module_idP, CC_id, frameP, msi_length,TBS, bytes_in_buffer,msi_pmch_stop,msi_sfs,cc->pmch_Config[0]->sf_AllocEnd_r9); + LOG_D(MAC, "[eNB %d] CC_id %d Frame %d : MSI->MCH, length of MSI is %d bytes TBS %d, bytes in buffer %d stop_sf_LSB %d msi_sfs %d cc->pmch_Config[0]->sf_AllocEnd_r9 %ld\n", + module_idP, CC_id, frameP, msi_length,TBS, bytes_in_buffer,msi_pmch_stop,msi_sfs,cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9); msi_sfs = 0; - //LOG_D(MAC,"Scheduler: MSI is transmitted in this subframeP \n" ); - - // LOG_D(MAC,"Scheduler: MSI length is %d bytes\n",msi_length); // Store MSI data to mch_buffer[0] memcpy((char *) &mch_buffer[sdu_length_total], msi_control_element, msi_length); @@ -598,75 +771,93 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, } // there is MCCH if (mcch_flag == 1) { + //MCCH scheduling if !FeMBMS + if(!cc->non_mbsfn_SubframeConfig){ + mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH_COUNTING, 0xFFFC, 1, &cc->MCCH_pdu.payload[0], + i); // this is the mbsfn sync area index + if(mcch_sdu_length>0) + LOG_I(MAC, "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE COUNTING (area %d, sfAlloc %d)\n", + module_idP, CC_id, frameP, subframeP, i, j); - //LOG_E(MAC, - //"[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE COUNTING (mod %d)\n",module_idP, CC_id, frameP, subframeP,frameP%2==0); - if(1/*frameP%2==0*/){ - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n", - module_idP, CC_id, frameP, subframeP, i, j); + if (mcch_sdu_length > 0) { + mcch_sdu_length+=1; //RLC ? + LOG_D(MAC, "[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n", + module_idP, CC_id, frameP, subframeP, mcch_sdu_length); - mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 0xFFFC, 1, &cc->MCCH_pdu.payload[0], - i); // this is the mbsfn sync area index - } - else{ - LOG_E(MAC, - "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE COUNTING (area %d, sfAlloc %d)\n", - module_idP, CC_id, frameP, subframeP, i, j); + header_len_mcch = 2; -// -// mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH_COUNTING, 0xFFFC, 1, &cc->MCCH_pdu.payload[0], -// i); // this is the mbsfn sync area index + if (cc->tdd_Config != NULL) { + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n", + module_idP, CC_id, frameP, subframeP, + mcch_sdu_length, mcch_mcs); + } else { + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n", + module_idP, CC_id, frameP, subframeP, + mcch_sdu_length, mcch_mcs); + } + + cc->mcch_active = 1; + + memcpy((char *) &mch_buffer[sdu_length_total]+1, + &cc->MCCH_pdu.payload[0], mcch_sdu_length); + sdu_lcids[num_sdus] = MCCH_LCHANID; + sdu_lengths[num_sdus] = mcch_sdu_length; + + if (sdu_lengths[num_sdus] > 128) { + header_len_mcch = 3; + } + + sdu_length_total += sdu_lengths[num_sdus]; + LOG_D(MAC, + "[eNB %d] CC_id %d Got %d bytes for MCCH from RRC \n", + module_idP, CC_id, sdu_lengths[num_sdus]); + num_sdus++; + } } - mcch_sdu_length+=1; //RLC ? + //MCCH scheduling ... do it anyway + { + LOG_I(MAC, "[eNB %d] CC_id %d Frame %d Subframe %d: Schedule MCCH MESSAGE (area %d, sfAlloc %d)\n", + module_idP, CC_id, frameP, subframeP, i, j); - if (mcch_sdu_length > 0) { - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n", - module_idP, CC_id, frameP, subframeP, mcch_sdu_length); + mcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, frameP, MCCH, 0xFFFC, 1, &cc->MCCH_pdu.payload[0], + i); // this is the mbsfn sync area index - header_len_mcch = 2; + if (mcch_sdu_length > 0) { + mcch_sdu_length+=1; //RLC ? + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d : MCCH->MCH, Received %d bytes from RRC \n", + module_idP, CC_id, frameP, subframeP, mcch_sdu_length); - if (cc->tdd_Config != NULL) { - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n", - module_idP, CC_id, frameP, subframeP, - mcch_sdu_length, mcch_mcs); - } else { - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n", - module_idP, CC_id, frameP, subframeP, - mcch_sdu_length, mcch_mcs); + header_len_mcch = 2; + + if (cc->tdd_Config != NULL) { + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (TDD) for MCCH message %d bytes (mcs %d )\n", + module_idP, CC_id, frameP, subframeP, + mcch_sdu_length, mcch_mcs); + } else { + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Scheduling MCCH->MCH (FDD) for MCCH message %d bytes (mcs %d)\n", + module_idP, CC_id, frameP, subframeP, + mcch_sdu_length, mcch_mcs); + } + + cc->mcch_active = 1; + + memcpy((char *) &mch_buffer[sdu_length_total]+1, + &cc->MCCH_pdu.payload[0], mcch_sdu_length); + sdu_lcids[num_sdus] = MCCH_LCHANID; + sdu_lengths[num_sdus] = mcch_sdu_length; + + if (sdu_lengths[num_sdus] > 128) { + header_len_mcch = 3; + } + + sdu_length_total += sdu_lengths[num_sdus]; + LOG_D(MAC,"[eNB %d] CC_id %d Got %d bytes for MCCH from RRC \n", + module_idP, CC_id, sdu_lengths[num_sdus]); + num_sdus++; } - - cc->mcch_active = 1; - - memcpy((char *) &mch_buffer[sdu_length_total]+1, - &cc->MCCH_pdu.payload[0], mcch_sdu_length); - sdu_lcids[num_sdus] = MCCH_LCHANID; - sdu_lengths[num_sdus] = mcch_sdu_length; - - // LOG_W(MAC,"MCCH RLC %x:",(unsigned char)mch_buffer[sdu_length_total]); - // for (int kk = 7; kk >= 0; kk--) - // { - // printf("%d",(((unsigned char)mch_buffer[sdu_length_total]) >> kk) & 1 ? '1' : '0'); - // } - // printf("\n"); - //mch_buffer[sdu_length_total] = (unsigned char)0; - - - if (sdu_lengths[num_sdus] > 128) { - header_len_mcch = 3; - } - - sdu_length_total += sdu_lengths[num_sdus]; - LOG_D(MAC, - "[eNB %d] CC_id %d Got %d bytes for MCCH from RRC \n", - module_idP, CC_id, sdu_lengths[num_sdus]); - num_sdus++; } - } + }// mcch_flag TBS = @@ -678,154 +869,108 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, // there is MTCHs, loop if there are more than 1 if (mtch_flag == 1 ) { // Calculate TBS - /* if ((msi_flag==1) || (mcch_flag==1)) { - TBS = mac_xface->get_TBS(mcch_mcs, mac_xface->frame_parms->N_RB_DL); - } - else { // only MTCH in this subframeP - TBS = mac_xface->get_TBS(RC.mac[module_idP]->pmch_Config[0]->dataMCS_r9, mac_xface->frame_parms->N_RB_DL); - } - - // get MTCH data from RLC (like for DTCH) - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframe %d: Schedule MTCH (area %d, sfAlloc %d)\n",Mod_id,CC_id,frame,subframe,i,j); - - header_len_mtch = 3; - LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", - Mod_id,CC_id,frame,MTCH,TBS, - TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); - - rlc_status = mac_rlc_status_ind(Mod_id,frame,1,RLC_MBMS_YES,MTCH+ (maxDRB + 3) * MAX_MOBILES_PER_RG, - TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); - printf("frame %d, subframe %d, rlc_status.bytes_in_buffer is %d\n",frame,subframe, rlc_status.bytes_in_buffer); - - */ - // get MTCH data from RLC (like for DTCH) - LOG_D(MAC, - "[eNB %d] CC_id %d Frame %d subframeP %d: Schedule MTCH (area %d, sfAlloc %d)\n", + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: Schedule MTCH (area %d, sfAlloc %d)\n", module_idP, CC_id, frameP, subframeP, i, j); header_len_mtch = 3; - LOG_D(MAC, - "[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", + LOG_D(MAC,"[eNB %d], CC_id %d, Frame %d, MTCH->MCH, Checking RLC status (rab %d, tbs %d, len %d)\n", module_idP, CC_id, frameP, MTCH, TBS, TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch); - mbms_rab_id = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9; + //TODO + mbms_rab_id = cc->mbms_SessionList[0/*mbms_mch_i*/]->list.array[0]->logicalChannelIdentity_r9; rlc_status = mac_rlc_status_ind(module_idP, 0xfffd, frameP, subframeP, module_idP, ENB_FLAG_YES, MBMS_FLAG_YES, - cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, + cc->mbms_SessionList[mbms_mch_i]->list.array[0]->logicalChannelIdentity_r9, //MTCH, 0, 0 ); + bytes_in_buffer = rlc_status.bytes_in_buffer; - + //TOCHECK is this really neede? if( !(mcch_flag==1 || msi_flag==1) ) msi_sfs = rlc_status.bytes_in_buffer/(TBS- header_len_mcch - header_len_msi -sdu_length_total - header_len_mtch)+(rlc_status.bytes_in_buffer%(TBS- header_len_mcch - header_len_msi -sdu_length_total - header_len_mtch)?1:0); - //uint16_t msi_control_element[29], *msi_ptr; - // - // - uint16_t TBS_MTCH = - get_TBS_DL(cc->pmch_Config[0]->dataMCS_r9, to_prb(cc->mib->message.dl_Bandwidth)); + + uint16_t TBS_MTCH = + get_TBS_DL(cc->pmch_Config[mbms_mch_i]->dataMCS_r9, to_prb(cc->mib->message.dl_Bandwidth)); + if(msi_flag==1 && buffer_pointer!=NULL){ - msi_ptr = &msi_control_element[0]; + // msi_ptr = &msi_control_element[0]; - //memcpy(buffer_pointer, - // msi_control_element, msi_length); - - // msi_pmch_stop = rlc_status.bytes_in_buffer/TBS+(rlc_status.bytes_in_buffer%TBS?1:0); msi_pmch_stop = (rlc_status.bytes_in_buffer - header_len_mcch - header_len_msi -sdu_length_total - header_len_mtch)/(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)+((rlc_status.bytes_in_buffer-TBS-header_len_mcch - header_len_msi -sdu_length_total)%(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)?0:0); - if( msi_pmch_stop > cc->pmch_Config[0]->sf_AllocEnd_r9) - LOG_E(MAC,"e-MBMS Buffer Overflow\n"); - if(msi_pmch_stop>=num_sf_alloc /*&& msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9*/) { - ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0; // last subframeP of this mtch (only one mtch now) & stop_sf limited to 256 - //((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = msi_pmch_stop; - ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9); - msi_pmch_stop = (msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[0]->sf_AllocEnd_r9); - }else{ - ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7; // last subframeP of this mtch (only one mtch now) - ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xFF; - msi_pmch_stop=0; - } - LOG_I(MAC,"frameP %d, subframeP %d rlc_status.bytes_in_buffer %d stop_sf_LSB %d\n",frameP,subframeP,rlc_status.bytes_in_buffer,((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB); - //LOG_W(MAC,"frameP %d, subframeP %d rlc_status.bytes_in_buffer %d stop_sf_LSB %d msi_calc:%d remainder %d\n",frameP,subframeP,rlc_status.bytes_in_buffer,((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB,rlc_status.bytes_in_buffer/(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)+((rlc_status.bytes_in_buffer-TBS-header_len_mcch - header_len_msi -sdu_length_total)%(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)?0:0),((rlc_status.bytes_in_buffer-TBS-header_len_mcch - header_len_msi -sdu_length_total)%(TBS_MTCH/*- header_len_mcch - header_len_msi -sdu_length_total*/ - header_len_mtch)?0:0)); + for (k = 0; k < num_mtch; k++) { // loop for all session in this MCH (MCH[0]) at this moment + msi_ptr = &msi_control_element[k]; - memcpy(buffer_pointer, + ((MSI_ELEMENT *) msi_ptr)->lcid = cc->mbms_SessionList[mbms_mch_i]->list.array[k]->logicalChannelIdentity_r9; //mtch_lcid; + + if( msi_pmch_stop > cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9) + LOG_E(MAC,"e-MBMS Buffer Overflow\n"); + + if(msi_pmch_stop>=num_sf_alloc /*&& msi_pmch_stop <=cc->pmch_Config[0]->sf_AllocEnd_r9*/) { + ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = (((msi_pmch_stop <=cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9) >> 8) & 0x7f); + ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = ((msi_pmch_stop <=cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9) & 0xff); + msi_pmch_stop = (msi_pmch_stop <=cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9 ? msi_pmch_stop: cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9); + }else{ + ((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB = 0x7; // last subframeP of this mtch (only one mtch now) + ((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB = 0xFF; + msi_pmch_stop=0; + } + LOG_I(MAC,"frameP %d, subframeP %d LCID %d rlc_status.bytes_in_buffer %d stop_sf_LSB %d stop_sf_MSB %d msi_pmch_stop %d sf_AllocEnd_r9 %ld, msi_length %d\n",frameP,subframeP,((MSI_ELEMENT *) msi_ptr)->lcid,rlc_status.bytes_in_buffer,((MSI_ELEMENT *) msi_ptr)->stop_sf_LSB,((MSI_ELEMENT *) msi_ptr)->stop_sf_MSB, msi_pmch_stop,cc->pmch_Config[mbms_mch_i]->sf_AllocEnd_r9, msi_length); + } + + memcpy((char*)buffer_pointer, msi_control_element, msi_length); - } - LOG_D(MAC, - "e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d TBS_MTCH %d pmch_stop %d msi_sfs %d\n", + LOG_D(MAC, "e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d TBS_MTCH %d pmch_stop %d msi_sfs %d\n", MTCH, frameP, subframeP, rlc_status.bytes_in_buffer,TBS_MTCH,msi_pmch_stop,msi_sfs); - if ((rlc_status.bytes_in_buffer > 0 && msi_pmch_stop > 0) && ((msi_flag!=1 || mcch_flag!=1)) /*|| (rlc_status.bytes_in_buffer > 0 && (msi_flag==1 || mcch_flag==1))*//*|| msi_sfs > cc->pmch_Config[0]->sf_AllocEnd_r9 */ /*msi_pmch_stop>=num_sf_alloc*/ ) { - //if(rlc_status.bytes_in_buffer > 0){ - LOG_D(MAC, - "[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d) rlc_status.bytes_in_buffer %d\n", - module_idP, CC_id, frameP, + //TODO not sure whether msi and mch MCH should be precluded ... keep in mind this konditions just in case if ((rlc_status.bytes_in_buffer > 0 && msi_pmch_stop > 0) && ((msi_flag!=1 || mcch_flag!=1)) + if ((rlc_status.bytes_in_buffer > 0 && msi_pmch_stop > 0) /*&& ((msi_flag!=1 || mcch_flag!=1))*/ /*|| (rlc_status.bytes_in_buffer > 0 && (msi_flag==1 || mcch_flag==1))*//*|| msi_sfs > cc->pmch_Config[0]->sf_AllocEnd_r9 */ /*msi_pmch_stop>=num_sf_alloc*/ ) { + LOG_I(MAC,"[eNB %d][MBMS USER-PLANE], CC_id %d, Frame %d, Subframe %d MTCH->MCH, Requesting %d bytes from RLC (header len mtch %d) rlc_status.bytes_in_buffer %d, LCID %ld\n", + module_idP, CC_id, frameP, subframeP, TBS - header_len_mcch - header_len_msi - - sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer); + sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer,cc->mbms_SessionList[mbms_mch_i]->list.array[0]->logicalChannelIdentity_r9); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0xfffd, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0xfffd, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[mbms_mch_i]->list.array[0]->logicalChannelIdentity_r9, TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, (char *) &mch_buffer[sdu_length_total] ,0, 0 ); - - // LOG_I(MAC,"RLC %x:",(unsigned char)mch_buffer[sdu_length_total]); - // for (int kk = 7; kk >= 0; kk--) - // { - // printf("%d",(((unsigned char)mch_buffer[sdu_length_total]) >> kk) & 1 ? '1' : '0'); - // } - // printf("\n"); - - //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(MAX_MOBILES_PER_ENB+1)), (char*)&mch_buffer[sdu_length_total]); - LOG_D(MAC, - "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_sfs %d sdu_lengths[num_sdus] %d\n", + LOG_D(MAC,"[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_sfs %d sdu_lengths[num_sdus] %d\n", module_idP, CC_id, sdu_lengths[num_sdus], MTCH,msi_pmch_stop,msi_sfs, sdu_lengths[num_sdus]); + cc->mtch_active = 1; - sdu_lcids[num_sdus] = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9/*MTCH*/; + + sdu_lcids[num_sdus] = cc->mbms_SessionList[mbms_mch_i]->list.array[0]->logicalChannelIdentity_r9/*MTCH*/; sdu_length_total += sdu_lengths[num_sdus]; if (msi_pmch_stop != 0 && msi_flag !=1) msi_pmch_stop--; - if (sdu_lengths[num_sdus] < 128) { header_len_mtch = 2; } num_sdus++; - //} } else { - // LOG_E(MAC, - // "[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d msi_pmch_stop %d msi_buffer %d msi_sfs %ld msi_buffer_act %ld sdu_lengths[num_sdus] %d\n", - // module_idP, CC_id, sdu_lengths[num_sdus], MTCH,msi_pmch_stop,msi_sfs,msi_buffer_act, sdu_lengths[num_sdus]); - header_len_mtch = 0; } } - // } // FINAL STEP: Prepare and multiplexe MSI, MCCH and MTCHs - if ((sdu_length_total + header_len_msi + header_len_mcch + - header_len_mtch) > 0) { + if ((sdu_length_total + header_len_msi + header_len_mcch + header_len_mtch) > 0) { + // Adjust the last subheader - /* if ((msi_flag==1) || (mcch_flag==1)) { - RC.mac[module_idP]->MCH_pdu.mcs = mcch_mcs; - } - else if (mtch_flag == 1) { // only MTCH in this subframeP - RC.mac[module_idP]->MCH_pdu.mcs = RC.mac[module_idP]->pmch_Config[0]->dataMCS_r9; - } - */ header_len_mtch_temp = header_len_mtch; header_len_mcch_temp = header_len_mcch; header_len_msi_temp = header_len_msi; @@ -881,12 +1026,10 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, cc->MCH_pdu.msi_active = cc->msi_active; cc->MCH_pdu.mcch_active = cc->mcch_active; cc->MCH_pdu.mtch_active = cc->mtch_active; - LOG_D(MAC, - " MCS for this sf is %d (mcch active %d, mtch active %d)\n", + LOG_D(MAC, " MCS for this sf is %d (mcch active %d, mtch active %d)\n", cc->MCH_pdu.mcs, cc->MCH_pdu.mcch_active, cc->MCH_pdu.mtch_active); - LOG_D(MAC, - "[eNB %d][MBMS USER-PLANE ] CC_id %d Generate header : sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,padding %d,post_padding %d (mcs %d, TBS %d), header MTCH %d, header MCCH %d, header MSI %d\n", + LOG_D(MAC, "[eNB %d][MBMS USER-PLANE ] CC_id %d Generate header : sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,padding %d,post_padding %d (mcs %d, TBS %d), header MTCH %d, header MCCH %d, header MSI %d\n", module_idP, CC_id, sdu_length_total, num_sdus, sdu_lengths[0], sdu_lcids[0], offset, padding, post_padding, cc->MCH_pdu.mcs, TBS, header_len_mtch, header_len_mcch, @@ -902,20 +1045,15 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, /* Tracing of PDU is done on UE side */ //if (opt_enabled == 1) { - trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI , 0xfffd, // M_RNTI = 6 in wirehsark - RC.mac[module_idP]->frame, - RC.mac[module_idP]->subframe, 0, 0); - LOG_D(OPT, - "[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n", + trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) cc->MCH_pdu.payload, TBS, module_idP, WS_M_RNTI , 0xfffd, // M_RNTI = 6 in wirehsark + RC.mac[module_idP]->frame, + RC.mac[module_idP]->subframe, 0, 0); + LOG_D(OPT, "[eNB %d][MCH] CC_id %d Frame %d : MAC PDU with size %d\n", module_idP, CC_id, frameP, TBS); //} eNB_MAC_INST *eNB = RC.mac[module_idP]; dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - // dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - // memset((void *) dl_config_pdu, - // 0, - // sizeof(nfapi_dl_config_request_pdu_t)); dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; fill_nfapi_mch_config( dl_req, @@ -934,12 +1072,6 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, TBS, eNB->pdu_index[CC_id], (uint8_t*)cc->MCH_pdu.payload); - - - /* - for (j=0;jMCH_pdu.payload[j+offset]); - printf(" \n"); */ return 1; } else { cc->MCH_pdu.Pdu_size = 0; @@ -947,21 +1079,8 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, cc->MCH_pdu.msi_active = 0; cc->MCH_pdu.mcch_active = 0; cc->MCH_pdu.mtch_active = 0; - // for testing purpose, fill with random data - //for (j=0;j<(TBS-sdu_length_total-offset);j++) - // RC.mac[module_idP]->MCH_pdu.payload[offset+sdu_length_total+j] = (char)(taus()&0xff); return 0; } - - //this is for testing - /* - if (mtch_flag == 1) { - // LOG_D(MAC,"DUY: mch_buffer length so far is : %ld\n", &mch_buffer[sdu_length_total]-&mch_buffer[0]); - return 1; - } - else - return 0; - */ } int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index faefc481f6..7eccc6222d 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -56,6 +56,7 @@ #include "LTE_MobilityControlInfo.h" #include "LTE_MBSFN-AreaInfoList-r9.h" #include "LTE_MBSFN-SubframeConfigList.h" +#include "LTE_MBSFNAreaConfiguration-r9.h" #include "LTE_PMCH-InfoList-r9.h" #include "LTE_SCellToAddMod-r10.h" #include "LTE_SystemInformationBlockType1-v1310-IEs.h" @@ -409,9 +410,11 @@ typedef struct { /*!\brief Values of BCCH SIB_BR logical channel (fake) */ #define BCCH_SI_BR 7 // SI-BR /*!\brief Values of BCCH SIB1_MBMS logical channel (fake) */ -#define BCCH_SIB1_MBMS 60 // SIB1_MBMS //TODO better armonize index +#define MIBCH_MBMS 10 // SIB1_MBMS //TODO better armonize index +#define BCCH_SIB1_MBMS 12 // SIB1_MBMS //TODO better armonize index /*!\brief Values of BCCH SI_MBMS logical channel (fake) */ -#define BCCH_SI_MBMS 61 // SIB_MBMS //TODO better armonize index +#define BCCH_SI_MBMS 13 // SIB_MBMS //TODO better armonize index +#define MCCH_COUNTING 14 /*!\brief Value of CCCH / SRB0 logical channel */ #define CCCH 0 // srb0 /*!\brief DCCH / SRB1 logical channel */ @@ -1286,6 +1289,8 @@ typedef struct { /// MBSFN SubframeConfig struct LTE_MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; struct LTE_NonMBSFN_SubframeConfig_r14 *non_mbsfn_SubframeConfig; + struct LTE_MBSFN_SubframeConfig *commonSF_Alloc_r9_mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA? + uint8_t commonSF_AllocPeriod_r9; /// number of subframe allocation pattern available for MBSFN sync area uint8_t num_sf_allocation_pattern; /// MBMS Flag diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 9d49fdffd5..b92ce85608 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -33,6 +33,16 @@ #include "PHY/defs_common.h" // for PRACH_RESOURCES_t and lte_subframe_t #include "openair2/COMMON/mac_messages_types.h" +/** \fn void schedule_fembms_mib(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); +\brief MIB scheduling for PBCH. This function requests the MIB from RRC and provides it to L1. +@param Mod_id Instance ID of eNB +@param frame Frame index +@param subframe Subframe number on which to act + +*/ + +void schedule_fembms_mib(module_id_t module_idP, + frame_t frameP, sub_frame_t subframeP); /** \addtogroup _mac * @{ @@ -532,6 +542,10 @@ int ue_query_mch(module_id_t Mod_id, uint8_t CC_id, uint32_t frame, sub_frame_t subframe, uint8_t eNB_index, uint8_t *sync_area, uint8_t *mcch_active); +int ue_query_mch_fembms(module_id_t Mod_id, uint8_t CC_id, uint32_t frame, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t * sync_area, uint8_t * mcch_active); + /* \brief Called by PHY to get sdu for PUSCH transmission. It performs the following operations: Checks BSR for DCCH, DCCH1 and DTCH corresponding to previous values computed either in SR or BSR procedures. It gets rlc status indications on DCCH,DCCH1 and DTCH and forms BSR elements and PHR in MAC header. CRNTI element is not supported yet. It computes transport block for up to 3 SDUs and generates header and forms the complete MAC SDU. @param Mod_id Instance id of UE in machine @@ -899,6 +913,7 @@ int generate_dlsch_header(unsigned char *mac_header, @param non_MBSFN_SubframeConfig pointer to FeMBMS Non MBSFN Subframe Config @param sib1_mbms_r14_fembms pointer SI Scheduling infomration for SI-MBMS @param mbsfn_AreaInfoList_fembms pointer to FeMBMS MBSFN Area Info list from SIB1-MBMS +@param mbms_AreaConfiguration pointer to eMBMS MBSFN Area Configuration */ int rrc_mac_config_req_eNB(module_id_t module_idP, @@ -935,7 +950,8 @@ int rrc_mac_config_req_eNB(module_id_t module_idP, LTE_SchedulingInfo_MBMS_r14_t *schedulingInfo_fembms, struct LTE_NonMBSFN_SubframeConfig_r14 *nonMBSFN_SubframeConfig, LTE_SystemInformationBlockType1_MBMS_r14_t *sib1_mbms_r14_fembms, - LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms + LTE_MBSFN_AreaInfoList_r9_t *mbsfn_AreaInfoList_fembms, + LTE_MBSFNAreaConfiguration_r9_t * mbms_AreaConfiguration ); /** \brief RRC eNB Configuration primitive for PHY/MAC. Allows configuration of PHY/MAC resources based on System Information (SI), RRCConnectionSetup and RRCConnectionReconfiguration messages. diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index 24630c0fe2..e97f1bebdd 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -72,7 +72,10 @@ extern UL_IND_t *UL_INFO; extern int next_ra_frame; extern module_id_t next_Mod_id; -int mbms_rab_id = 2047; +int mbms_rab_id=2047;//[8] = {2047,2047,2047,2047,2047,2047,2047,2047}; +static int mbms_mch_i=0; +//static int num_msi_per_CSA[28]; + /* * @@ -753,8 +756,9 @@ ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, LOG_E(MAC,"MCH Scheduling Information MAC Control Element should have an even size\n"); } - LOG_D(MAC,"MCH Scheduling Information, len(%d)\n",rx_lengths[i]); + LOG_D(MAC,"MCH Scheduling Information, len(%d)\n",rx_lengths[i]); + for (j=0; j> 3; @@ -768,7 +772,7 @@ ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, UE_mac_inst[module_idP].msi_status_v[j] = 0; if (UE_mac_inst[module_idP].mcch_status==1) { - LOG_D(MAC,"[UE %d] Frame %d : MCH->MSI for sync area %d (eNB %d, %d bytes), i(%d)\n", module_idP, frameP, sync_area, eNB_index, rx_lengths[i], UE_mac_inst[module_idP].pmch_stop_mtch[j]); + LOG_D(MAC,"[UE %d] Frame %d : MCH->MSI for sync area %d (eNB %d, %d bytes), LCID(%d)(%d)\n", module_idP, frameP, sync_area, eNB_index, rx_lengths[i], UE_mac_inst[module_idP].pmch_lcids[j] , UE_mac_inst[module_idP].pmch_stop_mtch[j]); if (UE_mac_inst[module_idP].pmch_stop_mtch[j] < 2043) { UE_mac_inst[module_idP].pmch_stop_mtch[j] += UE_mac_inst[module_idP].msi_current_alloc; @@ -794,7 +798,7 @@ ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, } if (j<28 && UE_mac_inst[module_idP].msi_status_v[j]==1) { - LOG_D(MAC,"[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes), j=%d\n", module_idP, frameP, sync_area, eNB_index, rx_lengths[i], j); + LOG_D(MAC,"[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes), j=%d lcid %d\n", module_idP, frameP, sync_area, eNB_index, rx_lengths[i], j,rx_lcids[i]); //This sucks I know ... workaround ! mbms_rab_id = rx_lcids[i]; //end sucks :-( @@ -951,7 +955,9 @@ int ue_query_p_mch_info(module_id_t module_idP, uint32_t frameP, uint32_t subfra } } else { //more that one MCH ?? check better this condition //msi and mtch are mutally excluded then the break is safe + //TODO if ((num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[i-1]->sf_AllocEnd_r9 + 1) && (sf_AllocEnd_r9 >= (num_sf_alloc+1))) { + //if ((num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[i-1]->sf_AllocEnd_r9) && (sf_AllocEnd_r9 >= (num_sf_alloc))) { //msi should be just after msi_flag = 1; LOG_D(MAC,"msi(%d) should be allocated:frame(%d),submframe(%d),num_sf_alloc(%d),sf_AllocEnd_r9(%d),common_num_sf_alloc(%d)\n",i,frameP,subframe,num_sf_alloc,sf_AllocEnd_r9, @@ -986,6 +992,458 @@ int ue_query_p_mch_info(module_id_t module_idP, uint32_t frameP, uint32_t subfra return mtch_mcs; } +//static int common_num_sf_alloc=0; +//static int x=0; +int ue_query_mch_fembms(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_t subframe, uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active) { + int i = 0, j = 0,/* ii = 0,*/ msi_pos = -1, mcch_mcs = -1, mtch_mcs = -1, l=0/*,ii=0*/; + int mcch_flag = 0, mtch_flag = 0, msi_flag = 0; + int alloc_offset=0; + uint32_t period; + //uint16_t num_non_mbsfn_SubframeConfig=0; + long mch_scheduling_period = -1; + uint8_t mch_lcid = 0; + //int first_pos=0; + + if(UE_mac_inst[module_idP].non_mbsfn_SubframeConfig == NULL ) + return -1; + + int non_mbsfn_SubframeConfig = (UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]>>7); + + period = 4<radioFrameAllocationPeriod_r14; + alloc_offset = UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->radioFrameAllocationOffset_r14; + + long mcch_period = 32 << UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_RepetitionPeriod_r9; + long mcch_offset = UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9; + + if (UE_mac_inst[module_idP].pmch_Config[0]) { + mch_scheduling_period = 8 << UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9; + } + + +// for(l=0;l<8;l++){ +// if(UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]!=NULL){ +// if(frameP%(4<> msi_pos)) == (0x100>>msi_pos)) +// first_pos++; +// if(first_pos == subframe){ +// ii=0; +// while(UE_mac_inst[module_idP].pmch_Config[ii]!=NULL){ +// num_msi_per_CSA[ii]= ( ( 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9) / (8 << UE_mac_inst[module_idP].pmch_Config[ii]->mch_SchedulingPeriod_r9) ); +// ii++; +// LOG_D(MAC,"frameP %d subframe %d num_msi_per_CSA[%d] %d\n",frameP,subframe,ii,num_msi_per_CSA[ii]); +// } +// } +// +// } +// } +// } +// + + // get the real MCS value + switch (UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) { + case 0: + mcch_mcs = 2; + break; + + case 1: + mcch_mcs = 7; + break; + + case 2: + mcch_mcs = 13; + break; + + case 3: + mcch_mcs = 19; + break; + } + LOG_D(MAC,"frameP %d subframe %d period %d alloc_offset %d mcch_mcs %d mcch_period %ld mcch_offset %ld buf %x mch_scheduling_period %ld\n",frameP, subframe, period, alloc_offset,mcch_mcs, mcch_period, mcch_offset,(UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0]),mch_scheduling_period); + + if((frameP % period ) == alloc_offset){ + switch(subframe){ + case 0: + return (-1); + break; + case 1: + if ((non_mbsfn_SubframeConfig & 0x100) > 0) + return (-1); + break; + case 2: + if ((non_mbsfn_SubframeConfig & 0x80) > 0) + return (-1); + break; + case 3: + if ((non_mbsfn_SubframeConfig & 0x40) > 0) + return (-1); + break; + case 4: + if ((non_mbsfn_SubframeConfig & 0x20) > 0) + return (-1); + break; + case 5: + if ((non_mbsfn_SubframeConfig & 0x10) > 0) + return (-1); + break; + case 6: + if ((non_mbsfn_SubframeConfig & 0x8) > 0) + return (-1); + break; + case 7: + if ((non_mbsfn_SubframeConfig & 0x4) > 0) + return (-1); + break; + case 8: + if ((non_mbsfn_SubframeConfig & 0x2) > 0) + return (-1); + break; + case 9: + if ((non_mbsfn_SubframeConfig & 0x1) > 0) + return (-1); + break; + } + } + + if (UE_mac_inst[module_idP].pmch_Config[0]) { + // Find the first subframe in this MCH to transmit MSI + if (frameP % 1 == 0) { + if (frameP % mch_scheduling_period == 0) { + msi_pos=0; + if((frameP&3)==0) + msi_pos++; + while((non_mbsfn_SubframeConfig & (0x100 >> msi_pos)) == (0x100>>msi_pos)) + msi_pos++; + if(msi_pos == subframe){ + UE_mac_inst[module_idP].common_num_sf_alloc=0; + mbms_mch_i=0; + //LOG_W(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } + } + } + + if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i+1]!=NULL){ + if( UE_mac_inst[module_idP].common_num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=subframe; + mbms_mch_i++; + // LOG_W(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } + + + // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1 + switch (subframe) { + case 0: + if (msi_pos == 0) { + msi_flag = 1; + } + mtch_flag = 1; + break; + case 1: + if (msi_pos == 1) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && + ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1)) { + mcch_flag = 1; + } + + mtch_flag = 1; + break; + + case 2: + if (msi_pos == 2) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && + ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2)) { + mcch_flag = 1; + } + + mtch_flag = 1; + + break; + + case 3: + if (msi_pos == 3) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && + ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3)) { + mcch_flag = 1; + } + + mtch_flag = 1; + + break; + case 4: + if (msi_pos == 4) { + msi_flag = 1; + } + mtch_flag = 1; + break; + case 5: + if (msi_pos == 5) { + msi_flag = 1; + } + mtch_flag = 1; + break; + + case 6: + if (msi_pos == 6) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && + ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6)) { + mcch_flag = 1; + } + + mtch_flag = 1; + + break; + + case 7: + if (msi_pos == 7) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && + ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7)) { + mcch_flag = 1; + } + + mtch_flag = 1; + + break; + + case 8: + if (msi_pos == 8) { + msi_flag = 1; + } + if ((frameP % mcch_period == mcch_offset) && + ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8)) { + mcch_flag = 1; + } + + mtch_flag = 1; + break; + + case 9: + if (msi_pos == 9) { + msi_flag = 1; + } + mtch_flag = 1; + break; + }// end switch + + if( (msi_flag == 1) || (mcch_flag == 1) || (mtch_flag == 1) ){ + UE_mac_inst[module_idP].common_num_sf_alloc++; + //if( (msi_flag!=1 && mcch_flag!=1) || (msi_flag!=1 && mcch_flag!=1 && mtch_flag!=1) ){ + //UE_mac_inst[module_idP].common_num_sf_alloc++; + //if(msi_flag == 1) + // if((num_msi_per_CSA[mbms_mch_i]--)==0){ + // LOG_E(MAC,"Both MSI and MTCH Should be reset?\n"); + // msi_flag=0; + //} + //} + + } + + + + +#ifdef OLD + // Acount for sf_allocable in CSA + int num_sf_alloc = 0; + + for (l = 0; l < 8; l++) { + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) + continue; + + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) + continue; + + uint32_t common_mbsfn_SubframeConfig = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.choice.oneFrame.buf[0]; + + + for (j = 0; j < 6; j++) + num_sf_alloc += ((common_mbsfn_SubframeConfig & (0x80 >> j)) == (0x80 >> j)); + //num_sf_alloc=1; + } + + num_sf_alloc = 10; + + num_non_mbsfn_SubframeConfig = (UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]>>7); + int ones=0; + for(j=0; j < 16; j++){ + if(num_non_mbsfn_SubframeConfig & 1) + ones++; + num_non_mbsfn_SubframeConfig>>=1; + } + + for (l = 0; l < 28; l++) { + if (UE_mac_inst[module_idP].pmch_stop_mtch[l] >= 1/*num_sf_alloc*/) { + if (UE_mac_inst[module_idP].pmch_stop_mtch[l] != 2047) { + if (UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch] != NULL){ + mtch_mcs = UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch]->dataMCS_r9; + //int common_mbsfn_alloc_offset = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[0]->radioframeAllocationOffset; + long common_mbsfn_period = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[0]->radioframeAllocationPeriod; + long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9; + if(UE_mac_inst[module_idP].common_num_sf_alloc >= UE_mac_inst[module_idP].pmch_stop_mtch[l]){ + //LOG_E(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc); + + mtch_mcs = -1; + }/*else + OG_W(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d\n",UE_mac_inst[module_idP].common_num_sf_alloc);*/ + LOG_D(MAC,"Attemp to UE_mac_inst[module_idP].common_num_sf_alloc %d num_sf_alloc %d commonSF_AllocPeriod %ld, common_mbsfn_period %ld num_non_mbsfn_SubframeConfig %x ones %d\n",UE_mac_inst[module_idP].common_num_sf_alloc,num_sf_alloc, commonSF_AllocPeriod,common_mbsfn_period,num_non_mbsfn_SubframeConfig,ones); + UE_mac_inst[module_idP].common_num_sf_alloc++; + UE_mac_inst[module_idP].common_num_sf_alloc = UE_mac_inst[module_idP].common_num_sf_alloc % (num_sf_alloc * commonSF_AllocPeriod / common_mbsfn_period-(1+ones)*(commonSF_AllocPeriod/4)); //TODO + } + else + mtch_mcs = -1; + + mch_lcid = (uint8_t)l; + break; + } + } + } +#endif + +{ + // Acount for sf_allocable in Common SF Allocation + int num_sf_alloc = 0; + + for (l = 0; l < 8; l++) { + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) + continue; + + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) + continue; + + //int common_mbsfn_alloc_offset = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationOffset; + long common_mbsfn_period = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationPeriod; + long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9; + + + num_sf_alloc =10*commonSF_AllocPeriod/common_mbsfn_period; + num_sf_alloc -=1*((commonSF_AllocPeriod/common_mbsfn_period)/4); //CAS sfs + uint32_t num_non_mbsfn_SubframeConfig2 = (UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]<<1 | UE_mac_inst[module_idP].non_mbsfn_SubframeConfig->subframeAllocation_r14.buf[0]>>7); + for (j = 0; j < 10; j++) + num_sf_alloc -= ((num_non_mbsfn_SubframeConfig2 & (0x200 >> j)) == (0x200 >> j))*((commonSF_AllocPeriod/common_mbsfn_period)/period); + + } + + for (l = 0; l < 8; l++) { + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) + continue; + + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) + continue; + + //int common_mbsfn_alloc_offset = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationOffset; + long common_mbsfn_period = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationPeriod; + //long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9; + + + if(msi_flag==1 && UE_mac_inst[module_idP].pmch_Config[mbms_mch_i] != NULL){ + LOG_D(MAC,"msi(%d) should be allocated:frame(%d),submframe(%d),num_sf_alloc(%d),sf_AllocEnd_r9(%ld),common_num_sf_alloc(%d)\n",mbms_mch_i,frameP,subframe,num_sf_alloc,UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9, + UE_mac_inst[module_idP].common_num_sf_alloc); + UE_mac_inst[module_idP].msi_current_alloc = UE_mac_inst[module_idP].common_num_sf_alloc;//num_sf_alloc; + UE_mac_inst[module_idP].msi_pmch = mbms_mch_i; + }else if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i] != NULL){ + if (UE_mac_inst[module_idP].pmch_stop_mtch[mbms_mch_i] >= UE_mac_inst[module_idP].common_num_sf_alloc/*num_sf_alloc*/) { + if (UE_mac_inst[module_idP].pmch_stop_mtch[mbms_mch_i] != 2047) { + mtch_flag = 1; + if (UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch] != NULL) + mtch_mcs = UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch]->dataMCS_r9; + else + mtch_mcs = -1; + mch_lcid = (uint8_t)mbms_mch_i; + LOG_D(MAC,"mtch should be allocated:frame(%d),submframe(%d),num_sf_alloc(%d),mtch_mcs(%d),pmch_stop_mtch(%d),lcid(%d),msi_pmch(%d)\n",frameP,subframe,num_sf_alloc,mtch_mcs, + UE_mac_inst[module_idP].pmch_stop_mtch[mbms_mch_i],UE_mac_inst[module_idP].pmch_lcids[mbms_mch_i],UE_mac_inst[module_idP].msi_pmch); + } + } + } + UE_mac_inst[module_idP].common_num_sf_alloc = UE_mac_inst[module_idP].common_num_sf_alloc % ((num_sf_alloc-mbms_mch_i) /** commonSF_AllocPeriod *// common_mbsfn_period);//48; + + if(mtch_flag) + break; + } + if(msi_flag==1){ + for (l = 0; l < 8; l++) { + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) + continue; + + if ( (/*AJ*/ (/*V*/ ( /*U*/ (frameP %(4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9)) ) / 8 ) % ((8 <mch_SchedulingPeriod_r9) / 8 ) ) != 0 ){ + msi_flag=0; + LOG_D(MAC,"frameP %d subframeP %d reset(%d)\n",frameP, subframe, mbms_mch_i); + } + } + } +} + + // sf allocation is non-overlapping + if ((msi_flag==1) || (mcch_flag==1) || (mtch_flag==1)) { + LOG_D(MAC,"[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", + module_idP, frameP, subframe,l,j,msi_flag,mcch_flag,mtch_flag); + *sync_area=i; + } + + //if(msi_flag == 1) + // if((num_msi_per_CSA[mbms_mch_i]--)==0){ + // LOG_E(MAC,"Both MSI and MTCH Should be reset?\n"); + // msi_flag=mtch_flag=0; + //} + + + if ((mcch_flag == 1)) { // || (msi_flag==1)) + *mcch_active = 1; + } + + if ( (mcch_flag==1) || ((msi_flag==1) && (UE_mac_inst[module_idP].mcch_status==1)) ) { + if (msi_flag!=1) { + for (i=0; i<8; i++) + UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[i] = NULL; + + for (i=0; i<15; i++) + UE_mac_inst[module_idP].pmch_Config[i] = NULL; + + for (i=0; i<28 ; i++) { + UE_mac_inst[module_idP].pmch_lcids[i] = -1; + UE_mac_inst[module_idP].pmch_stop_mtch[i] = 2047; + UE_mac_inst[module_idP].msi_status_v[i] = 0; + } + } else { + for (i=0; i<28; i++) { + UE_mac_inst[module_idP].pmch_lcids[i] = -1; + UE_mac_inst[module_idP].pmch_stop_mtch[i] = 2047; + UE_mac_inst[module_idP].msi_status_v[i] = 0; + } + } + + return mcch_mcs; + } else if ((mtch_flag==1) && (UE_mac_inst[module_idP].msi_status_v[(mch_lcid > 27) ? 27 : mch_lcid] == 1)) { + return mtch_mcs; + } else { + return -1; + } + + + + // if(mcch_flag == 1 || msi_flag == 1 ){ + // *mcch_active = 1; + // return (mcch_mcs); + // }else if(mtch_flag == 1){ + // mtch_mcs=-1; + // return (mtch_mcs); + // } + + // return -1; + +} + + int ue_query_p_mch(module_id_t module_idP, uint32_t frameP, uint32_t subframe, int *mtch_active, int *msi_active, uint8_t *mch_lcid) { int i, j, mtch_mcs = -1; int mtch_flag = 0; @@ -1100,6 +1558,7 @@ int ue_query_p_mch(module_id_t module_idP, uint32_t frameP, uint32_t subframe, i return mtch_mcs; } + int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_t subframe, uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active) { int i = 0, j = 0, ii = 0, jj = 0, msi_pos = 0, mcch_mcs = -1, mtch_mcs = -1; int l =0; @@ -1162,6 +1621,11 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ ii = UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80 >> msi_pos); msi_pos++; } + if(msi_pos == subframe){ + UE_mac_inst[module_idP].common_num_sf_alloc=0; + mbms_mch_i=0; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } } } @@ -1170,6 +1634,14 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ case 1: if (UE_mac_inst[module_idP].tdd_Config == NULL) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) { + if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i+1]!=NULL){ + if( UE_mac_inst[module_idP].common_num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=1; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 1) { msi_flag = 1; } @@ -1188,6 +1660,14 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ case 2: if (UE_mac_inst[module_idP].tdd_Config == NULL) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) { + if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i+1]!=NULL){ + if( UE_mac_inst[module_idP].common_num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=2; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 2) { msi_flag = 1; } @@ -1219,6 +1699,14 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ } } else { // FDD if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) { + if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i+1]!=NULL){ + if( UE_mac_inst[module_idP].common_num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=3; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 3) { msi_flag = 1; } @@ -1255,6 +1743,14 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ case 6: if (UE_mac_inst[module_idP].tdd_Config == NULL) { if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) { + if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i+1]!=NULL){ + if( UE_mac_inst[module_idP].common_num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=6; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 4) { msi_flag = 1; } @@ -1286,6 +1782,14 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ } } else { // FDD if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) { + if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i+1]!=NULL){ + if( UE_mac_inst[module_idP].common_num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=5; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } + if (msi_pos == 5) { msi_flag = 1; } @@ -1317,6 +1821,13 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ } } else { // FDD if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) { + if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i+1]!=NULL){ + if( UE_mac_inst[module_idP].common_num_sf_alloc == UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9){ + msi_pos=6; + mbms_mch_i++; + LOG_D(MAC,"MSP, frameP %d subframeP %d msi_pos(%d) mbms_mch_i %d\n",frameP, subframe, msi_pos,mbms_mch_i); + } + } if (msi_pos == 6) { msi_flag = 1; } @@ -1351,6 +1862,14 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ break; }// end switch + if( (msi_flag == 1) || (mcch_flag == 1) || (mtch_flag == 1) ){ + UE_mac_inst[module_idP].common_num_sf_alloc++; + //if( (msi_flag!=1 && mcch_flag!=1) || (msi_flag!=1 && mcch_flag!=1 && mtch_flag!=1) ){ + //UE_mac_inst[module_idP].common_num_sf_alloc++; + //} + } + +#ifdef OLD // Acount for sf_allocable in CSA int num_sf_alloc = 0; @@ -1392,11 +1911,86 @@ int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_ } } } +#endif + +{ + // Acount for sf_allocable in Common SF Allocation + int num_sf_alloc = 0; + + for (l = 0; l < 8; l++) { + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) + continue; + + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) + continue; + + //int common_mbsfn_alloc_offset = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationOffset; + //long common_mbsfn_period = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationPeriod; + //long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9; + + uint32_t common_mbsfn_SubframeConfig = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.choice.oneFrame.buf[0]; + + for (j = 0; j < 6; j++) + num_sf_alloc += ((common_mbsfn_SubframeConfig & (0x80 >> j)) == (0x80 >> j)); + } + + + for (l = 0; l < 8; l++) { + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) + continue; + + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->subframeAllocation.present != LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) + continue; + + //int common_mbsfn_alloc_offset = UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationOffset; + long common_mbsfn_period = 1 << UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l]->radioframeAllocationPeriod; + long commonSF_AllocPeriod = 4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9; + + + if(msi_flag==1 && UE_mac_inst[module_idP].pmch_Config[mbms_mch_i] != NULL){ + LOG_D(MAC,"msi(%d) should be allocated:frame(%d),submframe(%d),num_sf_alloc(%d),sf_AllocEnd_r9(%ld),common_num_sf_alloc(%d)\n",mbms_mch_i,frameP,subframe,num_sf_alloc,UE_mac_inst[module_idP].pmch_Config[mbms_mch_i]->sf_AllocEnd_r9, + UE_mac_inst[module_idP].common_num_sf_alloc); + UE_mac_inst[module_idP].msi_current_alloc = UE_mac_inst[module_idP].common_num_sf_alloc;//num_sf_alloc; + UE_mac_inst[module_idP].msi_pmch = mbms_mch_i; + }else if(UE_mac_inst[module_idP].pmch_Config[mbms_mch_i] != NULL){ + if (UE_mac_inst[module_idP].pmch_stop_mtch[mbms_mch_i] >= UE_mac_inst[module_idP].common_num_sf_alloc/*num_sf_alloc*/) { + if (UE_mac_inst[module_idP].pmch_stop_mtch[mbms_mch_i] != 2047) { + mtch_flag = 1; + if (UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch] != NULL) + mtch_mcs = UE_mac_inst[module_idP].pmch_Config[UE_mac_inst[module_idP].msi_pmch]->dataMCS_r9; + else + mtch_mcs = -1; + mch_lcid = (uint8_t)mbms_mch_i; + LOG_D(MAC,"mtch should be allocated:frame(%d),submframe(%d),num_sf_alloc(%d),mtch_mcs(%d),pmch_stop_mtch(%d),lcid(%d),msi_pmch(%d)\n",frameP,subframe,num_sf_alloc,mtch_mcs, + UE_mac_inst[module_idP].pmch_stop_mtch[mbms_mch_i],UE_mac_inst[module_idP].pmch_lcids[mbms_mch_i],UE_mac_inst[module_idP].msi_pmch); + } + } + } + //LOG_D(MAC,"UE_mac_inst[module_idP].common_num_sf_alloc: %d num_sf_alloc %d mbms_mch_i %d commonSF_AllocPeriod %d common_mbsfn_period %d\n",UE_mac_inst[module_idP].common_num_sf_alloc,num_sf_alloc,mbms_mch_i,commonSF_AllocPeriod,common_mbsfn_period); + UE_mac_inst[module_idP].common_num_sf_alloc = UE_mac_inst[module_idP].common_num_sf_alloc % ((num_sf_alloc* commonSF_AllocPeriod-mbms_mch_i) / common_mbsfn_period);//48; + + + if(mtch_flag) + break; + } + if(msi_flag==1){ + for (l = 0; l < 8; l++) { + if (UE_mac_inst[module_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[l] == NULL) + continue; + + if ( (/*AJ*/ (/*V*/ ( /*U*/ (frameP %(4 << UE_mac_inst[module_idP].commonSF_AllocPeriod_r9)) ) / 8 ) % ((8 <mch_SchedulingPeriod_r9) / 8 ) ) != 0 ){ + msi_flag=0; + LOG_D(MAC,"frameP %d subframeP %d reset(%d)\n",frameP, subframe, mbms_mch_i); + } + } + } + +} // sf allocation is non-overlapping if ((msi_flag==1) || (mcch_flag==1) || (mtch_flag==1)) { - LOG_D(MAC,"[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n", - module_idP, frameP, subframe,l,j,msi_flag,mcch_flag,mtch_flag); + LOG_D(MAC,"[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d x %d\n", + module_idP, frameP, subframe,l,j,msi_flag,mcch_flag,mtch_flag,UE_mac_inst[module_idP].common_num_sf_alloc); *sync_area=i; break; } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 50fa64b6ce..77aedfa24a 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1395,8 +1395,9 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, if (NCS == 0) return nb_preambles; else { r = L_ra/NCS; - printf(" found_sequences %u\n", (nb_preambles/r)); - return (nb_preambles/r); + found_sequences = (nb_preambles/r) + (nb_preambles%r!=0); //ceil(nb_preambles/r) + printf(" found_sequences %u\n", found_sequences); + return (found_sequences); } } else{ @@ -1859,92 +1860,156 @@ uint16_t Table_61412[28][2] = {{2,30},{2,40},{2,50},{2,64},{2,78},{2,99},{2,120} uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51311[Imcs][0]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_51312[Imcs][0]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51313[Imcs][0]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,3])\n", table_idx); + AssertFatal(0, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx); } } uint32_t nr_get_code_rate_dl(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51311[Imcs][1]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_51312[Imcs][1]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51313[Imcs][1]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,3])\n", table_idx); + AssertFatal(0, "Invalid MCS table index %d (expected in range [0,2])\n", table_idx); } } uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51311[Imcs][0]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_51312[Imcs][0]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51313[Imcs][0]); break; case 3: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_61411[Imcs][0]); break; case 4: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_61412[Imcs][0]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,2])\n", table_idx); + AssertFatal(0, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx); } } uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx) { switch(table_idx) { case 0: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 0 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51311[Imcs][1]); break; case 1: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 1 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_51312[Imcs][1]); break; case 2: + if (Imcs > 28) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 2 (expected range [0,28])\n", Imcs); + Imcs = 28; + } return (Table_51313[Imcs][1]); break; case 3: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 3 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_61411[Imcs][1]); break; case 4: + if (Imcs > 27) { + LOG_E(MAC, "Invalid MCS index %d for MCS table 4 (expected range [0,27])\n", Imcs); + Imcs = 27; + } return (Table_61412[Imcs][1]); break; default: - AssertFatal(0, "Invalid MCS table index %d (expected in range [1,2])\n", table_idx); + AssertFatal(0, "Invalid MCS table index %d (expected in range [0,4])\n", table_idx); } } @@ -2119,9 +2184,9 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) { LOG_I(PHY,"PUSH PT-RS is not present.\n"); return -1; } else if (N_RB >= nrb0 && N_RB < nrb1) - return 0; + return 2; else - return 1; + return 4; } uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 5a9620ed01..bc98e16d39 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -34,7 +34,6 @@ #include "NR_MAC_UE/mac_proto.h" #include "NR_MAC-CellGroupConfig.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" -#include "SCHED_NR/phy_frame_config_nr.h" int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, @@ -326,6 +325,84 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, } +/** \brief This function is relavant for the UE procedures for control. It loads the search spaces, the BWPs and the CORESETs into the MAC instance and + \brief performs assert checks on the relevant RRC configuration. + @param NR_UE_MAC_INST_t mac: pointer to local MAC instance + @returns void + */ +void config_control_ue(NR_UE_MAC_INST_t *mac){ + + uint8_t bwp_id = 1, coreset_id = 1, ss_id; + NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; + AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n"); + AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count); + + NR_BWP_DownlinkCommon_t *bwp_Common = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Common; + AssertFatal(bwp_Common != NULL, "bwp_Common is null\n"); + + NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Dedicated; + AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n"); + + NR_SetupRelease_PDCCH_Config_t *pdcch_Config = dl_bwp_Dedicated->pdcch_Config; + AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n"); + + NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; + AssertFatal(pdcch_ConfigCommon != NULL, "pdcch_ConfigCommon is null\n"); + AssertFatal(pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, "ra_SearchSpace must be available in DL BWP\n"); + + struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + AssertFatal(commonSearchSpaceList != NULL, "commonSearchSpaceList is null\n"); + AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH CSS list has 0 elements\n"); + + struct NR_PDCCH_Config__controlResourceSetToAddModList *controlResourceSetToAddModList = pdcch_Config->choice.setup->controlResourceSetToAddModList; + AssertFatal(controlResourceSetToAddModList != NULL, "controlResourceSetToAddModList is null\n"); + AssertFatal(controlResourceSetToAddModList->list.count == 1, "controlResourceSetToAddModList->list.count=%d\n", controlResourceSetToAddModList->list.count); + AssertFatal(controlResourceSetToAddModList->list.array[0] != NULL, "coreset[0][0] is null\n"); + + struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList; + AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n"); + AssertFatal(searchSpacesToAddModList->list.count > 0, "list of UE specifically configured Search Spaces is empty\n"); + AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count); + + struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList; + AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n"); + AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count); + + // check pdcch_Config, pdcch_ConfigCommon and DL BWP + mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; + mac->coreset[bwp_id - 1][coreset_id - 1] = controlResourceSetToAddModList->list.array[0]; + + // Check dedicated UL BWP and pass to MAC + mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[0]; + AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n"); + + // check available Search Spaces in the searchSpacesToAddModList and pass to MAC + // note: the network configures at most 10 Search Spaces per BWP per cell (including UE-specific and common Search Spaces). + for (ss_id = 0; ss_id < searchSpacesToAddModList->list.count; ss_id++) { + NR_SearchSpace_t *ss = searchSpacesToAddModList->list.array[ss_id]; + AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); + AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); + AssertFatal(*ss->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); + AssertFatal(ss->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n"); + AssertFatal(ss->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n"); + mac->SSpace[0][0][ss_id] = ss; + } + + // Check available CSSs in the commonSearchSpaceList (list of additional common search spaces) + // note: commonSearchSpaceList SIZE(1..4) + for (int css_id = 0; css_id < commonSearchSpaceList->list.count; css_id++) { + NR_SearchSpace_t *css = commonSearchSpaceList->list.array[css_id]; + AssertFatal(css->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); + AssertFatal(*css->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); + AssertFatal(css->searchSpaceId != 0, "css->searchSpaceId is 0\n"); + AssertFatal(css->searchSpaceType != NULL, "css->searchSpaceType is null\n"); + AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n"); + AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n"); + mac->SSpace[0][0][ss_id] = css; + ss_id++; + } +} + int nr_rrc_mac_config_req_ue( module_id_t module_id, int cc_idP, @@ -338,16 +415,16 @@ int nr_rrc_mac_config_req_ue( NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - // NR_ServingCellConfig_t *serving_cell_config = spcell_configP->spCellConfigDedicated; // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. - if(mibP != NULL){ mac->mib = mibP; // update by every reception } if(cell_group_config != NULL ){ + mac->scg = cell_group_config; mac->servCellIndex = *cell_group_config->spCellConfig->servCellIndex; + config_control_ue(mac); if (cell_group_config->spCellConfig->reconfigurationWithSync) { mac->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; @@ -355,7 +432,6 @@ int nr_rrc_mac_config_req_ue( mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); } - mac->scg = cell_group_config; /* if(mac_cell_group_configP != NULL){ @@ -420,8 +496,8 @@ int nr_rrc_mac_config_req_ue( } } */ - } - + } + return 0; } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 5775e5bfb9..e45f6a9b69 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -178,7 +178,6 @@ typedef struct { SFN_C_TYPE type0_pdcch_ss_sfn_c; uint32_t type0_pdcch_ss_n_c; uint32_t type0_pdcch_consecutive_slots; - int rnti_type; /* PDUs */ /// Outgoing CCCH pdu for PHY @@ -222,11 +221,6 @@ typedef struct { uint32_t RA_tx_frame; /// Random-access variable for window calculation (subframe of last change in window counter) uint8_t RA_tx_subframe; - /// Scheduled RX frame for RA Msg2 - uint16_t msg2_rx_frame; - /// Scheduled RX slot for RA Msg2 - uint16_t msg2_rx_slot; - /// Random-access Group B maximum path-loss /// Random-access variable for backoff (frame of last change in backoff counter) uint32_t RA_backoff_frame; /// Random-access variable for backoff (subframe of last change in backoff counter) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index af9822a5df..bae8e0d3c0 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -39,6 +39,7 @@ #include "PHY/defs_UE.h" #include "openair2/LAYER2/RLC/rlc.h" #include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "executables/softmodem-common.h" static NR_UE_MAC_INST_t *nr_ue_mac_inst; @@ -59,7 +60,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); - nr_ip_over_LTE_DRB_preconfiguration(); + nr_DRB_preconfiguration(); } } else LOG_I(MAC,"Running without RRC instance\n"); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 56ae14f98b..351bcc292f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -62,9 +62,8 @@ #include "NR_MAC_COMMON/nr_mac.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" -extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9]; extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; -extern const uint16_t nr_slots_per_frame[5]; +extern const uint8_t nr_slots_per_frame[5]; //extern uint8_t nfapi_mode; @@ -360,11 +359,11 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t sdu_lcids[NB_RB_MAX] = {0}; uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848, header_length_total, num_sdus, offset, preambleTransMax, mac_ce_len; + int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len; AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n"); - if (UE_mode == PRACH && prach_resources->init_msg1) { + if (UE_mode < PUSCH && prach_resources->init_msg1) { LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active); @@ -449,7 +448,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, nr_get_RA_window(mac); // Fill in preamble and PRACH resources - if (mac->generate_nr_prach) + if (mac->generate_nr_prach == 1) nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated); offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer @@ -471,7 +470,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, payload[offset + j] = 0; // mac_pdu[offset + j] = 0; } } - } else { // RACH is active + } else if (mac->RA_window_cnt != -1) { // RACH is active //////////////////////////////////////////////////////////////// /////* Random Access Response reception (5.1.4 TS 38.321) *///// @@ -482,7 +481,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // - handle beam failure recovery request // - handle DL assignment on PDCCH for RA-RNTI // - handle backoff and raResponseWindow params - // - disabled contention resolution as OAI NSA is contention-free based // LOG_D(MAC, "[MAC][UE %d][RAPROC] frame %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n", // mod_id, frame, nr_tti_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe); @@ -495,12 +493,13 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, if (mac->RA_window_cnt >= 0 && mac->RA_RAPID_found == 1) { - // mac->ra_state = WAIT_CONTENTION_RESOLUTION; - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR successfully received \n", mod_id, frame, nr_tti_tx); + mac->RA_window_cnt = -1; + mac->ra_state = RA_SUCCEEDED; + LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR successfully received \n", mod_id, frame, nr_tti_tx); } else if (mac->RA_window_cnt == 0 && !mac->RA_RAPID_found) { - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception failed \n", mod_id, frame, nr_tti_tx); + LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception failed \n", mod_id, frame, nr_tti_tx); mac->ra_state = RA_UE_IDLE; mac->RA_PREAMBLE_TRANSMISSION_COUNTER++; @@ -572,21 +571,21 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // mac->RA_tx_subframe = nr_tti_tx; // Fill in preamble and PRACH resources - if (mac->generate_nr_prach) + if (mac->generate_nr_prach == 1) nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); } else { mac->RA_window_cnt--; - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception not successful, (RA window count %d) \n", + LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception not successful, (RA window count %d) \n", mod_id, frame, nr_tti_tx, mac->RA_window_cnt); // Fill in preamble and PRACH resources - if (mac->generate_nr_prach) + if (mac->generate_nr_prach == 1) nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); } @@ -616,28 +615,28 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac){ mac->RA_window_cnt = mac->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB switch (ra_ResponseWindow) { - case 0: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: mac->RA_window_cnt += 1; break; - case 1: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: mac->RA_window_cnt += 2; break; - case 2: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: mac->RA_window_cnt += 4; break; - case 3: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: mac->RA_window_cnt += 8; break; - case 4: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: mac->RA_window_cnt += 10; break; - case 5: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: mac->RA_window_cnt += 20; break; - case 6: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: mac->RA_window_cnt += 40; break; - case 7: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: mac->RA_window_cnt += 80; break; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 53263747fc..2285fc5999 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -46,6 +46,8 @@ #endif #define LOG_DCI_PARM(a...) LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci)" a) +// #define DEBUG_DCI + dci_pdu_rel15_t *def_dci_pdu_rel15; void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) { @@ -62,217 +64,261 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd } +void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id, uint8_t dci_format){ + + uint16_t monitoringSymbolsWithinSlot; + uint8_t bwp_id = 1, coreset_id = 1; + int sps; + def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t)); + AssertFatal(mac->scc != NULL, "scc is null\n"); + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_BWP_DownlinkCommon_t *bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common; + NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; + NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id]; + + // DCI format configuration + rel15->dci_format = dci_format; + + // CORESET configuration + NR_ControlResourceSet_t *coreset = mac->coreset[bwp_id - 1][coreset_id - 1]; + rel15->coreset.duration = coreset->duration; + for (int i = 0; i < 6; i++) + rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i]; + rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; + if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) { + struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved; + rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize); + rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize); + AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n"); + rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId; + } else { + rel15->coreset.RegBundleSize = 0; + rel15->coreset.InterleaverSize = 0; + rel15->coreset.ShiftIndex = 0; + } + rel15->coreset.CoreSetType = 1; + rel15->coreset.precoder_granularity = coreset->precoderGranularity; + + // Scrambling RNTI + if (coreset->pdcch_DMRS_ScramblingID) { + rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID; + rel15->coreset.scrambling_rnti = mac->t_crnti; + } else { + rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId; + rel15->coreset.scrambling_rnti = 0; + } + + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: ss_id %d bwp %p bwp_Id %d controlResourceSetId %d\n", ss_id, mac->DLbwp[bwp_id - 1], mac->DLbwp[bwp_id - 1]->bwp_Id, coreset->controlResourceSetId); + #endif + + // loop over RNTI type and configure resource allocation for DCI + switch(rnti_type) { + case NR_RNTI_C: + // we use DL BWP dedicated + sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; + // for SPS=14 8 MSBs in positions 13 down to 6 + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->crnti; + rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); + rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; + rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_C, rel15->BWPSize, bwp_id); + break; + case NR_RNTI_RA: + // we use the initial DL BWP + sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->ra_rnti; + rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); + rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; + rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_RA, rel15->BWPSize, bwp_id); + break; + case NR_RNTI_P: + break; + case NR_RNTI_CS: + break; + case NR_RNTI_TC: + break; + case NR_RNTI_SP_CSI: + break; + case NR_RNTI_SI: + break; + case NR_RNTI_SFI: + break; + case NR_RNTI_INT: + break; + case NR_RNTI_TPC_PUSCH: + break; + case NR_RNTI_TPC_PUCCH: + break; + case NR_RNTI_TPC_SRS: + break; + default: + break; + } + for (int i = 0; i < sps; i++) { + if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { + rel15->coreset.StartSymbolIndex = i; + break; + } + } + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: rnti_type %d BWPSize %d BWPStart %d rel15->SubcarrierSpacing %d rel15->dci_format %d rel15->dci_length %d sps %d monitoringSymbolsWithinSlot %d \n", + rnti_type, + rel15->BWPSize, + rel15->BWPStart, + rel15->SubcarrierSpacing, + rel15->dci_format, + rel15->dci_length, + sps, + monitoringSymbolsWithinSlot); + #endif + // add DCI + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; + dl_config->number_pdus = dl_config->number_pdus + 1; +} + void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, frame_t frame, int slot) { - def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t)); - - NR_BWP_Downlink_t *bwp; - NR_BWP_DownlinkCommon_t *bwp_Common; - NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated; - NR_SetupRelease_PDCCH_Config_t *pdcch_Config; - NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon; - struct NR_PDCCH_Config__controlResourceSetToAddModList *controlResourceSetToAddModList; - struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList; - struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList; - NR_SearchSpace_t *NR_SearchSpace; - NR_ControlResourceSet_t *coreset; - - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; + int ss_id; + uint8_t bwp_id = 1, coreset_id = 1; NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; + NR_BWP_Downlink_t *bwp = mac->DLbwp[bwp_id - 1]; - uint8_t bwp_id = 1; - int ss_id, sps; + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] ra_rnti %p (%x) crnti %p (%x) t_crnti %p (%x)\n", &mac->ra_rnti, mac->ra_rnti, &mac->crnti, mac->crnti, &mac->t_crnti, mac->t_crnti); + #endif - // get PDCCH configuration(s) (Coreset, SearchSpace, etc...) from BWP Dedicated in serving cell config dedicated (scd) - // get BWP 1, Coreset ID 0, SearchSpace ID 0 (i.e. configured in MIB and in ServingCellConfigCommon) + // loop over all available SS for BWP ID 1, CORESET ID 1 + for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id] != NULL; ss_id++){ + NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id]; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + NR_BWP_DownlinkCommon_t *bwp_Common = bwp->bwp_Common; + NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; + struct NR_PhysicalCellGroupConfig *phy_cgc = mac->scg->physicalCellGroupConfig; + switch (ss->searchSpaceType->present){ + case NR_SearchSpace__searchSpaceType_PR_common: + // this is for CSSs, we use BWP common and pdcch_ConfigCommon - // Check dedicated DL BWP - if (mac->DLbwp[0] == NULL) { - NR_SearchSpace_t *ss; - int ss_id = 0; - - AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n"); - AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count); - mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; - - dl_bwp_Dedicated = mac->DLbwp[0]->bwp_Dedicated; - AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n"); - - bwp_Common = mac->DLbwp[0]->bwp_Common; - AssertFatal(bwp_Common != NULL, "bwp_Common is null\n"); - - pdcch_Config = dl_bwp_Dedicated->pdcch_Config; - AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n"); - - pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; - AssertFatal(pdcch_ConfigCommon != NULL, "pdcch_ConfigCommon is null\n"); - AssertFatal(pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, "ra_SearchSpace must be available in DL BWP\n"); - - controlResourceSetToAddModList = pdcch_Config->choice.setup->controlResourceSetToAddModList; - AssertFatal(controlResourceSetToAddModList != NULL, "controlResourceSetToAddModList is null\n"); - - AssertFatal(controlResourceSetToAddModList->list.count == 1, "controlResourceSetToAddModList->list.count=%d\n", controlResourceSetToAddModList->list.count); - - mac->coreset[0][0] = controlResourceSetToAddModList->list.array[0]; - coreset = mac->coreset[0][0]; - AssertFatal(coreset != NULL, "coreset[0][0] is null\n"); - - searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList; - AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n"); - AssertFatal(searchSpacesToAddModList->list.count > 0, "searchSpacesToAddModList is empty\n"); - AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count); - - for (int i = 0; i < searchSpacesToAddModList->list.count; i++) { - ss = searchSpacesToAddModList->list.array[i]; - AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); - AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); - AssertFatal(*ss->controlResourceSetId == coreset->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); - mac->SSpace[0][0][ss_id] = ss; - ss_id++; - } - } - - // Check dedicated UL BWP - if (mac->ULbwp[0] == NULL) { - uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList; - AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n"); - AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count); - mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[bwp_id - 1]; - AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n"); - } - - bwp = mac->DLbwp[0]; - bwp_Common = bwp->bwp_Common; - pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; - dl_bwp_Dedicated = bwp->bwp_Dedicated; - pdcch_Config = dl_bwp_Dedicated->pdcch_Config; - searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList; - - // check USSs - ss_id = 0; - NR_SearchSpace = mac->SSpace[0][0][ss_id]; - while(NR_SearchSpace != NULL && ss_id < searchSpacesToAddModList->list.count) { - AssertFatal(NR_SearchSpace->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n"); - AssertFatal(NR_SearchSpace->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n"); - ss_id++; - } - - if (mac->crnti > 0) { - - NR_SearchSpace_t *css; - NR_SearchSpace_t *uss = NULL; - NR_ServingCellConfigCommon_t *scc; - NR_SearchSpaceId_t ra_SearchSpaceId; - rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; - uint16_t monitoringSymbolsWithinSlot; - uint8_t add_dci = 1; - - AssertFatal(mac->scc != NULL, "scc is null\n"); - - scc = mac->scc; - rel15->dci_format = NR_DL_DCI_FORMAT_1_1; - - // CoReSet configuration - coreset = mac->coreset[0][0]; - rel15->coreset.duration = coreset->duration; - for (int i = 0; i < 6; i++) - rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i]; - - rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; - - if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) { - struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved; - rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize); - rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize); - AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n"); - rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId; - } else { - rel15->coreset.RegBundleSize = 0; - rel15->coreset.InterleaverSize = 0; - rel15->coreset.ShiftIndex = 0; - } - - rel15->coreset.CoreSetType = 1; - rel15->coreset.precoder_granularity = coreset->precoderGranularity; - - if (mac->ra_state == WAIT_RAR){ - - NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; - struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH CSS list has 0 elements\n"); - - ra_SearchSpaceId = *pdcch_ConfigCommon->choice.setup->ra_SearchSpace; - - // fetch the CSS for RA from the CSS list - for (int i = 0; i < commonSearchSpaceList->list.count; i++) { - css = commonSearchSpaceList->list.array[i]; - if(css->searchSpaceId == ra_SearchSpaceId) - break; - } - - // check CSSs - if(css != NULL) { - AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n"); - AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n"); - } - - if (frame == mac->msg2_rx_frame && slot == mac->msg2_rx_slot){ - sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; - monitoringSymbolsWithinSlot = (css->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (css->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = mac->ra_rnti; - rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); // NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); - rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); - for (int i = 0; i < sps; i++) - if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { - rel15->coreset.StartSymbolIndex = i; - break; - } - fill_dci_search_candidates(css, rel15); - } else { - add_dci = 0; + // Fetch configuration for searchSpaceZero + // note: The search space with the SearchSpaceId = 0 identifies the search space configured via PBCH (MIB) and in ServingCellConfigCommon (searchSpaceZero). + if (pdcch_ConfigCommon->choice.setup->searchSpaceZero){ + LOG_D(MAC, "[DCI_CONFIG] Configure SearchSpace#0 of the initial BWP\n"); + LOG_W(MAC, "[DCI_CONFIG] This should not be available yet..."); } - } else if (mac->ra_state == WAIT_CONTENTION_RESOLUTION){ - - rel15->rnti = mac->t_crnti; - - } else { - - rel15->rnti = mac->crnti; - rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); - rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); - // get UE-specific search space - for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[0][0][ss_id] != NULL; ss_id++){ - uss = mac->SSpace[0][0][ss_id]; - if (uss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) break; - } - AssertFatal(ss_id < FAPI_NR_MAX_SS_PER_CORESET, "couldn't find a UE-specific SS\n"); - sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; - // for SPS=14 8 MSBs in positions 13 down to 6 - monitoringSymbolsWithinSlot = (uss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (uss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - for (int i = 0; i < sps; i++) - if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { - rel15->coreset.StartSymbolIndex = i; - break; + if (ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0){ + // check available SS IDs + if (pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type1-PDCCH common random access search space\n"); + switch(mac->ra_state){ + case WAIT_RAR: + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_RA, ss_id, NR_DL_DCI_FORMAT_1_0); + fill_dci_search_candidates(ss, rel15); + break; + case WAIT_CONTENTION_RESOLUTION: + rel15->rnti = mac->t_crnti; + break; + default: + break; + } + } } - fill_dci_search_candidates(uss, rel15); - } + if (pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG + LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ + // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG + LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ + // Configure monitoring of PDCCH candidates in Type2-PDCCH common search space on the MCG + LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (phy_cgc){ + if (phy_cgc->cs_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + if (phy_cgc->ext1){ + if (phy_cgc->ext1->mcs_C_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + } + } + } // end DCI 00 and 01 + // DCI 2_0 + if (ss->searchSpaceType->choice.common->dci_Format2_0){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_0 with CRC scrambled by SFI-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } + // DCI 2_1 + if (ss->searchSpaceType->choice.common->dci_Format2_1){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_1 with CRC scrambled by INT-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } + // DCI 2_2 + if (ss->searchSpaceType->choice.common->dci_Format2_2){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_2 with CRC scrambled by TPC-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } + // DCI 2_3 + if (ss->searchSpaceType->choice.common->dci_Format2_3){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_3 with CRC scrambled by TPC-SRS-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } - // Scrambling RNTI - if (coreset->pdcch_DMRS_ScramblingID) { - rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID; - rel15->coreset.scrambling_rnti = mac->t_crnti; - } else { - rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId; - rel15->coreset.scrambling_rnti = 0; - } + break; + case NR_SearchSpace__searchSpaceType_PR_ue_Specific: + // this is an USS + if (ss->searchSpaceType->choice.ue_Specific){ + if(ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1){ + // Monitors DCI 01 and 11 scrambled with C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI + if (get_softmodem_params()->phy_test == 1 && mac->crnti > 0) { + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in the user specific search space\n"); + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C, ss_id, NR_DL_DCI_FORMAT_1_1); + fill_dci_search_candidates(ss, rel15); - if (add_dci){ - dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - dl_config->number_pdus = dl_config->number_pdus + 1; + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] ss %d ue_Specific %p searchSpaceType->present %d dci_Formats %d\n", + ss_id, + ss->searchSpaceType->choice.ue_Specific, + ss->searchSpaceType->present, + ss->searchSpaceType->choice.ue_Specific->dci_Formats); + #endif + } + if (phy_cgc){ + if (phy_cgc->cs_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + if (phy_cgc->sp_CSI_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by SP-CSI-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + if (phy_cgc->ext1){ + if (phy_cgc->ext1->mcs_C_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + } + } + } + } + break; + default: + AssertFatal(1 == 0, "[DCI_CONFIG] Unrecognized search space type..."); + break; } } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8e5206f2f5..6492c2cc33 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -757,193 +757,183 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } */ } - } else if (ul_info && ul_info->slot_tx == 8) { - module_id_t mod_id = ul_info->module_id; - uint32_t gNB_index = ul_info->gNB_index; - int cc_id = ul_info->cc_id; - frame_t rx_frame = ul_info->frame_rx; - slot_t rx_slot = ul_info->slot_rx; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + } else if (ul_info) { - // program PUSCH. this should actually be done upon reception of an UL DCI - nr_dcireq_t dcireq; - nr_scheduled_response_t scheduled_response; + if (get_softmodem_params()->phy_test && ul_info->slot_tx == 8) { // ULSCH is handled only in phy-test mode (consistently with OAI gNB) - //--------------------------Temporary configuration-----------------------------// - uint16_t rnti = 0x1234; - uint32_t rb_size = 50; - uint32_t rb_start = 0; - uint8_t nr_of_symbols = 11; - uint8_t start_symbol_index = 0; - uint8_t nrOfLayers = 1; - uint8_t mcs_index = 9; - uint8_t mcs_table = 0; - uint8_t harq_process_id = 0; - uint8_t rv_index = 0; - uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); - uint8_t dmrs_config_type = 0; - uint8_t ptrs_mcs1 = 2; - uint8_t ptrs_mcs2 = 4; - uint8_t ptrs_mcs3 = 10; - uint16_t n_rb0 = 25; - uint16_t n_rb1 = 75; - uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, mcs_table); - uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size); - //------------------------------------------------------------------------------// + uint8_t nb_dmrs_re_per_rb; + uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; + uint8_t data_existing = 0; + uint16_t TBS_bytes; + uint32_t TBS; + int i; - dcireq.module_id = mod_id; - dcireq.gNB_index = gNB_index; - dcireq.cc_id = cc_id; - dcireq.frame = rx_frame; - dcireq.slot = rx_slot; + module_id_t mod_id = ul_info->module_id; + uint32_t gNB_index = ul_info->gNB_index; + int cc_id = ul_info->cc_id; + frame_t rx_frame = ul_info->frame_rx; + slot_t rx_slot = ul_info->slot_rx; + frame_t frame_tx = ul_info->frame_tx; + slot_t slot_tx = ul_info->slot_tx; + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + uint8_t access_mode = SCHEDULED_ACCESS; - scheduled_response.dl_config = NULL; - scheduled_response.ul_config = &dcireq.ul_config_req; - scheduled_response.tx_request = NULL; - scheduled_response.module_id = mod_id; - scheduled_response.CC_id = cc_id; - scheduled_response.frame = rx_frame; - scheduled_response.slot = rx_slot; + // program PUSCH. this should actually be done upon reception of an UL DCI + nr_dcireq_t dcireq; + nr_scheduled_response_t scheduled_response; + fapi_nr_tx_request_t tx_req; + fapi_nr_tx_request_body_t tx_req_body; - scheduled_response.ul_config->slot = ul_info->slot_tx; - scheduled_response.ul_config->number_pdus = 1; - scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_start = rb_start; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nr_of_symbols = nr_of_symbols; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = l_prime_mask << start_symbol_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_index = mcs_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nrOfLayers = nrOfLayers; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_process_id; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t)); - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + //--------------------------Temporary configuration-----------------------------// + uint16_t rnti = 0x1234; + uint32_t rb_size = 50; + uint32_t rb_start = 0; + uint8_t nr_of_symbols = 11; + uint8_t start_symbol_index = 0; + uint8_t nrOfLayers = 1; + uint8_t mcs_index = 9; + uint8_t mcs_table = 0; + uint8_t harq_process_id = 0; + uint8_t rv_index = 0; + uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); + uint8_t dmrs_config_type = 0; + uint8_t ptrs_mcs1 = 2; + uint8_t ptrs_mcs2 = 4; + uint8_t ptrs_mcs3 = 10; + uint16_t n_rb0 = 25; + uint16_t n_rb1 = 75; + uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, mcs_table); + uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size); + uint8_t no_data_in_dmrs = 1; + uint16_t number_dmrs_symbols = 0; + uint16_t ul_dmrs_symb_pos = l_prime_mask << start_symbol_index; + //------------------------------------------------------------------------------// - if (1 << ptrs_time_density >= nr_of_symbols) { - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + for (i = start_symbol_index; i < start_symbol_index + nr_of_symbols; i++) { + if((ul_dmrs_symb_pos >> i) & 0x01) + number_dmrs_symbols += 1; + } + + if(no_data_in_dmrs) + nb_dmrs_re_per_rb = 12; + else + nb_dmrs_re_per_rb = ((dmrs_config_type == pusch_dmrs_type1) ? 6:4); + + TBS = nr_compute_tbs(nr_get_Qm_ul(mcs_index, 0), + nr_get_code_rate_ul(mcs_index, 0), + rb_size, + nr_of_symbols, + nb_dmrs_re_per_rb*number_dmrs_symbols, + 0, + 0, + nrOfLayers); + TBS_bytes = TBS/8; + + if (IS_SOFTMODEM_NOS1){ + // Getting IP traffic to be transmitted + data_existing = nr_ue_get_sdu(mod_id, + cc_id, + frame_tx, + slot_tx, + 0, + ulsch_input_buffer, + TBS_bytes, + &access_mode); + } + + //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity + if (!IS_SOFTMODEM_NOS1 || !data_existing) { + //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid + //and block this traffic from being forwarded to the upper layers at the gNB + LOG_D(PHY, "Random data to be tranmsitted: \n"); + + //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) + //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should + //have a valid LCID (nr_process_mac_pdu function) + ulsch_input_buffer[0] = 0x31; + + for (i = 1; i < TBS_bytes; i++) { + ulsch_input_buffer[i] = (unsigned char) rand(); + //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); + } + } + +#ifdef DEBUG_MAC_PDU + + LOG_D(PHY, "Is data existing ?: %d \n", data_existing); + LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS_bytes); + for (i = 0; i < TBS_bytes; i++) { + printf("%02x", ulsch_input_buffer[i]); + } + printf("\n"); + +#endif + + dcireq.module_id = mod_id; + dcireq.gNB_index = gNB_index; + dcireq.cc_id = cc_id; + dcireq.frame = rx_frame; + dcireq.slot = rx_slot; + + scheduled_response.dl_config = NULL; + scheduled_response.ul_config = &dcireq.ul_config_req; + // Config UL TX PDU + tx_req.slot = slot_tx; + tx_req.sfn = frame_tx; + // tx_req->tx_config // TbD + tx_req.number_of_pdus = 1; + tx_req_body.pdu_length = TBS_bytes; + tx_req_body.pdu_index = 0; + tx_req_body.pdu = ulsch_input_buffer; + + scheduled_response.tx_request = &tx_req; + scheduled_response.tx_request->tx_request_body = &tx_req_body; + scheduled_response.module_id = mod_id; + scheduled_response.CC_id = cc_id; + scheduled_response.frame = rx_frame; + scheduled_response.slot = rx_slot; + + scheduled_response.ul_config->slot = ul_info->slot_tx; + scheduled_response.ul_config->number_pdus = 1; + scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_start = rb_start; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nr_of_symbols = nr_of_symbols; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol_index; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = ul_dmrs_symb_pos; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_index = mcs_index; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nrOfLayers = nrOfLayers; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_process_id; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t)); + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + + if (1 << ptrs_time_density >= nr_of_symbols) { + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } + + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ + mac->if_module->scheduled_response(&scheduled_response); + } + + // TODO: expand + // Note: Contention resolution is currently not active + if (mac->RA_contention_resolution_timer_active == 1) + ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx); } - - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&scheduled_response); - } - - // TODO: expand - // Note: Contention resolution is currently not active - if (mac->RA_contention_resolution_timer_active == 1) - ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx); } - return UE_CONNECTION_OK; } -// Notes: -// - Type1-PDCCH CSS configuration from ra-SearchSpace. -// - Msg2 is scheduled in the mixed slot or in the last dl slot if they are allowed by the Type 1 Common Search Space configuration -// todo: -// - if Type1-PDCCH CSS is not configured in RRC message (Coreset and SearchSpace), UE searches in Type 0 PDCCH CSS. -void nr_ue_msg2_scheduler(module_id_t mod_id, - uint16_t rach_frame, - uint16_t rach_slot, - uint16_t *msg2_frame, - uint16_t *msg2_slot){ - - uint8_t bwp_id = 1; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_CellGroupConfig_t *scg = mac->scg; - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; - NR_SearchSpace_t *ss; - struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - uint8_t mu = *scc->ssbSubcarrierSpacing; - uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; - uint8_t slot_window, slot_limit, frame_limit; - uint16_t start_next_period, monitoring_slot_period, monitoring_offset; - - // number of mixed slot or of last dl slot if there is no mixed slot - uint16_t last_dl_slot_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; - uint16_t nr_dl_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; - uint16_t nr_ul_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - - // lenght of tdd period in slots - uint16_t tdd_period_slot = last_dl_slot_period + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - - AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH common SearchSpace list has 0 elements\n"); - - LOG_D(MAC, "Frame %d, Slot %d: Scheduling Msg2 reception \n", rach_frame, rach_slot); - - // Common searchspace list - for (int i = 0; i < commonSearchSpaceList->list.count; i++) { - ss = commonSearchSpaceList->list.array[i]; - if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace) - // retrieving ra pdcch monitoring period and offset - find_monitoring_periodicity_offset_common(ss, &monitoring_slot_period, &monitoring_offset); - } - - if (nr_dl_symbols == 0) - last_dl_slot_period--; - if ((nr_dl_symbols > 0) || (nr_ul_symbols > 0)) - tdd_period_slot++; - - // computing start of next period - start_next_period = (rach_slot - (rach_slot % tdd_period_slot) + tdd_period_slot) % nr_slots_per_frame[mu]; - *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot - *msg2_frame = (*msg2_slot > rach_slot) ? rach_frame : (rach_frame +1); - - switch(response_window){ - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: - slot_window = 1; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: - slot_window = 2; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: - slot_window = 4; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: - slot_window = 8; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: - slot_window = 10; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: - slot_window = 20; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: - slot_window = 40; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: - slot_window = 80; - break; - default: - AssertFatal(1==0,"Invalid response window value %d\n",response_window); - } - AssertFatal(slot_window<=nr_slots_per_frame[mu], "Msg2 response window needs to be lower or equal to 10ms"); - - // slot and frame limit to transmit msg2 according to response window - slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu]; - frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); - - // go to previous slot if the current scheduled slot is beyond the response window - // and if the slot is not among the PDCCH monitored ones (38.213 10.1) - while ((*msg2_slot > slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu] + *msg2_slot - monitoring_offset) % monitoring_slot_period != 0)) { - if((*msg2_slot % tdd_period_slot) > 0) - (*msg2_slot)--; - else - AssertFatal(1 == 0, "No available DL slot to schedule reception of msg2 has been found"); - } - LOG_D(MAC, "Scheduled Msg2 reception in Frame %d, Slot %d: \n", *msg2_frame, *msg2_slot); -} - // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x // It fills the PRACH PDU per each FD occasion. // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. @@ -972,6 +962,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s config_index = rach_ConfigGeneric->prach_ConfigurationIndex; mac->RA_offset = 2; // to compensate the rx frame offset at the gNB + mac->generate_nr_prach = 0; // Reset flag for PRACH generation if (is_nr_UL_slot(scc, slotP)) { @@ -1090,8 +1081,8 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s } } } - } else { - mac->generate_nr_prach = 0; + } else if (mac->ra_state == RA_SUCCEEDED){ + mac->generate_nr_prach = 2; } mac->scheduled_response.ul_config = ul_config; } @@ -2320,7 +2311,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc AssertFatal(mac->DLbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); AssertFatal(mac->ULbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); - const uint16_t n_RB_DLBWP = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); + const uint16_t n_RB_DLBWP = (mac->ra_state == WAIT_RAR) ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275) : NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); const uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); LOG_D(MAC,"nr_ue_process_dci at MAC layer with dci_format=%d (DL BWP %d, UL BWP %d)\n",dci_format,n_RB_DLBWP,n_RB_ULBWP); @@ -2351,7 +2342,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_domain_assignment.val) < 0) - break; + return -1; /* FREQ_HOPPING_FLAG */ if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) @@ -2425,7 +2416,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_domain_assignment.val) < 0) - break; + return -1; /* FREQ_HOPPING_FLAG */ if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) @@ -2756,12 +2747,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0) - break; + return -1; /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->scc->dmrs_TypeA_Position, dlsch_config_pdu_1_0->number_symbols); - dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 1 : 2; + dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + /* number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214 version 15.9.0 Release 15 */ + if (dlsch_config_pdu_1_0->number_symbols == 2) + dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 1; + else + dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 2; /* VRB_TO_PRB_MAPPING */ dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; /* MCS */ @@ -2822,10 +2818,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_0->pucch_resource_id, dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind); - if (mac->ra_rnti == rnti) + if (mac->RA_window_cnt >= 0 && rnti == mac->ra_rnti){ dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; - else + } else { dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; + } // dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = n_RB_DLBWP; @@ -2875,12 +2872,15 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0) - break; + return -1; /* dmrs symbol positions*/ dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->scc->dmrs_TypeA_Position, dlsch_config_pdu_1_1->number_symbols); - dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 1 : 2; + dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + /* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214, + using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */ + dlsch_config_pdu_1_1->n_dmrs_cdm_groups = 1; /* VRB_TO_PRB_MAPPING */ if (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.resource_allocation != 0) dlsch_config_pdu_1_1->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; @@ -3133,6 +3133,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, case NR_DL_DCI_FORMAT_1_0: switch(rnti_type) { case NR_RNTI_RA: + N_RB = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); // TBR hotfix // Freq domain assignment fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos=fsize; @@ -3167,8 +3168,6 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, #endif break; - mac->rnti_type = rnti_type; - case NR_RNTI_C: // indicating a DL DCI format 1bit @@ -3583,19 +3582,18 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, // L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; // F: lenght of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. - while (!done && pdu_len > 0){ mac_ce_len = 0x0000; mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct mac_sdu_len = 0x0000; rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID; + //#ifdef DEBUG_HEADER_PARSING + LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID, pdu_len); + //#endif switch(rx_lcid){ // MAC CE - /*#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID, pdu_len); - #endif*/ case DL_SCH_LCID_CCCH: // MSG4 RRC Connection Setup 38.331 // varialbe length @@ -3803,7 +3801,8 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, } pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); - AssertFatal(pdu_len >= 0, "[MAC] nr_ue_process_mac_pdu, residual mac pdu length < 0!\n"); + if (pdu_len < 0) + LOG_E(MAC, "[MAC] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", pdu_len); } } diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c index 31a865f317..8d52db6747 100644 --- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c +++ b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c @@ -107,9 +107,10 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, uint8_t n_subPDUs = 0; // number of RAR payloads uint8_t n_subheaders = 0; // number of MAC RAR subheaders //uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs - unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req; - uint16_t ta_command = 0, msg3_f_alloc, bwp_size; - int f_alloc, mask; + //unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req; // WIP + //uint16_t ta_command = 0, msg3_f_alloc, bwp_size; // WIP + uint16_t ta_command = 0; + //int f_alloc, mask; // WIP AssertFatal(CC_id == 0, "RAR reception on secondary CCs is not supported yet\n"); @@ -143,6 +144,7 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, // LOG_I(MAC, "[UE %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", // mod_id, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index); + #if 0 // TbD WIP Msg3 development ongoing if (ue_mac->RA_RAPID_found) { // TC-RNTI *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); @@ -200,6 +202,7 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, ue_mac->t_crnti = 0; ta_command = (0xffff); } + #endif // move the selected RAR to the front of the RA_PDSCH buffer memcpy((void *) (selected_rar_buffer + 0), (void *) rarh, 1); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index d0c9f6a3eb..a1fbf2d6f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -309,41 +309,18 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm else LOG_I(PHY,"TDD has been properly configurated\n"); } -/* - // PDCCH-ConfigCommon - cfg->pdcch_config.controlResourceSetZero.value = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero; - cfg->pdcch_config.searchSpaceZero.value = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero; - - // PDSCH-ConfigCommon - cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; - cfg->pdsch_config.dmrs_TypeA_Position.value = scc->dmrs_TypeA_Position; - AssertFatal(cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value<=NFAPI_NR_PDSCH_CONFIG_MAXALLOCATIONS,"illegal TimeDomainAllocation count %d\n",cfg->pdsch_config.num_PDSCHTimeDomainResourceAllocations.value); - for (int i=0;ipdsch_config.num_PDSCHTimeDomainResourceAllocations.value;i++) { - cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_k0[i].value=*scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0; - cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_mappingType[i].value=scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType; - cfg->pdsch_config.PDSCHTimeDomainResourceAllocation_startSymbolAndLength[i].value=scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; - } - - // PUSCH-ConfigCommon - cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; - cfg->pusch_config.dmrs_TypeA_Position.value = scc->dmrs_TypeA_Position+2; - AssertFatal(cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value<=NFAPI_NR_PUSCH_CONFIG_MAXALLOCATIONS,"illegal TimeDomainAllocation count %d\n",cfg->pusch_config.num_PUSCHTimeDomainResourceAllocations.value); - for (int i=0;ipusch_config.num_PUSCHTimeDomainResourceAllocations.value;i++) { - cfg->pusch_config.PUSCHTimeDomainResourceAllocation_k2[i].value=*scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[0]->k2; - }*/ - - } int rrc_mac_config_req_gNB(module_id_t Mod_idP, int ssb_SubcarrierOffset, int pdsch_AntennaPorts, + int pusch_tgt_snrx10, + int pucch_tgt_snrx10, NR_ServingCellConfigCommon_t *scc, int add_ue, uint32_t rnti, - NR_CellGroupConfig_t *secondaryCellGroup - ){ + NR_CellGroupConfig_t *secondaryCellGroup){ if (scc != NULL ) { AssertFatal((scc->ssb_PositionsInBurst->present > 0) && (scc->ssb_PositionsInBurst->present < 4), "SSB Bitmap type %d is not valid\n",scc->ssb_PositionsInBurst->present); @@ -364,7 +341,8 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, } } - + RC.nrmac[Mod_idP]->pusch_target_snrx10 = pusch_tgt_snrx10; + RC.nrmac[Mod_idP]->pucch_target_snrx10 = pucch_tgt_snrx10; NR_PHY_Config_t phycfg; phycfg.Mod_id = Mod_idP; phycfg.CC_id = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 2960c36a04..1c36c474d8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -62,6 +62,32 @@ const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; +void clear_mac_stats(gNB_MAC_INST *gNB) { + memset((void*)gNB->UE_list.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t)); +} + +void dump_mac_stats(gNB_MAC_INST *gNB) { + + NR_UE_list_t *UE_list = &gNB->UE_list; + NR_mac_stats_t *stats; + int lc_id; + + for (int UE_id=0;UE_idactive[UE_id] == TRUE) { + LOG_I(MAC,"UE %x\n",UE_list->rnti[UE_id]); + stats = &UE_list->mac_stats[UE_id]; + LOG_I(MAC,"dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",stats->dlsch_rounds[0],stats->dlsch_rounds[1],stats->dlsch_rounds[2],stats->dlsch_rounds[3],stats->dlsch_errors); + LOG_I(MAC,"dlsch_total_bytes %d\n",stats->dlsch_total_bytes); + LOG_I(MAC,"ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",stats->ulsch_rounds[0],stats->ulsch_rounds[1],stats->ulsch_rounds[2],stats->ulsch_rounds[3],stats->ulsch_errors); + LOG_I(MAC,"ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",stats->ulsch_total_bytes_scheduled,stats->ulsch_total_bytes_rx); + for (lc_id=0;lc_id<63;lc_id++) { + if (stats->lc_bytes_tx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes TX\n",lc_id,stats->lc_bytes_tx[lc_id]); + if (stats->lc_bytes_rx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes RX\n",lc_id,stats->lc_bytes_rx[lc_id]); + } + } + } +} + void clear_nr_nfapi_information(gNB_MAC_INST * gNB, int CC_idP, frame_t frameP, @@ -288,8 +314,33 @@ void copy_nr_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) } */ +void nr_schedule_pusch(int Mod_idP, + int UE_id, + int num_slots_per_tdd, + int ul_slots, + frame_t frameP, + sub_frame_t slotP) { + + nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; + NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; + int k = slotP + ul_slots - num_slots_per_tdd; + NR_sched_pusch *pusch = &UE_list->UE_sched_ctrl[UE_id].sched_pusch[k]; + if ((pusch->active == true) && (frameP == pusch->frame) && (slotP == pusch->slot)) { + UL_tti_req->SFN = pusch->frame; + UL_tti_req->Slot = pusch->slot; + UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + UL_tti_req->pdus_list[UL_tti_req->n_pdus].pusch_pdu = pusch->pusch_pdu; + UL_tti_req->n_pdus+=1; + memset((void *) &UE_list->UE_sched_ctrl[UE_id].sched_pusch[k], + 0, sizeof(NR_sched_pusch)); + } +} + + void nr_schedule_pucch(int Mod_idP, int UE_id, + int nr_ulmix_slots, frame_t frameP, sub_frame_t slotP) { @@ -306,15 +357,12 @@ void nr_schedule_pucch(int Mod_idP, nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; NR_sched_pucch *curr_pucch; - int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) - nr_ulmix_slots++; for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k]; if ((curr_pucch->dai_c > 0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) { - UL_tti_req->SFN = frameP; - UL_tti_req->Slot = slotP; + UL_tti_req->SFN = curr_pucch->frame; + UL_tti_req->Slot = curr_pucch->ul_slot; UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t); nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu; @@ -323,7 +371,7 @@ void nr_schedule_pucch(int Mod_idP, O_ack = curr_pucch->dai_c; O_uci = O_ack; // for now we are just sending acknacks in pucch - LOG_I(MAC, "Scheduling pucch reception for frame %d slot %d\n", frameP, slotP); + LOG_D(MAC, "Scheduling pucch reception for frame %d slot %d\n", frameP, slotP); nr_configure_pucch(pucch_pdu, scc, @@ -333,11 +381,15 @@ void nr_schedule_pucch(int Mod_idP, O_ack, SR_flag); - curr_pucch->dai_c = 0; + memset((void *) &UE_list->UE_sched_ctrl[UE_id].sched_pucch[k], + 0, + sizeof(NR_sched_pucch)); } } } + + bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot){ if((bitmap>>slot)&0x01) @@ -347,15 +399,12 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot){ } void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame_rxP, - sub_frame_t slot_rxP, - frame_t frame_txP, - sub_frame_t slot_txP){ + frame_t frame, + sub_frame_t slot){ - //printf("gNB_dlsch_ulsch_scheduler frameRX %d slotRX %d frameTX %d slotTX %d\n",frame_rxP,slot_rxP,frame_txP,slot_txP); protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame_txP, slot_txP,module_idP); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); int CC_id; int UE_id; @@ -377,11 +426,14 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) nr_ulmix_slots++; - if (slot_txP== 0 && (UE_list->fiveG_connected[UE_id] || get_softmodem_params()->phy_test)) { + if (slot== 0 && (UE_list->fiveG_connected[UE_id] || get_softmodem_params()->phy_test)) { for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k], 0, sizeof(NR_sched_pucch)); + memset((void *) &UE_list->UE_sched_ctrl[UE_id].sched_pusch[k], + 0, + sizeof(NR_sched_pusch)); } } @@ -390,93 +442,112 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, pdcp_run(&ctxt); //rrc_rx_tx(&ctxt, CC_id); - - RC.nrmac[module_idP]->frame = frame_rxP; - RC.nrmac[module_idP]->slot = slot_rxP; + /* send tick to RLC every ms */ + if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) { + void nr_rlc_tick(int frame, int subframe); + nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing); + } dlsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch ulsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch // hardcoding dlsch to be in slot 1 - if (!(slot_txP%num_slots_per_tdd)) { - if(slot_txP==0) + if (!(slot%num_slots_per_tdd)) { + if(slot==0) { *dlsch_in_slot_bitmap = 0x02; - else - *dlsch_in_slot_bitmap = 0x00; - } - - // hardcoding ulsch to be in slot 8 - if (!(slot_rxP%num_slots_per_tdd)) { - if(slot_rxP==0) *ulsch_in_slot_bitmap = 0x100; - else + } + else { + *dlsch_in_slot_bitmap = 0x00; *ulsch_in_slot_bitmap = 0x00; + } } - // Check if there are downlink symbols in the slot, - if (is_nr_DL_slot(cc->ServingCellConfigCommon,slot_txP)) { - memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0 - memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1 - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - //mbsfn_status[CC_id] = 0; + memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0 + memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1 + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + //mbsfn_status[CC_id] = 0; - // clear vrb_maps - memset(cc[CC_id].vrb_map, 0, 100); - memset(cc[CC_id].vrb_map_UL, 0, 100); + // clear vrb_maps + memset(cc[CC_id].vrb_map, 0, 100); + memset(cc[CC_id].vrb_map_UL, 0, 100); - clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame_txP, slot_txP); - } + clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); + } - // refresh UE list based on UEs dropped by PHY in previous subframe - /* - for (i = 0; i < MAX_MOBILES_PER_GNB; i++) { - if (UE_list->active[i]) { + // refresh UE list based on UEs dropped by PHY in previous subframe + /* + for (i = 0; i < MAX_MOBILES_PER_GNB; i++) { + if (UE_list->active[i]) { - nfapi_nr_config_request_t *cfg = &RC.nrmac[module_idP]->config[CC_id]; + nfapi_nr_config_request_t *cfg = &RC.nrmac[module_idP]->config[CC_id]; - rnti = 0;//UE_RNTI(module_idP, i); - CC_id = 0;//UE_PCCID(module_idP, i); + rnti = 0;//UE_RNTI(module_idP, i); + CC_id = 0;//UE_PCCID(module_idP, i); - } //END if (UE_list->active[i]) - } //END for (i = 0; i < MAX_MOBILES_PER_GNB; i++) - */ + } //END if (UE_list->active[i]) + } //END for (i = 0; i < MAX_MOBILES_PER_GNB; i++) + */ - // This schedules MIB - if((slot_txP == 0) && (frame_txP & 7) == 0) - schedule_nr_mib(module_idP, frame_txP, slot_txP); + if ((slot == 0) && (frame & 127) == 0) dump_mac_stats(RC.nrmac[module_idP]); - if (get_softmodem_params()->phy_test == 0) - nr_schedule_RA(module_idP, frame_txP, slot_txP); - else - UE_list->fiveG_connected[UE_id] = true; + // This schedules MIB + if((slot == 0) && (frame & 7) == 0){ + schedule_nr_mib(module_idP, frame, slot); + } - // Phytest scheduling + // This schedule PRACH if we are not in phy_test mode + if (get_softmodem_params()->phy_test == 0) + schedule_nr_prach(module_idP, frame, slot); - if (get_softmodem_params()->phy_test) { + // This schedule SR + // TODO - // TbD once RACH is available, start ta_timer when UE is connected - if (ue_sched_ctl->ta_timer) - ue_sched_ctl->ta_timer--; + // This schedule CSI + // TODO - if (ue_sched_ctl->ta_timer == 0) { - gNB->ta_command = ue_sched_ctl->ta_update; - /* if time is up, then set the timer to not send it for 5 frames - // regardless of the TA value */ - ue_sched_ctl->ta_timer = 100; - /* reset ta_update */ - ue_sched_ctl->ta_update = 31; - /* MAC CE flag indicating TA length */ - gNB->ta_len = 2; - } + // This schedule RA procedure if not in phy_test mode + // Otherwise already consider 5G already connected + if (get_softmodem_params()->phy_test == 0) { + nr_schedule_RA(module_idP, frame, slot); + nr_schedule_reception_msg3(module_idP, 0, frame, slot); + } else + UE_list->fiveG_connected[UE_id] = true; + + if (get_softmodem_params()->phy_test) { + + // TbD once RACH is available, start ta_timer when UE is connected + if (ue_sched_ctl->ta_timer) + ue_sched_ctl->ta_timer--; + if (ue_sched_ctl->ta_timer == 0) { + gNB->ta_command = ue_sched_ctl->ta_update; + /* if time is up, then set the timer to not send it for 5 frames + // regardless of the TA value */ + ue_sched_ctl->ta_timer = 100; + /* reset ta_update */ + ue_sched_ctl->ta_update = 31; + /* MAC CE flag indicating TA length */ + gNB->ta_len = 2; } + } - if (UE_list->fiveG_connected[UE_id] && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot_txP%num_slots_per_tdd))) { - ue_sched_ctl->current_harq_pid = slot_txP % num_slots_per_tdd; - nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,&pucch_sched); - nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); - // resetting ta flag - gNB->ta_len = 0; - } + // This schedules the DCI for Uplink and subsequently PUSCH + if (UE_list->fiveG_connected[UE_id]) { + int tda = 1; // time domain assignment hardcoded for now + schedule_fapi_ul_pdu(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, tda); + nr_schedule_pusch(module_idP, UE_id, num_slots_per_tdd, nr_ulmix_slots, frame, slot); + } + + if (UE_list->fiveG_connected[UE_id] && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot%num_slots_per_tdd))) { + ue_sched_ctl->current_harq_pid = slot % num_slots_per_tdd; + nr_update_pucch_scheduling(module_idP, UE_id, frame, slot, num_slots_per_tdd,&pucch_sched); + nr_schedule_uss_dlsch_phytest(module_idP, frame, slot, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); + // resetting ta flag + gNB->ta_len = 0; + } + + if (UE_list->fiveG_connected[UE_id]) + nr_schedule_pucch(module_idP, UE_id, nr_ulmix_slots, frame, slot); /* // Allocate CCEs for good after scheduling is done @@ -484,24 +555,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, allocate_CCEs(module_idP, CC_id, subframeP, 0); */ - } //is_nr_DL_slot - - if (is_nr_UL_slot(cc->ServingCellConfigCommon,slot_rxP)) { - - if (get_softmodem_params()->phy_test == 0) { - if (UE_list->fiveG_connected[UE_id]) - nr_schedule_pucch(module_idP, UE_id, frame_rxP, slot_rxP); - schedule_nr_prach(module_idP, (frame_rxP+1)&1023, slot_rxP); - nr_schedule_reception_msg3(module_idP, 0, frame_rxP, slot_rxP); - } - if (get_softmodem_params()->phy_test){ - nr_schedule_pucch(module_idP, UE_id, frame_rxP, slot_rxP); - if (is_xlsch_in_slot(*ulsch_in_slot_bitmap,slot_rxP%num_slots_per_tdd)){ - nr_schedule_uss_ulsch_phytest(module_idP, frame_rxP, slot_rxP); - } - } - } - stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index bc57416875..85692da2e5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -42,8 +42,7 @@ #include "SIMULATION/TOOLS/sim.h" // for taus extern RAN_CONTEXT_t RC; - -const uint8_t nr_slots_per_frame_mac[5] = {10, 20, 40, 80, 160}; +extern const uint8_t nr_slots_per_frame[5]; uint8_t DELTA[4]= {2,3,4,6}; @@ -204,6 +203,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req[0]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; + if (is_nr_UL_slot(scc,slotP)) { uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot; uint16_t RA_sfn_index = -1; @@ -335,9 +335,9 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP } } } + } } - void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, uint16_t *msg2_frame, uint16_t *msg2_slot, NR_ServingCellConfigCommon_t *scc, @@ -360,8 +360,7 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, tdd_period_slot++; // computing start of next period - uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame_mac[mu]; - + uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu]; *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot *msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1); @@ -393,16 +392,16 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, default: AssertFatal(1==0,"Invalid response window value %d\n",response_window); } - AssertFatal(slot_window<=nr_slots_per_frame_mac[mu],"Msg2 response window needs to be lower or equal to 10ms"); + AssertFatal(slot_window<=nr_slots_per_frame[mu],"Msg2 response window needs to be lower or equal to 10ms"); // slot and frame limit to transmit msg2 according to response window - uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame_mac[mu]; + uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu]; //uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); // go to previous slot if the current scheduled slot is beyond the response window // and if the slot is not among the PDCCH monitored ones (38.213 10.1) - while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame_mac[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { + while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { if((*msg2_slot%tdd_period_slot) > 0) (*msg2_slot)--; else @@ -594,11 +593,11 @@ void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc, uint8_t k2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2; temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213 - ra->Msg3_slot = temp_slot%nr_slots_per_frame_mac[mu]; - if (nr_slots_per_frame_mac[mu]>temp_slot) + ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu]; + if (nr_slots_per_frame[mu]>temp_slot) ra->Msg3_frame = current_frame; else - ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame_mac[mu]); + ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]); LOG_I(MAC, "[RAPROC] Msg3 slot %d: current slot %u Msg3 frame %u k2 %u Msg3_tda_id %u start symbol index %u\n", ra->Msg3_slot, current_slot, ra->Msg3_frame, k2,ra->Msg3_tda_id, StartSymbolIndex); ra->msg3_nb_rb = 18; @@ -634,7 +633,10 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t NR_UE_list_t *UE_list = &mac->UE_list; int UE_id = 0; - AssertFatal(ra->state != RA_IDLE, "RA is not active for RA %X\n", ra->rnti); + if (ra->state == RA_IDLE) { + LOG_W(MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti); + return; + } LOG_I(MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot); @@ -738,7 +740,7 @@ void nr_generate_Msg2(module_id_t module_idP, NR_RA_t *ra){ int UE_id = 0, dci_formats[2], rnti_types[2], mcsIndex; - int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment; + int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0; gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; // NR_RA_t *ra = &cc->ra[0]; @@ -800,7 +802,11 @@ void nr_generate_Msg2(module_id_t module_idP, LOG_I(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw); - mcsIndex = 0; // Qm>2 not allowed for RAR + // Qm>2 not allowed for RAR + if (get_softmodem_params()->do_ra) + mcsIndex = 9; + else + mcsIndex = 0; pdsch_pdu_rel15->pduBitmap = 0; pdsch_pdu_rel15->rnti = RA_rnti; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index cf2323f571..495095ce9e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -38,6 +38,7 @@ #include "NR_MAC_gNB/nr_mac_gNB.h" #include "NR_MAC_COMMON/nr_mac_extern.h" #include "LAYER2/MAC/mac.h" +#include "LAYER2/NR_MAC_gNB/mac_proto.h" /*NFAPI*/ #include "nfapi_nr_interface.h" @@ -76,6 +77,8 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, //NR_CellGroupConfig_t *config = UE_list->secondaryCellGroup[UE_id]; ue_sched_ctl = &(UE_list->UE_sched_ctrl[UE_id]); + NR_mac_stats_t *mac_stats = &(UE_list->mac_stats[UE_id]); + // 1) Compute MAC CE and related subheaders // DRX command subheader (MAC CE size 0) @@ -112,6 +115,8 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, memcpy((void *) mac_pdu_ptr, (void *) ce_ptr, mac_ce_size); ce_ptr += mac_ce_size; mac_pdu_ptr += (unsigned char) mac_ce_size; + + } // Contention resolution fixed subheader and MAC CE @@ -324,6 +329,8 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, memcpy((void *) mac_pdu_ptr, (void *) dlsch_buffer_ptr, sdu_lengths[i]); dlsch_buffer_ptr += sdu_lengths[i]; mac_pdu_ptr += sdu_lengths[i]; + + mac_stats->lc_bytes_tx[sdu_lcids[i]] += sdu_lengths[i]; } // 4) Compute final offset for padding @@ -341,6 +348,70 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, return offset; } +void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10) { + // TODO + int max_harq_rounds = 4; // TODO define macro + int num_ucis = UL_info->uci_ind.num_ucis; + nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; + + for (int i = 0; i < num_ucis; i++) { + switch (uci_list[i].pdu_type) { + case NFAPI_NR_UCI_PDCCH_PDU_TYPE: break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + //if (get_softmodem_params()->phy_test == 0) { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; + // handle harq + int harq_idx_s = 0; + // tpc (power control) + sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30); + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_pdu->harq->num_harq; harq_bit++) { + // search for the right harq process + for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) { + // if the gNB received ack with a good confidence + if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { + if ((uci_pdu->harq->harq_list[harq_bit].harq_value == 1) && + (uci_pdu->harq->harq_confidence_level == 0)) { + // toggle NDI and reset round + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + else + sched_ctrl->harq_processes[harq_idx].round++; + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; + harq_idx_s = harq_idx + 1; + // if the max harq rounds was reached + if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + stats->dlsch_errors++; + } + break; + } + // if feedback slot processing is aborted + else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) && + (sched_ctrl->harq_processes[harq_idx].is_waiting)) { + sched_ctrl->harq_processes[harq_idx].round++; + if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; + } + } + } + //} + break; + } + + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: break; + } + } + + UL_info->uci_ind.num_ucis = 0; +} + /* functionalities of this function have been moved to nr_schedule_uss_dlsch_phytest */ void nr_schedule_ue_spec(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 8841083796..f786db8ba9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -53,7 +53,10 @@ #include "NR_SearchSpace.h" #include "NR_ControlResourceSet.h" +//#define UL_HARQ_PRINT extern RAN_CONTEXT_t RC; + +const uint8_t nr_rv_round_map[4] = {0, 2, 1, 3}; //#define ENABLE_MAC_PAYLOAD_DEBUG 1 //uint8_t mac_pdu[MAX_NR_DLSCH_PAYLOAD_BYTES]; @@ -257,8 +260,6 @@ int configure_fapi_dl_pdu(int Mod_idP, uint16_t *rbSize, uint16_t *rbStart) { - - gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; NR_COMMON_channels_t *cc = nr_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -314,12 +315,12 @@ int configure_fapi_dl_pdu(int Mod_idP, pdsch_pdu_rel15->qamModOrder[0] = 2; pdsch_pdu_rel15->mcsIndex[0] = mcs; pdsch_pdu_rel15->mcsTable[0] = 0; - pdsch_pdu_rel15->rvIndex[0] = (get_softmodem_params()->phy_test==1) ? 0 : UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round; + pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round]; pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = 1; pdsch_pdu_rel15->transmissionScheme = 0; pdsch_pdu_rel15->refPoint = 0; // Point A - + UE_list->mac_stats[UE_id].dlsch_rounds[UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round]++; pdsch_pdu_rel15->dmrsConfigType = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; pdsch_pdu_rel15->SCID = 0; @@ -372,7 +373,7 @@ int configure_fapi_dl_pdu(int Mod_idP, dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3; // TPC for PUCCH - dci_pdu_rel15[0].tpc = 1; // table 7.2.1-1 in 38.213 + dci_pdu_rel15[0].tpc = UE_list->UE_sched_ctrl[UE_id].tpc1; // table 7.2.1-1 in 38.213 // PUCCH resource indicator dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator; // PDSCH to HARQ TI @@ -454,6 +455,9 @@ int configure_fapi_dl_pdu(int Mod_idP, // Hardcode it for now TBS = dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]; + if (UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round==0) + UE_list->mac_stats[UE_id].dlsch_total_bytes += TBS; + LOG_D(MAC, "DLSCH PDU: start PRB %d n_PRB %d startSymbolAndLength %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d TBS: %d\n", pdsch_pdu_rel15->rbStart, pdsch_pdu_rel15->rbSize, @@ -474,7 +478,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types, - int time_domain_assignment, + int time_domain_assignment, uint8_t tpc, int n_ubwp, int bwp_id) { switch(dci_formats[(pdcch_pdu_rel15->numDlDci)-1]) { @@ -491,7 +495,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, dci_pdu_rel15->ndi = 1; dci_pdu_rel15->rv = 0; dci_pdu_rel15->harq_pid = 0; - dci_pdu_rel15->tpc = 2; + dci_pdu_rel15->tpc = 1; break; case NR_UL_DCI_FORMAT_0_1: dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; @@ -516,7 +520,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, // mcs dci_pdu_rel15->mcs = pusch_pdu->mcs_index; // tpc command for pusch - dci_pdu_rel15->tpc = 2; //TODO + dci_pdu_rel15->tpc = tpc; // SRS resource indicator if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) { if (*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook) @@ -593,7 +597,7 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, LOG_D(MAC, "In nr_schedule_uss_dlsch_phytest frame %d slot %d\n",frameP,slotP); int post_padding = 0, ta_len = 0, header_length_total = 0, sdu_length_total = 0, num_sdus = 0; - int lcid, offset, i, header_length_last, TBS_bytes; + int lcid, offset, i, header_length_last, TBS_bytes = 0; int UE_id = 0, CC_id = 0; gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; @@ -627,70 +631,62 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, if (TBS_bytes == 0) return; - - //The --NOS1 use case currently schedules DLSCH transmissions only when there is IP traffic arriving - //through the LTE stack - if (IS_SOFTMODEM_NOS1){ - for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { + lcid = DL_SCH_LCID_DTCH; - // TODO: check if the lcid is active + //for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { - LOG_D(MAC, "[gNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (TBS %d bytes, len %d)\n", - module_idP, frameP, lcid, TBS_bytes, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3); + // TODO: check if the lcid is active - if (TBS_bytes - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - slotP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - 0, - 0); + LOG_D(MAC, "[gNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (TBS %d bytes, len %d)\n", + module_idP, frameP, lcid, TBS_bytes, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3); - if (rlc_status.bytes_in_buffer > 0) { + //if (TBS_bytes - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + slotP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + 0, + 0); - LOG_D(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d), TBS_bytes: %d \n \n", - module_idP, frameP, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, - lcid, header_length_total, TBS_bytes); + if (rlc_status.bytes_in_buffer > 0) { - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, - (char *)&mac_sdus[sdu_length_total], - 0, - 0); + LOG_I(MAC, "configure fapi due to data availability \n"); - LOG_D(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", module_idP, sdu_lengths[num_sdus], lcid); + LOG_I(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d), TBS_bytes: %d \n \n", + module_idP, frameP, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, + lcid, header_length_total, TBS_bytes); - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, + (char *)&mac_sdus[sdu_length_total], + 0, + 0); - num_sdus++; + LOG_W(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", module_idP, sdu_lengths[num_sdus], lcid); - //ue_sched_ctl->uplane_inactivity_timer = 0; - } - } else { // no TBS_bytes left - break; - } - } + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + + num_sdus++; + + //ue_sched_ctl->uplane_inactivity_timer = 0; + } - } //if (IS_SOFTMODEM_NOS1) else { - //When the --NOS1 option is not enabled, DLSCH transmissions with random data - //occur every time that the current function is called (dlsch phytest mode) - LOG_D(MAC,"Configuring DL_TX in %d.%d\n", frameP, slotP); // fill dlsch_buffer with random data @@ -715,7 +711,7 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, } #endif - } // else IS_SOFTMODEM_NOS1 + } // there is at least one SDU or TA command // if (num_sdus > 0 ){ @@ -758,14 +754,14 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, } #endif } else { - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) +#if defined(ENABLE_MAC_PAYLOAD_DEBUG) if (frameP%100 == 0){ LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n", frameP, slotP, TBS_bytes); for(int i = 0; i < 10; i++) { - LOG_I(MAC, "%x. ", ((uint8_t *)gNB_mac->UE_list.DLSCH_pdu[CC_id][0][0].payload[0])[i]); //LOG_I(MAC, "%x. ", mac_payload[i]); + LOG_I(MAC, "byte %d : %x\n", i,((uint8_t *)gNB_mac->UE_list.DLSCH_pdu[0][0].payload[0])[i]); //LOG_I(MAC, "%x. ", mac_payload[i]); } } - #endif +#endif } } else { // There is no data from RLC or MAC header, so don't schedule @@ -773,10 +769,42 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, } +int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) { -void nr_schedule_uss_ulsch_phytest(int Mod_idP, - frame_t frameP, - sub_frame_t slotP) { + uint8_t hrq_id; + uint8_t max_ul_harq_pids = 3; // temp: for testing + // schedule active harq processes + NR_UE_ul_harq_t cur_harq; + for (hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) { + cur_harq = sched_ctrl->ul_harq_processes[hrq_id]; + if (cur_harq.state==ACTIVE_NOT_SCHED) { +#ifdef UL_HARQ_PRINT + printf("[SCHED] Found ulharq id %d, scheduling it for retransmission\n",hrq_id); +#endif + return hrq_id; + } + } + + // schedule new harq processes + for (hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) { + cur_harq = sched_ctrl->ul_harq_processes[hrq_id]; + if (cur_harq.state==INACTIVE) { +#ifdef UL_HARQ_PRINT + printf("[SCHED] Found new ulharq id %d, scheduling it\n",hrq_id); +#endif + return hrq_id; + } + } + LOG_E(MAC,"All UL HARQ processes are busy. Cannot schedule ULSCH\n"); + return -1; +} + +void schedule_fapi_ul_pdu(int Mod_idP, + frame_t frameP, + sub_frame_t slotP, + int num_slots_per_tdd, + int ul_slots, + int time_domain_assignment) { gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; NR_COMMON_channels_t *cc = nr_mac->common_channels; @@ -796,40 +824,11 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; - nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0]; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - uint16_t rnti = UE_list->rnti[UE_id]; - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu; - - UL_tti_req->SFN = frameP; - UL_tti_req->Slot = slotP; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - nfapi_nr_pusch_pdu_t *pusch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pusch_pdu; - memset(pusch_pdu,0,sizeof(nfapi_nr_pusch_pdu_t)); - UL_tti_req->n_pdus+=1; - - LOG_D(MAC, "Scheduling UE specific PUSCH\n"); - //UL_tti_req = &nr_mac->UL_tti_req[CC_id]; - - //Resource Allocation in time domain - int startSymbolAndLength=0; - int time_domain_assignment=1; - int StartSymbolIndex,NrOfSymbols,K2,mapping_type; AssertFatal(time_domain_assignmentbwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count, "time_domain_assignment %d>=%d\n",time_domain_assignment,ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count); - startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); - pusch_pdu->start_symbol_index = StartSymbolIndex; - pusch_pdu->nr_of_symbols = NrOfSymbols; - mapping_type = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; + int K2; if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2 != NULL) K2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2; else { @@ -838,225 +837,272 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, else K2=3; } - pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = rnti; - pusch_pdu->handle = 0; //not yet used + if (is_xlsch_in_slot(UE_list->UE_sched_ctrl[UE_id].ulsch_in_slot_bitmap,(slotP+K2)%num_slots_per_tdd)) { + + //nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; + nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0]; + UL_dci_req->SFN = frameP; + UL_dci_req->Slot = slotP; + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu; + + AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); + AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, + "searchPsacesToAddModList is empty\n"); + + uint16_t rnti = UE_list->rnti[UE_id]; + + int first_ul_slot = num_slots_per_tdd - ul_slots; + NR_sched_pusch *pusch_sched = &UE_list->UE_sched_ctrl[UE_id].sched_pusch[slotP+K2-first_ul_slot]; + pusch_sched->frame = frameP; + pusch_sched->slot = slotP + K2; + pusch_sched->active = true; + nfapi_nr_pusch_pdu_t *pusch_pdu = &pusch_sched->pusch_pdu; + memset(pusch_pdu,0,sizeof(nfapi_nr_pusch_pdu_t)); + + LOG_D(MAC, "Scheduling UE specific PUSCH\n"); + //UL_tti_req = &nr_mac->UL_tti_req[CC_id]; + + //Resource Allocation in time domain + int startSymbolAndLength=0; + int StartSymbolIndex,NrOfSymbols,mapping_type; + + startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); + pusch_pdu->start_symbol_index = StartSymbolIndex; + pusch_pdu->nr_of_symbols = NrOfSymbols; + + mapping_type = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; + + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_pdu->rnti = rnti; + pusch_pdu->handle = 0; //not yet used - pusch_pdu->bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pusch_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pusch_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing; - pusch_pdu->cyclic_prefix = 0; - //pusch information always include - //this informantion seems to be redundant. with hthe mcs_index and the modulation table, the mod_order and target_code_rate can be determined. - pusch_pdu->mcs_index = 9; - pusch_pdu->mcs_table = 0; //0: notqam256 [TS38.214, table 5.1.3.1-1] - corresponds to nr_target_code_rate_table1 in PHY - pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; - pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; - if (pusch_Config->transformPrecoder == NULL) { - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_pdu->transform_precoding = 1; - else - pusch_pdu->transform_precoding = 0; - } - else - pusch_pdu->transform_precoding = *pusch_Config->transformPrecoder; - if (pusch_Config->dataScramblingIdentityPUSCH != NULL) - pusch_pdu->data_scrambling_id = *pusch_Config->dataScramblingIdentityPUSCH; - else - pusch_pdu->data_scrambling_id = *scc->physCellId; - - pusch_pdu->nrOfLayers = 1; - - //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - if (pusch_Config->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { - pusch_pdu->resource_alloc = 1; //type 1 - pusch_pdu->rb_start = 0; - pusch_pdu->rb_size = 50; - } - else - AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - - pusch_pdu->vrb_to_prb_mapping = 0; - - if (pusch_Config->frequencyHopping==NULL) - pusch_pdu->frequency_hopping = 0; - else - pusch_pdu->frequency_hopping = 1; - - //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] - //pusch_pdu->uplink_frequency_shift_7p5khz = 0; - - - // -------------------- - // ------- DMRS ------- - // -------------------- - NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; - if (mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA) - NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; - else - NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - if (NR_DMRS_UplinkConfig->dmrs_Type == NULL) - pusch_pdu->dmrs_config_type = 0; - else - pusch_pdu->dmrs_config_type = 1; - pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - if (pusch_pdu->transform_precoding) { // transform precoding disabled - long *scramblingid; - if (pusch_pdu->scid == 0) - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; - else - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; - if (scramblingid == NULL) - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - else - pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; - } - else { - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - if (NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) - pusch_pdu->pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; - else - pusch_pdu->pusch_identity = *scc->physCellId; - } - pusch_dmrs_AdditionalPosition_t additional_pos; - if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL) - additional_pos = 2; - else { - if (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3) - additional_pos = 3; - else - additional_pos = *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition; - } - pusch_maxLength_t pusch_maxLength; - if (NR_DMRS_UplinkConfig->maxLength == NULL) - pusch_maxLength = 1; - else - pusch_maxLength = 2; - uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, mapping_type, additional_pos, pusch_maxLength); - pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; - - pusch_pdu->num_dmrs_cdm_grps_no_data = 1; - pusch_pdu->dmrs_ports = 1; - // -------------------------------------------------------------------------------------------------------------------------------------------- - - // -------------------- - // ------- PTRS ------- - // -------------------- - if (NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { - // TODO to be fixed from RRC config - uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig - pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); - pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); - pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - - pusch_pdu->pdu_bit_map &= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS - } - else{ -// if(1<pusch_ptrs.ptrs_time_density >= pusch_pdu->nr_of_symbols) - pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - } - - // -------------------------------------------------------------------------------------------------------------------------------------------- - - //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - //Optional Data only included if indicated in pduBitmap - // TODO from harq function as in pdsch - pusch_pdu->pusch_data.rv_index = 0; - pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 1; - - uint8_t num_dmrs_symb = 0; - - for(int dmrs_counter = pusch_pdu->start_symbol_index; dmrs_counter < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; dmrs_counter++) - num_dmrs_symb += ((pusch_pdu->ul_dmrs_symb_pos >> dmrs_counter) & 1); - - uint8_t N_PRB_DMRS; - if (pusch_pdu->dmrs_config_type == 0) { - N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*6; - } - else { - N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*4; - } - - pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, - pusch_pdu->target_code_rate, - pusch_pdu->rb_size, - pusch_pdu->nr_of_symbols, - N_PRB_DMRS * num_dmrs_symb, - 0, //nb_rb_oh - 0, - pusch_pdu->nrOfLayers)>>3; - - - pusch_pdu->pusch_data.num_cb = 0; //CBG not supported - //pusch_pdu->pusch_data.cb_present_and_position; - //pusch_pdu->pusch_uci; - //pusch_pdu->pusch_ptrs; - //pusch_pdu->dfts_ofdm; - //beamforming - //pusch_pdu->beamforming; //not used for now - - - ul_dci_request_pdu = &UL_dci_req->ul_dci_pdu_list[UL_dci_req->numPdus]; - memset((void*)ul_dci_request_pdu,0,sizeof(nfapi_nr_ul_dci_request_pdus_t)); - ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; - - int dci_formats[2]; - int rnti_types[2]; - - NR_SearchSpace_t *ss; - int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - int found=0; - - for (int i=0;ibwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) { - ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; - AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n"); - AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n"); - if (ss->searchSpaceType->present == target_ss) { - found=1; - break; + pusch_pdu->bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pusch_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pusch_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + pusch_pdu->cyclic_prefix = 0; + //pusch information always include + //this informantion seems to be redundant. with hthe mcs_index and the modulation table, the mod_order and target_code_rate can be determined. + pusch_pdu->mcs_index = 9; + pusch_pdu->mcs_table = 0; //0: notqam256 [TS38.214, table 5.1.3.1-1] - corresponds to nr_target_code_rate_table1 in PHY + pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; + pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; + if (pusch_Config->transformPrecoder == NULL) { + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) + pusch_pdu->transform_precoding = 1; + else + pusch_pdu->transform_precoding = 0; } - } - AssertFatal(found==1,"Couldn't find an adequate searchspace\n"); + else + pusch_pdu->transform_precoding = *pusch_Config->transformPrecoder; + if (pusch_Config->dataScramblingIdentityPUSCH != NULL) + pusch_pdu->data_scrambling_id = *pusch_Config->dataScramblingIdentityPUSCH; + else + pusch_pdu->data_scrambling_id = *scc->physCellId; - if (ss->searchSpaceType->choice.ue_Specific->dci_Formats) - dci_formats[0] = NR_UL_DCI_FORMAT_0_1; - else - dci_formats[0] = NR_UL_DCI_FORMAT_0_0; + pusch_pdu->nrOfLayers = 1; - rnti_types[0] = NR_RNTI_C; - LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frameP,slotP); + //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] + if (pusch_Config->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { + pusch_pdu->resource_alloc = 1; //type 1 + pusch_pdu->rb_start = 0; + if (get_softmodem_params()->phy_test==1) + pusch_pdu->rb_size = 50; + else + pusch_pdu->rb_size = 5; + } + else + AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - int ret = nr_configure_pdcch(nr_mac, - pdcch_pdu_rel15, - UE_list->rnti[UE_id], - 1, // ue-specific, - ss, - scc, - bwp); + pusch_pdu->vrb_to_prb_mapping = 0; - if (ret < 0) { - LOG_I(MAC,"CCE list not empty, couldn't schedule PUSCH\n"); - UL_tti_req->n_pdus-=1; - return; - } - else { + if (pusch_Config->frequencyHopping==NULL) + pusch_pdu->frequency_hopping = 0; + else + pusch_pdu->frequency_hopping = 1; + + //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] + //pusch_pdu->uplink_frequency_shift_7p5khz = 0; + + + // -------------------- + // ------- DMRS ------- + // -------------------- + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; + if (mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA) + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + else + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + if (NR_DMRS_UplinkConfig->dmrs_Type == NULL) + pusch_pdu->dmrs_config_type = 0; + else + pusch_pdu->dmrs_config_type = 1; + pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] + if (pusch_pdu->transform_precoding) { // transform precoding disabled + long *scramblingid; + if (pusch_pdu->scid == 0) + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; + else + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; + if (scramblingid == NULL) + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + else + pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; + } + else { + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + if (NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) + pusch_pdu->pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; + else + pusch_pdu->pusch_identity = *scc->physCellId; + } + pusch_dmrs_AdditionalPosition_t additional_pos; + if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL) + additional_pos = 2; + else { + if (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3) + additional_pos = 3; + else + additional_pos = *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition; + } + pusch_maxLength_t pusch_maxLength; + if (NR_DMRS_UplinkConfig->maxLength == NULL) + pusch_maxLength = 1; + else + pusch_maxLength = 2; + uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, mapping_type, additional_pos, pusch_maxLength); + pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; + + pusch_pdu->num_dmrs_cdm_grps_no_data = 1; + pusch_pdu->dmrs_ports = 1; + // -------------------------------------------------------------------------------------------------------------------------------------------- + + // -------------------- + // ------- PTRS ------- + // -------------------- + if (NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { + // TODO to be fixed from RRC config + uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig + pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); + pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); + pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); + pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + + pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + } + else{ + pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } + + // -------------------------------------------------------------------------------------------------------------------------------------------- + + //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] + //Optional Data only included if indicated in pduBitmap + int8_t harq_id = select_ul_harq_pid(&UE_list->UE_sched_ctrl[UE_id]); + if (harq_id < 0) return; + NR_UE_ul_harq_t *cur_harq = &UE_list->UE_sched_ctrl[UE_id].ul_harq_processes[harq_id]; + pusch_pdu->pusch_data.harq_process_id = harq_id; + pusch_pdu->pusch_data.new_data_indicator = cur_harq->ndi; + pusch_pdu->pusch_data.rv_index = nr_rv_round_map[cur_harq->round]; + + cur_harq->state = ACTIVE_SCHED; + cur_harq->last_tx_slot = pusch_sched->slot; + + uint8_t num_dmrs_symb = 0; + + for(int dmrs_counter = pusch_pdu->start_symbol_index; dmrs_counter < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; dmrs_counter++) + num_dmrs_symb += ((pusch_pdu->ul_dmrs_symb_pos >> dmrs_counter) & 1); + + uint8_t N_PRB_DMRS; + if (pusch_pdu->dmrs_config_type == 0) { + N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*6; + } + else { + N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*4; + } + + pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, + pusch_pdu->target_code_rate, + pusch_pdu->rb_size, + pusch_pdu->nr_of_symbols, + N_PRB_DMRS * num_dmrs_symb, + 0, //nb_rb_oh + 0, + pusch_pdu->nrOfLayers)>>3; + + UE_list->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++; + if (cur_harq->round == 0) UE_list->mac_stats[UE_id].ulsch_total_bytes_scheduled+=pusch_pdu->pusch_data.tb_size; + + pusch_pdu->pusch_data.num_cb = 0; //CBG not supported + //pusch_pdu->pusch_data.cb_present_and_position; + //pusch_pdu->pusch_uci; + //pusch_pdu->pusch_ptrs; + //pusch_pdu->dfts_ofdm; + //beamforming + //pusch_pdu->beamforming; //not used for now + + + ul_dci_request_pdu = &UL_dci_req->ul_dci_pdu_list[UL_dci_req->numPdus]; + memset((void*)ul_dci_request_pdu,0,sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + UL_dci_req->numPdus+=1; + + int dci_formats[2]; + int rnti_types[2]; + + NR_SearchSpace_t *ss; + int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + + AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); + AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, + "searchPsacesToAddModList is empty\n"); + + int found=0; + + for (int i=0;ibwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) { + ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; + AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n"); + AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n"); + if (ss->searchSpaceType->present == target_ss) { + found=1; + break; + } + } + AssertFatal(found==1,"Couldn't find an adequate searchspace\n"); + + if (ss->searchSpaceType->choice.ue_Specific->dci_Formats) + dci_formats[0] = NR_UL_DCI_FORMAT_0_1; + else + dci_formats[0] = NR_UL_DCI_FORMAT_0_0; + + rnti_types[0] = NR_RNTI_C; + LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frameP,slotP); + + int ret = nr_configure_pdcch(nr_mac, + pdcch_pdu_rel15, + UE_list->rnti[UE_id], + 1, // ue-specific, + ss, + scc, + bwp); + + if (ret < 0) { + LOG_I(MAC,"CCE list not empty, couldn't schedule PUSCH\n"); + pusch_sched->active = false; + return; + } + else { dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t)); - config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,time_domain_assignment,n_ubwp,bwp_id); + config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,time_domain_assignment,UE_list->UE_sched_ctrl[UE_id].tpc0,n_ubwp,bwp_id); fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); free(dci_pdu_rel15); + } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 4bb7eab6b7..35d7209321 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1484,7 +1484,17 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ memset((void *) &UE_list->UE_sched_ctrl[UE_id], 0, sizeof(NR_UE_sched_ctrl_t)); + UE_list->UE_sched_ctrl[UE_id].ul_rssi = 0; UE_list->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch *)malloc(num_slots_ul*sizeof(NR_sched_pucch)); + UE_list->UE_sched_ctrl[UE_id].sched_pusch = (NR_sched_pusch *)malloc(num_slots_ul*sizeof(NR_sched_pusch)); + for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k], + 0, + sizeof(NR_sched_pucch)); + memset((void *) &UE_list->UE_sched_ctrl[UE_id].sched_pusch[k], + 0, + sizeof(NR_sched_pusch)); + } LOG_I(MAC, "gNB %d] Add NR UE_id %d : rnti %x\n", mod_idP, UE_id, @@ -1501,6 +1511,18 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ return -1; } + +uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) { + // al values passed to this function are x10 + + int snrx10 = (cqi*5) - 640; + if (snrx10 > target + incr) return 0; // decrease 1dB + if (snrx10 < target - incr) return 2; // increase 1dB + if (snrx10 < target - (3*incr)) return 3; // increase 3dB + return 1; // no change +} + + void get_pdsch_to_harq_feedback(int Mod_idP, int UE_id, NR_SearchSpace__searchSpaceType_PR ss_type, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 89c3fe69fe..bb0dad7064 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -36,6 +36,7 @@ void nr_process_mac_pdu( module_id_t module_idP, + rnti_t rnti, uint8_t CC_id, frame_t frameP, uint8_t *pduP, @@ -210,7 +211,8 @@ void nr_process_mac_pdu( } LOG_D(MAC, "[UE %d] Frame %d : ULSCH -> UL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len); - + int UE_id = find_nr_UE_id(module_idP, rnti); + RC.nrmac[module_idP]->UE_list.mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len; #if defined(ENABLE_MAC_PAYLOAD_DEBUG) LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); @@ -219,25 +221,33 @@ void nr_process_mac_pdu( LOG_T(MAC, "\n"); #endif - - if (IS_SOFTMODEM_NOS1){ - if (rx_lcid < NB_RB_MAX && rx_lcid >= UL_SCH_LCID_DTCH) { - - mac_rlc_data_ind(module_idP, - 0x1234, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pdu_ptr + mac_subheader_len), - mac_sdu_len, - 1, - NULL); - } else { - LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, module_idP); - } + if(IS_SOFTMODEM_NOS1){ + mac_rlc_data_ind(module_idP, + 0x1234, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pdu_ptr + mac_subheader_len), + mac_sdu_len, + 1, + NULL); } + else{ + mac_rlc_data_ind(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pdu_ptr + mac_subheader_len), + mac_sdu_len, + 1, + NULL); + } + break; @@ -255,6 +265,39 @@ void nr_process_mac_pdu( } } +void handle_nr_ul_harq(uint16_t slot, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, nfapi_nr_crc_t crc_pdu) { + + int max_harq_rounds = 4; // TODO define macro + uint8_t hrq_id = crc_pdu.harq_id; + NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id]; + if (cur_harq->state==ACTIVE_SCHED) { + if (!crc_pdu.tb_crc_status) { + cur_harq->ndi ^= 1; + cur_harq->round = 0; + cur_harq->state = INACTIVE; // passed -> make inactive. can be used by scheduder for next grant +#ifdef UL_HARQ_PRINT + printf("[HARQ HANDLER] Ulharq id %d crc passed, freeing it for scheduler\n",hrq_id); +#endif + } else { + cur_harq->round++; + cur_harq->state = ACTIVE_NOT_SCHED; +#ifdef UL_HARQ_PRINT + printf("[HARQ HANDLER] Ulharq id %d crc failed, requesting retransmission\n",hrq_id); +#endif + } + + if (!(cur_harq->roundndi ^= 1; + cur_harq->state = INACTIVE; // failed after 4 rounds -> make inactive + cur_harq->round = 0; + LOG_D(MAC,"[HARQ HANDLER] RNTI %x: Ulharq id %d crc failed in all round, freeing it for scheduler\n",crc_pdu.rnti,hrq_id); + stats->ulsch_errors++; + } + return; + } else + LOG_E(MAC,"Incorrect ULSCH HARQ process %d or invalid state %d\n",hrq_id,cur_harq->state); +} + /* * When data are received on PHY and transmitted to MAC */ @@ -266,7 +309,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, uint8_t *sduP, const uint16_t sdu_lenP, const uint16_t timing_advance, - const uint8_t ul_cqi){ + const uint8_t ul_cqi, + const uint16_t rssi){ int current_rnti = 0, UE_id = -1, harq_pid = 0; gNB_MAC_INST *gNB_mac = NULL; NR_UE_list_t *UE_list = NULL; @@ -276,10 +320,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti); gNB_mac = RC.nrmac[gnb_mod_idP]; UE_list = &gNB_mac->UE_list; + int target_snrx10 = gNB_mac->pusch_target_snrx10; if (UE_id != -1) { UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + UE_list->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP; LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d\n", gnb_mod_idP, harq_pid, @@ -290,20 +336,33 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, UE_id, ul_cqi); + // if not missed detection (10dB threshold for now) + if (UE_scheduling_control->ul_rssi < (100+rssi)) { + UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30); + UE_scheduling_control->ta_update = timing_advance; + UE_scheduling_control->ul_rssi = rssi; + LOG_D(MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); + } + else{ + UE_scheduling_control->tpc0 = 1; + } + #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_I(MAC, "Printing received UL MAC payload at gNB side: %d \n"); - for (int i = 0; i < sdu_lenP ; i++) { + LOG_I(MAC, "Printing received UL MAC payload at gNB side: %d \n"); + for (int i = 0; i < sdu_lenP ; i++) { //harq_process_ul_ue->a[i] = (unsigned char) rand(); //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); printf("%02x ",(unsigned char)sduP[i]); - } - printf("\n"); + } + printf("\n"); #endif if (sduP != NULL){ - UE_scheduling_control->ta_update = timing_advance; LOG_D(MAC, "Received PDU at MAC gNB \n"); - nr_process_mac_pdu(gnb_mod_idP, CC_idP, frameP, sduP, sdu_lenP); + nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP); + } + else { + } } else { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 8711c4bef2..2c7c955506 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -50,6 +50,8 @@ void config_common(int Mod_idP, int rrc_mac_config_req_gNB(module_id_t Mod_idP, int ssb_SubcarrierOffset, int pdsch_AntennaPorts, + int pusch_tgt_snrx10, + int pucch_tgt_snrx10, NR_ServingCellConfigCommon_t *scc, int nsa_flag, uint32_t rnti, @@ -62,7 +64,6 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, sub_frame_t subframeP); void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame_txP, sub_frame_t slot_txP, frame_t frame_rxP, sub_frame_t slot_rxP); int nr_generate_dlsch_pdu(module_id_t Mod_idP, @@ -137,7 +138,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types, - int time_domain_assignment, + int time_domain_assignment, uint8_t tpc, int n_ubwp, int bwp_id); void configure_fapi_dl_Tx(module_id_t Mod_idP, @@ -154,9 +155,18 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, NR_sched_pucch *pucch_sched, nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_config); -void nr_schedule_uss_ulsch_phytest(int Mod_idP, - frame_t frameP, - sub_frame_t slotP); +void nr_schedule_pusch(int Mod_idP, + int UE_id, + int num_slots_per_tdd, + int ul_slots, + frame_t frameP, + sub_frame_t slotP); + +void nr_schedule_pucch(int Mod_idP, + int UE_id, + int nr_ulmix_slots, + frame_t frameP, + sub_frame_t slotP); void nr_update_pucch_scheduling(int Mod_idP, int UE_id, @@ -227,6 +237,8 @@ void find_aggregation_candidates(uint8_t *aggregation_level, uint8_t *nr_of_candidates, NR_SearchSpace_t *ss); +uint8_t nr_get_tpc(int target, uint8_t cqi, int incr); + int get_spf(nfapi_nr_config_request_scf_t *cfg); int to_absslot(nfapi_nr_config_request_scf_t *cfg,int frame,int slot); @@ -291,9 +303,16 @@ void nr_generate_Msg2(module_id_t module_idP, void nr_schedule_reception_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP); +void schedule_fapi_ul_pdu(int Mod_idP, + frame_t frameP, + sub_frame_t slotP, + int num_slots_per_tdd, + int ul_slots, + int time_domain_assignment); void nr_process_mac_pdu( module_id_t module_idP, + rnti_t rnti, uint8_t CC_id, frame_t frameP, uint8_t *pduP, @@ -301,6 +320,8 @@ void nr_process_mac_pdu( int binomial(int n, int k); +bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); + /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB @@ -318,15 +339,20 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, const rnti_t rntiP, uint8_t * sduP, const uint16_t sdu_lenP, - const uint16_t timing_advance, const uint8_t ul_cqi); + const uint16_t timing_advance, + const uint8_t ul_cqi, + const uint16_t rssi); + +void handle_nr_ul_harq(uint16_t slot, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, nfapi_nr_crc_t crc_pdu); int16_t ssb_index_from_prach(module_id_t module_idP, frame_t frameP, - sub_frame_t slotP, + sub_frame_t slotP, uint16_t preamble_index, uint8_t freq_index, uint8_t symbol); void find_SSB_and_RO_available(module_id_t module_idP); +void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10); #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 56e020838d..bd0be8c409 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -35,6 +35,7 @@ #include "assertions.h" #include "LAYER2/PDCP_v10.1.0/pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "RRC/NR/nr_rrc_defs.h" #include "common/utils/LOG/log.h" //#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" @@ -89,7 +90,7 @@ void mac_top_init_gNB(void) pdcp_layer_init(); if(IS_SOFTMODEM_NOS1) - nr_ip_over_LTE_DRB_preconfiguration(); + nr_DRB_preconfiguration(); rrc_init_nr_global_param(); @@ -117,6 +118,9 @@ void mac_top_init_gNB(void) UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].round = 0; UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].ndi = 0; UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].is_waiting = 0; + UE_list->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].round = 0; + UE_list->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].ndi = 0; + UE_list->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].state = 0; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index a5f0ce6a12..7d24e58dd3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -261,8 +261,16 @@ typedef struct NR_sched_pucch { uint8_t dai_c; uint8_t timing_indicator; uint8_t resource_indicator; + bool active; } NR_sched_pucch; +typedef struct NR_sched_pusch { + int frame; + int slot; + bool active; + nfapi_nr_pusch_pdu_t pusch_pdu; +} NR_sched_pusch; + typedef struct NR_UE_harq { uint8_t is_waiting; uint8_t ndi; @@ -270,15 +278,33 @@ typedef struct NR_UE_harq { uint16_t feedback_slot; } NR_UE_harq_t; +typedef enum { + INACTIVE = 0, + ACTIVE_NOT_SCHED, + ACTIVE_SCHED +} NR_UL_harq_states_t; + +typedef struct NR_UE_ul_harq { + uint8_t ndi; + uint8_t round; + uint16_t last_tx_slot; + NR_UL_harq_states_t state; +} NR_UE_ul_harq_t; + /*! \brief scheduling control information set through an API */ typedef struct { uint64_t dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch uint64_t ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch NR_sched_pucch *sched_pucch; + NR_sched_pusch *sched_pusch; uint16_t ta_timer; int16_t ta_update; + uint8_t tpc0; + uint8_t tpc1; + uint16_t ul_rssi; uint8_t current_harq_pid; NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; + NR_UE_ul_harq_t ul_harq_processes[NR_MAX_NB_HARQ_PROCESSES]; int dummy; NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information } NR_UE_sched_ctrl_t; @@ -288,11 +314,25 @@ typedef struct NR_preamble_ue { uint8_t *preamble_list; } NR_preamble_ue; +typedef struct { + + int lc_bytes_tx[64]; + int lc_bytes_rx[64]; + int dlsch_rounds[8]; + int dlsch_errors; + int dlsch_total_bytes; + int ulsch_rounds[8]; + int ulsch_errors; + int ulsch_total_bytes_scheduled; + int ulsch_total_bytes_rx; +} NR_mac_stats_t; + /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ typedef struct { DLSCH_PDU DLSCH_pdu[4][MAX_MOBILES_PER_GNB]; /// scheduling control info NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB]; + NR_mac_stats_t mac_stats[MAX_MOBILES_PER_GNB]; int next[MAX_MOBILES_PER_GNB]; int head; int next_ul[MAX_MOBILES_PER_GNB]; @@ -330,14 +370,14 @@ typedef struct gNB_MAC_INST_s { eth_params_t eth_params_s; /// Module module_id_t Mod_id; - /// frame counter - frame_t frame; - /// slot counter - int slot; /// timing advance group NR_TAG_t *tag; /// Pointer to IF module instance for PHY NR_IF_Module_t *if_inst; + /// Pusch target SNR + int pusch_target_snrx10; + /// Pucch target SNR + int pucch_target_snrx10; /// TA command int ta_command; /// MAC CE flag indicating TA length diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 3667af2698..33f268f07f 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -2353,101 +2353,6 @@ void pdcp_module_cleanup (void) { } -void nr_ip_over_LTE_DRB_preconfiguration(void){ - - // Addition for the use-case of 4G stack on top of 5G-NR. - // We need to configure pdcp and rlc instances without having an actual - // UE RRC Connection. In order to be able to test the NR PHY with some injected traffic - // on top of the LTE stack. - protocol_ctxt_t ctxt; - LTE_DRB_ToAddModList_t* DRB_configList=NULL; - DRB_configList = CALLOC(1, sizeof(LTE_DRB_ToAddModList_t)); - struct LTE_LogicalChannelConfig *DRB_lchan_config = NULL; - struct LTE_RLC_Config *DRB_rlc_config = NULL; - struct LTE_PDCP_Config *DRB_pdcp_config = NULL; - struct LTE_PDCP_Config__rlc_UM *PDCP_rlc_UM = NULL; - - struct LTE_DRB_ToAddMod *DRB_config = NULL; - struct LTE_LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters = NULL; - long *logicalchannelgroup_drb; - - - //Static preconfiguration of DRB - DRB_config = CALLOC(1, sizeof(*DRB_config)); - - DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long)); - // allowed value 5..15, value : x+4 - *(DRB_config->eps_BearerIdentity) = 1; //ue_context_pP->ue_context.e_rab[i].param.e_rab_id;//+ 4; // especial case generation - // DRB_config->drb_Identity = 1 + drb_identity_index + e_rab_done;// + i ;// (DRB_Identity_t) ue_context_pP->ue_context.e_rab[i].param.e_rab_id; - // 1 + drb_identiy_index; - DRB_config->drb_Identity = 1; - DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long)); - *(DRB_config->logicalChannelIdentity) = DRB_config->drb_Identity + 3; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2 - - DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config)); - DRB_config->rlc_Config = DRB_rlc_config; - - DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config)); - DRB_config->pdcp_Config = DRB_pdcp_config; - DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long)); - *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity; - DRB_pdcp_config->rlc_AM = NULL; - DRB_pdcp_config->rlc_UM = NULL; - - DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional; - DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10; - DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35; - // PDCP - PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); - DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; - PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; - - DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed; - - DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config)); - DRB_config->logicalChannelConfig = DRB_lchan_config; - DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters)); - DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters; - - DRB_ul_SpecificParameters->priority= 4; - - DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8; - //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - DRB_ul_SpecificParameters->bucketSizeDuration = - LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - - logicalchannelgroup_drb = CALLOC(1, sizeof(long)); - *logicalchannelgroup_drb = 1;//(i+1) % 3; - DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb; - - ASN_SEQUENCE_ADD(&DRB_configList->list,DRB_config); - - if (ENB_NAS_USE_TUN){ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, 0x1234, 0, 0,0); - } - else{ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0); - } - - rrc_pdcp_config_asn1_req(&ctxt, - (LTE_SRB_ToAddModList_t *) NULL, - DRB_configList, - (LTE_DRB_ToReleaseList_t *) NULL, - 0xff, NULL, NULL, NULL - , (LTE_PMCH_InfoList_r9_t *) NULL, - &DRB_config->drb_Identity); - - rrc_rlc_config_asn1_req(&ctxt, - (LTE_SRB_ToAddModList_t*)NULL, - DRB_configList, - (LTE_DRB_ToReleaseList_t*)NULL - //#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0)) - ,(LTE_PMCH_InfoList_r9_t *)NULL - , 0, 0 - //#endif - ); -} //----------------------------------------------------------------------------- void pdcp_layer_init(void) //----------------------------------------------------------------------------- diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index 6c6bd30070..c9a62d573b 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -310,7 +310,7 @@ int pdcp_fifo_read_input_mbms_sdus_fromtun (const protocol_ctxt_t *const ctxt_p ctxt.module_id, ctxt.rnti, ctxt.enb_flag); if (h_rc == HASH_TABLE_OK) { - LOG_I(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %ld \n", + LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d on Rab %ld \n", ctxt.frame, ctxt.instance, len, rab_id); LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %ld][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %04x][RB %ld]\n", ctxt.frame, ctxt.instance, rab_id, len, ctxt.module_id, diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c index 2fb844f05a..98c8c3e252 100644 --- a/openair2/LAYER2/RLC/rlc.c +++ b/openair2/LAYER2/RLC/rlc.c @@ -519,7 +519,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, // LOG_I(RLC,"DUY rlc_data_req: mbms_rb_id in RLC instant is: %d\n", mbms_rb_id); if (sdu_pP != NULL) { if (sdu_sizeP > 0) { - LOG_I(RLC,"received a packet with size %d for MBMS \n", sdu_sizeP); + LOG_D(RLC,"received a packet with size %d for MBMS \n", sdu_sizeP); new_sdu_p = get_free_mem_block (sdu_sizeP + sizeof (struct rlc_um_data_req_alloc), __func__); if (new_sdu_p != NULL) { diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c index 85ee4e0571..4313f379fe 100644 --- a/openair2/LAYER2/RLC/rlc_rrc.c +++ b/openair2/LAYER2/RLC/rlc_rrc.c @@ -640,7 +640,8 @@ rlc_union_t *rrc_rlc_add_rlc ( } else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) { rlc_union_p = calloc(1, sizeof(rlc_union_t)); h_rc = hashtable_insert(rlc_coll_p, key, rlc_union_p); - h_lcid_rc = hashtable_insert(rlc_coll_p, key_lcid, rlc_union_p); + if(MBMS_flagP != TRUE) + h_lcid_rc = hashtable_insert(rlc_coll_p, key_lcid, rlc_union_p); if ((h_rc == HASH_TABLE_OK) && (h_lcid_rc == HASH_TABLE_OK)) { if (MBMS_flagP == TRUE) { diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c new file mode 100644 index 0000000000..e25201c22c --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -0,0 +1,74 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_entity.h" + +#include "nr_pdcp_entity_drb_am.h" + +#include "LOG/log.h" + +nr_pdcp_entity_t *new_nr_pdcp_entity_srb( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data) +{ + abort(); +} + +nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data) +{ + nr_pdcp_entity_drb_am_t *ret; + + ret = calloc(1, sizeof(nr_pdcp_entity_drb_am_t)); + if (ret == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ret->common.recv_pdu = nr_pdcp_entity_drb_am_recv_pdu; + ret->common.recv_sdu = nr_pdcp_entity_drb_am_recv_sdu; + ret->common.set_integrity_key = nr_pdcp_entity_drb_am_set_integrity_key; + + ret->common.delete = nr_pdcp_entity_drb_am_delete; + + ret->common.deliver_sdu = deliver_sdu; + ret->common.deliver_sdu_data = deliver_sdu_data; + + ret->common.deliver_pdu = deliver_pdu; + ret->common.deliver_pdu_data = deliver_pdu_data; + + ret->rb_id = rb_id; + + ret->common.maximum_nr_pdcp_sn = 4095; + + return (nr_pdcp_entity_t *)ret; +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h new file mode 100644 index 0000000000..45555ad6af --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_PDCP_ENTITY_H_ +#define _NR_PDCP_ENTITY_H_ + +typedef struct nr_pdcp_entity_t { + /* functions provided by the PDCP module */ + void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size); + void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, + int sdu_id); + void (*delete)(struct nr_pdcp_entity_t *entity); + void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key); + + /* callbacks provided to the PDCP module */ + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size); + void *deliver_sdu_data; + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id); + void *deliver_pdu_data; + int tx_hfn; + int next_nr_pdcp_tx_sn; + int maximum_nr_pdcp_sn; +} nr_pdcp_entity_t; + +nr_pdcp_entity_t *new_nr_pdcp_entity_srb( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data); + +nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( + int rb_id, + void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id), + void *deliver_pdu_data); + +void nr_DRB_preconfiguration(void); + +#endif /* _NR_PDCP_ENTITY_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c new file mode 100644 index 0000000000..85f638d66d --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c @@ -0,0 +1,71 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_entity_drb_am.h" + +#include +#include +#include + +void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size) +{ + nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + + if (size < 3) abort(); + if (!(buffer[0] & 0x80)) { printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } + entity->common.deliver_sdu(entity->common.deliver_sdu_data, + (nr_pdcp_entity_t *)entity, buffer+3, size-3); +} + +void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int size, + int sdu_id) +{ + nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + int sn; + char buf[size+2]; + + sn = entity->common.next_nr_pdcp_tx_sn; + + entity->common.next_nr_pdcp_tx_sn++; + if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) { + entity->common.next_nr_pdcp_tx_sn = 0; + entity->common.tx_hfn++; + } + + buf[0] = 0x80 | ((sn >> 16) & 0x3); + buf[1] = (sn >> 8) & 0xff; + buf[2] = sn & 0xff; + memcpy(buf+3, buffer, size); + + entity->common.deliver_pdu(entity->common.deliver_pdu_data, + (nr_pdcp_entity_t *)entity, buf, size+3, sdu_id); +} + +void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *key) +{ + /* nothing to do */ +} + +void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity) +{ + nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + free(entity); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h new file mode 100644 index 0000000000..faa8226e93 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h @@ -0,0 +1,38 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_PDCP_ENTITY_DRB_AM_H_ +#define _NR_PDCP_ENTITY_DRB_AM_H_ + +#include "nr_pdcp_entity.h" + +typedef struct { + nr_pdcp_entity_t common; + int rb_id; +} nr_pdcp_entity_drb_am_t; + +void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size); +void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size, + int sdu_id); +void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key); +void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity); + +#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c new file mode 100644 index 0000000000..c8b385bbfc --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -0,0 +1,946 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_ue_manager.h" +#include "NR_RadioBearerConfig.h" +#include "NR_RLC-BearerConfig.h" +#include "NR_CellGroupConfig.h" +#include "openair2/RRC/NR/nr_rrc_proto.h" + +/* from OAI */ +#include "pdcp.h" + +#define TODO do { \ + printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \ + exit(1); \ + } while (0) + +static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager; + +/* necessary globals for OAI, not used internally */ +hash_table_t *pdcp_coll_p; +static uint64_t pdcp_optmask; + +/****************************************************************************/ +/* rlc_data_req queue - begin */ +/****************************************************************************/ + +#include + +/* NR PDCP and RLC both use "big locks". In some cases a thread may do + * lock(rlc) followed by lock(pdcp) (typically when running 'rx_sdu'). + * Another thread may first do lock(pdcp) and then lock(rlc) (typically + * the GTP module calls 'pdcp_data_req' that, in a previous implementation + * was indirectly calling 'rlc_data_req' which does lock(rlc)). + * To avoid the resulting deadlock it is enough to ensure that a call + * to lock(pdcp) will never be followed by a call to lock(rlc). So, + * here we chose to have a separate thread that deals with rlc_data_req, + * out of the PDCP lock. Other solutions may be possible. + * So instead of calling 'rlc_data_req' directly we have a queue and a + * separate thread emptying it. + */ + +typedef struct { + protocol_ctxt_t ctxt_pP; + srb_flag_t srb_flagP; + MBMS_flag_t MBMS_flagP; + rb_id_t rb_idP; + mui_t muiP; + confirm_t confirmP; + sdu_size_t sdu_sizeP; + mem_block_t *sdu_pP; +} rlc_data_req_queue_item; + +#define RLC_DATA_REQ_QUEUE_SIZE 10000 + +typedef struct { + rlc_data_req_queue_item q[RLC_DATA_REQ_QUEUE_SIZE]; + volatile int start; + volatile int length; + pthread_mutex_t m; + pthread_cond_t c; +} rlc_data_req_queue; + +static rlc_data_req_queue q; + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +static void *rlc_data_req_thread(void *_) +{ + int i; + + while (1) { + if (pthread_mutex_lock(&q.m) != 0) abort(); + while (q.length == 0) + if (pthread_cond_wait(&q.c, &q.m) != 0) abort(); + i = q.start; + if (pthread_mutex_unlock(&q.m) != 0) abort(); + + rlc_data_req(&q.q[i].ctxt_pP, + q.q[i].srb_flagP, + q.q[i].MBMS_flagP, + q.q[i].rb_idP, + q.q[i].muiP, + q.q[i].confirmP, + q.q[i].sdu_sizeP, + q.q[i].sdu_pP, + NULL, + NULL); + + if (pthread_mutex_lock(&q.m) != 0) abort(); + + q.length--; + q.start = (q.start + 1) % RLC_DATA_REQ_QUEUE_SIZE; + + if (pthread_cond_signal(&q.c) != 0) abort(); + if (pthread_mutex_unlock(&q.m) != 0) abort(); + } +} + +static void init_nr_rlc_data_req_queue(void) +{ + pthread_t t; + + pthread_mutex_init(&q.m, NULL); + pthread_cond_init(&q.c, NULL); + + if (pthread_create(&t, NULL, rlc_data_req_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void enqueue_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP, + void *_unused1, void *_unused2) +{ + int i; + int logged = 0; + + if (pthread_mutex_lock(&q.m) != 0) abort(); + while (q.length == RLC_DATA_REQ_QUEUE_SIZE) { + if (!logged) { + logged = 1; + LOG_W(PDCP, "%s: rlc_data_req queue is full\n", __FUNCTION__); + } + if (pthread_cond_wait(&q.c, &q.m) != 0) abort(); + } + + i = (q.start + q.length) % RLC_DATA_REQ_QUEUE_SIZE; + q.length++; + + q.q[i].ctxt_pP = *ctxt_pP; + q.q[i].srb_flagP = srb_flagP; + q.q[i].MBMS_flagP = MBMS_flagP; + q.q[i].rb_idP = rb_idP; + q.q[i].muiP = muiP; + q.q[i].confirmP = confirmP; + q.q[i].sdu_sizeP = sdu_sizeP; + q.q[i].sdu_pP = sdu_pP; + + if (pthread_cond_signal(&q.c) != 0) abort(); + if (pthread_mutex_unlock(&q.m) != 0) abort(); +} + +/****************************************************************************/ +/* rlc_data_req queue - end */ +/****************************************************************************/ + +/****************************************************************************/ +/* hacks to be cleaned up at some point - begin */ +/****************************************************************************/ + +#include "LAYER2/MAC/mac_extern.h" + +static void reblock_tun_socket(void) +{ + extern int nas_sock_fd[]; + int f; + + f = fcntl(nas_sock_fd[0], F_GETFL, 0); + f &= ~(O_NONBLOCK); + if (fcntl(nas_sock_fd[0], F_SETFL, f) == -1) { + LOG_E(PDCP, "reblock_tun_socket failed\n"); + exit(1); + } +} + +static void *enb_tun_read_thread(void *_) +{ + extern int nas_sock_fd[]; + char rx_buf[NL_MAX_PAYLOAD]; + int len; + int rnti; + protocol_ctxt_t ctxt; + + int rb_id = 1; + + while (1) { + len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); + if (len == -1) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + +printf("\n\n\n########## nas_sock_fd read returns len %d\n", len); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + if (rnti == -1) continue; + + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = rnti; + + pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, + RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, + PDCP_TRANSMISSION_MODE_DATA, NULL, NULL); + } + + return NULL; +} + +static void *ue_tun_read_thread(void *_) +{ + extern int nas_sock_fd[]; + char rx_buf[NL_MAX_PAYLOAD]; + int len; + int rnti; + protocol_ctxt_t ctxt; + + int rb_id = 1; + + while (1) { + len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD); + if (len == -1) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + +printf("\n\n\n########## nas_sock_fd read returns len %d\n", len); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + if (rnti == -1) continue; + + ctxt.module_id = 0; + ctxt.enb_flag = 0; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = rnti; + + pdcp_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, + RLC_SDU_CONFIRM_NO, len, (unsigned char *)rx_buf, + PDCP_TRANSMISSION_MODE_DATA, NULL, NULL); + } + + return NULL; +} + +static void start_pdcp_tun_enb(void) +{ + pthread_t t; + + reblock_tun_socket(); + + if (pthread_create(&t, NULL, enb_tun_read_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void start_pdcp_tun_ue(void) +{ + pthread_t t; + + reblock_tun_socket(); + + if (pthread_create(&t, NULL, ue_tun_read_thread, NULL) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/****************************************************************************/ +/* hacks to be cleaned up at some point - end */ +/****************************************************************************/ + +int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) +{ + return 0; +} + +void pdcp_layer_init(void) +{ + /* hack: be sure to initialize only once */ + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + static int initialized = 0; + if (pthread_mutex_lock(&m) != 0) abort(); + if (initialized) { + if (pthread_mutex_unlock(&m) != 0) abort(); + return; + } + initialized = 1; + if (pthread_mutex_unlock(&m) != 0) abort(); + + nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); + init_nr_rlc_data_req_queue(); +} + +#include "nfapi/oai_integration/vendor_ext.h" +#include "targets/RT/USER/lte-softmodem.h" +#include "openair2/RRC/NAS/nas_config.h" + +uint64_t pdcp_module_init(uint64_t _pdcp_optmask) +{ + /* hack: be sure to initialize only once */ + static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + static int initialized = 0; + if (pthread_mutex_lock(&m) != 0) abort(); + if (initialized) { + abort(); + } + initialized = 1; + if (pthread_mutex_unlock(&m) != 0) abort(); + +#if 0 + pdcp_optmask = _pdcp_optmask; + return pdcp_optmask; +#endif + /* temporary enforce netlink when UE_NAS_USE_TUN is set, + this is while switching from noS1 as build option + to noS1 as config option */ + if ( _pdcp_optmask & UE_NAS_USE_TUN_BIT) { + pdcp_optmask = pdcp_optmask | PDCP_USE_NETLINK_BIT ; + } + + pdcp_optmask = pdcp_optmask | _pdcp_optmask ; + LOG_I(PDCP, "pdcp init,%s %s\n", + ((LINK_ENB_PDCP_TO_GTPV1U)?"usegtp":""), + ((PDCP_USE_NETLINK)?"usenetlink":"")); + + if (PDCP_USE_NETLINK) { + nas_getparams(); + + if(UE_NAS_USE_TUN) { + int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1; + netlink_init_tun("ue",num_if); + //Add --nr-ip-over-lte option check for next line + if (IS_SOFTMODEM_NOS1) + nas_config(1, 1, 2, "ue"); + LOG_I(PDCP, "UE pdcp will use tun interface\n"); + start_pdcp_tun_ue(); + } else if(ENB_NAS_USE_TUN) { + netlink_init_tun("enb",1); + nas_config(1, 1, 1, "enb"); + LOG_I(PDCP, "ENB pdcp will use tun interface\n"); + start_pdcp_tun_enb(); + } else { + LOG_I(PDCP, "pdcp will use kernel modules\n"); + abort(); + netlink_init(); + } + } + return pdcp_optmask ; +} + +static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size) +{ + extern int nas_sock_fd[]; + int len; + nr_pdcp_ue_t *ue = _ue; + MessageDef *message_p; + uint8_t *gtpu_buffer_p; + int rb_id; + int i; + + if(IS_SOFTMODEM_NOS1){ + len = write(nas_sock_fd[0], buf, size); + if (len != size) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + } + else{ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + + rb_found: + gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U, + size + GTPU_HEADER_OVERHEAD_MAX); + AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY"); + memcpy(>pu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], buf, size); + message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ); + AssertFatal(message_p != NULL, "OUT OF MEMORY"); + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer = gtpu_buffer_p; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length = size; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset = GTPU_HEADER_OVERHEAD_MAX; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti = ue->rnti; + GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id = rb_id + 4; + printf("!!!!!!! deliver_sdu_drb (drb %d) sending message to gtp size %d: ", rb_id, size); + //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)buf[i]); + printf("\n"); + itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); + + } +} + +static void deliver_pdu_drb(void *_ue, nr_pdcp_entity_t *entity, + char *buf, int size, int sdu_id) +{ + nr_pdcp_ue_t *ue = _ue; + int rb_id; + protocol_ctxt_t ctxt; + int i; + mem_block_t *memblock; + + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + ctxt.module_id = 0; + ctxt.enb_flag = 1; + ctxt.instance = 0; + ctxt.frame = 0; + ctxt.subframe = 0; + ctxt.eNB_index = 0; + ctxt.configured = 1; + ctxt.brOption = 0; + + ctxt.rnti = ue->rnti; + + memblock = get_free_mem_block(size, __FUNCTION__); + memcpy(memblock->data, buf, size); + +printf("!!!!!!! deliver_pdu_drb (srb %d) calling rlc_data_req size %d: ", rb_id, size); +//for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); +printf("\n"); + enqueue_rlc_data_req(&ctxt, 0, MBMS_FLAG_NO, rb_id, sdu_id, 0, size, memblock, NULL, NULL); +} + +boolean_t pdcp_data_ind( + const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer) +{ + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + + if (ctxt_pP->module_id != 0 || + //ctxt_pP->enb_flag != 1 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 || + ctxt_pP->configured != 1 || + ctxt_pP->brOption != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (ctxt_pP->enb_flag) + T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(rnti), + T_INT(rb_id), T_INT(sdu_buffer_size)); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + if (srb_flagP == 1) { + if (rb_id < 1 || rb_id > 2) + rb = NULL; + else + rb = ue->srb[rb_id - 1]; + } else { + if (rb_id < 1 || rb_id > 5) + rb = NULL; + else + rb = ue->drb[rb_id - 1]; + } + + if (rb != NULL) { + rb->recv_pdu(rb, (char *)sdu_buffer->data, sdu_buffer_size); + } else { + LOG_E(PDCP, "%s:%d:%s: fatal: no RB found (rb_id %ld, srb_flag %d)\n", + __FILE__, __LINE__, __FUNCTION__, rb_id, srb_flagP); + exit(1); + } + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + free_mem_block(sdu_buffer, __FUNCTION__); + + return 1; +} + +void pdcp_run(const protocol_ctxt_t *const ctxt_pP) +{ + MessageDef *msg_p; + int result; + protocol_ctxt_t ctxt; + + while (1) { + itti_poll_msg(ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p); + if (msg_p == NULL) + break; + switch (ITTI_MSG_ID(msg_p)) { + case RRC_DCCH_DATA_REQ: + PROTOCOL_CTXT_SET_BY_MODULE_ID( + &ctxt, + RRC_DCCH_DATA_REQ(msg_p).module_id, + RRC_DCCH_DATA_REQ(msg_p).enb_flag, + RRC_DCCH_DATA_REQ(msg_p).rnti, + RRC_DCCH_DATA_REQ(msg_p).frame, + 0, + RRC_DCCH_DATA_REQ(msg_p).eNB_index); + result = pdcp_data_req(&ctxt, + SRB_FLAG_YES, + RRC_DCCH_DATA_REQ(msg_p).rb_id, + RRC_DCCH_DATA_REQ(msg_p).muip, + RRC_DCCH_DATA_REQ(msg_p).confirmp, + RRC_DCCH_DATA_REQ(msg_p).sdu_size, + RRC_DCCH_DATA_REQ(msg_p).sdu_p, + RRC_DCCH_DATA_REQ(msg_p).mode, + NULL, NULL); + + if (result != TRUE) + LOG_E(PDCP, "PDCP data request failed!\n"); + result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + break; + default: + LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p)); + break; + } + } +} + +static void add_srb(int rnti, struct NR_SRB_ToAddMod *s) +{ + TODO; +} + +static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s) +{ + nr_pdcp_entity_t *pdcp_drb; + nr_pdcp_ue_t *ue; + + int drb_id = s->drb_Identity; + +printf("\n\n################# rnti %d add drb %d\n\n\n", rnti, drb_id); + + if (drb_id != 1) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id); + exit(1); + } + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + if (ue->drb[drb_id-1] != NULL) { + LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } else { + pdcp_drb = new_nr_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue); + nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); + + LOG_D(PDCP, "%s:%d:%s: added drb %d to ue %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); +} + +static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_Config_t *rlc_Config) +{ + switch (rlc_Config->present) { + case NR_RLC_Config_PR_am: + add_drb_am(rnti, s); + break; + case NR_RLC_Config_PR_um_Bi_Directional: + //add_drb_um(rnti, s); + /* hack */ + add_drb_am(rnti, s); + break; + default: + LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 +#endif + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) + //struct NR_RLC_Config *rlc_Config) +{ + int rnti = ctxt_pP->rnti; + int i; + + if (//ctxt_pP->enb_flag != 1 || + ctxt_pP->module_id != 0 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 || + //ctxt_pP->configured != 2 || + //srb2add_list == NULL || + //drb2add_list != NULL || + drb2release_list != NULL || + security_modeP != 255 || + //kRRCenc != NULL || + //kRRCint != NULL || + //kUPenc != NULL || + pmch_InfoList_r9 != NULL /*|| + defaultDRB != NULL */) { + TODO; + } + + if (srb2add_list != NULL) { + for (i = 0; i < srb2add_list->list.count; i++) { + add_srb(rnti, srb2add_list->list.array[i]); + } + } + + if (drb2add_list != NULL) { + for (i = 0; i < drb2add_list->list.count; i++) { + LOG_I(PDCP, "Before calling add_drb \n"); + add_drb(rnti, drb2add_list->list.array[i], rlc_bearer2add_list->list.array[i]->rlc_Config); + } + } + + /* update security */ + if (kRRCint != NULL) { + /* todo */ + } + + free(kRRCenc); + free(kRRCint); + free(kUPenc); + + return 0; +} + +/* Dummy function due to dependency from LTE libraries */ +boolean_t rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + LTE_SRB_ToAddModList_t *const srb2add_list, + LTE_DRB_ToAddModList_t *const drb2add_list, + LTE_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 +#endif + ,rb_id_t *const defaultDRB) +{ + return 0; +} + +void nr_DRB_preconfiguration(void) +{ + + NR_RadioBearerConfig_t *rbconfig = NULL; + struct NR_CellGroupConfig__rlc_BearerToAddModList *Rlc_Bearer_ToAdd_list = NULL; + protocol_ctxt_t ctxt; + //fill_default_rbconfig(rb_config, 5, 1); + rbconfig = calloc(1, sizeof(*rbconfig)); + + rbconfig->srb_ToAddModList = NULL; + rbconfig->srb3_ToRelease = NULL; + rbconfig->drb_ToAddModList = calloc(1,sizeof(*rbconfig->drb_ToAddModList)); + NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); + drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); + drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; + drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5; + drb_ToAddMod->drb_Identity = 1; + drb_ToAddMod->reestablishPDCP = NULL; + drb_ToAddMod->recoverPDCP = NULL; + drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); + drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); + drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30; + drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); + *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; + drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); + *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len12bits; + drb_ToAddMod->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drb_ToAddMod->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + + drb_ToAddMod->pdcp_Config->drb->integrityProtection=NULL; + drb_ToAddMod->pdcp_Config->drb->statusReportRequired=NULL; + drb_ToAddMod->pdcp_Config->drb->outOfOrderDelivery=NULL; + drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL; + + drb_ToAddMod->pdcp_Config->t_Reordering = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->t_Reordering)); + *drb_ToAddMod->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + drb_ToAddMod->pdcp_Config->ext1 = NULL; + + ASN_SEQUENCE_ADD(&rbconfig->drb_ToAddModList->list,drb_ToAddMod); + + rbconfig->drb_ToReleaseList = NULL; + + rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig)); + rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig)); + rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL; + rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse)); + *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; + + xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); + + + NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); + + RLC_BearerConfig->logicalChannelIdentity = 4; + RLC_BearerConfig->servedRadioBearer = calloc(1,sizeof(*RLC_BearerConfig->servedRadioBearer)); + RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; + + RLC_BearerConfig->servedRadioBearer->choice.drb_Identity=1; + RLC_BearerConfig->reestablishRLC=calloc(1,sizeof(*RLC_BearerConfig->reestablishRLC)); + *RLC_BearerConfig->reestablishRLC=NR_RLC_BearerConfig__reestablishRLC_true; + RLC_BearerConfig->rlc_Config=calloc(1,sizeof(*RLC_BearerConfig->rlc_Config)); + + // RLC UM Bi-directional Bearer configuration + RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_um_Bi_Directional; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional)); + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + + // RLC AM Bearer configuration + /*RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; + RLC_BearerConfig->rlc_Config->choice.am = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am)); + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500; + RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32; + + RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15;*/ + + RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters)); + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedServingCells = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedSCS_List = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->maxPUSCH_Duration = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->configuredGrantType1Allowed = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup)); + *RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = NULL; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false; + RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL; + + Rlc_Bearer_ToAdd_list = calloc(1,sizeof(*Rlc_Bearer_ToAdd_list)); + ASN_SEQUENCE_ADD(&Rlc_Bearer_ToAdd_list->list, RLC_BearerConfig); + + if (ENB_NAS_USE_TUN){ + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, 0x1234, 0, 0,0); + } + else{ + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0); + } + + nr_rrc_pdcp_config_asn1_req( + &ctxt, + (NR_SRB_ToAddModList_t *) NULL, + rbconfig->drb_ToAddModList , + rbconfig->drb_ToReleaseList, + 0xff, + NULL, + NULL, + NULL, + NULL, + NULL, + Rlc_Bearer_ToAdd_list); + + nr_rrc_rlc_config_asn1_req (&ctxt, + (NR_SRB_ToAddModList_t *) NULL, + rbconfig->drb_ToAddModList, + rbconfig->drb_ToReleaseList, + (LTE_PMCH_InfoList_r9_t *) NULL, + Rlc_Bearer_ToAdd_list); +} + +uint64_t get_pdcp_optmask(void) +{ + return pdcp_optmask; +} + +boolean_t pdcp_remove_UE( + const protocol_ctxt_t *const ctxt_pP) +{ + TODO; + return 1; +} + +void pdcp_config_set_security(const protocol_ctxt_t* const ctxt_pP, pdcp_t *pdcp_pP, rb_id_t rb_id, + uint16_t lc_idP, uint8_t security_modeP, uint8_t *kRRCenc_pP, uint8_t *kRRCint_pP, uint8_t *kUPenc_pP) +{ + TODO; +} + +static boolean_t pdcp_data_req_drb( + protocol_ctxt_t *ctxt_pP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer) +{ +printf("pdcp_data_req called size %d\n", sdu_buffer_size); + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + int rnti = ctxt_pP->rnti; + + if (ctxt_pP->module_id != 0 || + //ctxt_pP->enb_flag != 1 || + ctxt_pP->instance != 0 || + ctxt_pP->eNB_index != 0 /*|| + ctxt_pP->configured != 1 || + ctxt_pP->brOption != 0*/) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, rnti); + + if (rb_id < 1 || rb_id > 5) + rb = NULL; + else + rb = ue->drb[rb_id - 1]; + + if (rb == NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal: no DRB found (rnti %d, rb_id %ld)\n", + __FILE__, __LINE__, __FUNCTION__, rnti, rb_id); + exit(1); + } + + rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP); + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + return 1; +} + +boolean_t pdcp_data_req( + protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + ,const uint32_t *const sourceL2Id + ,const uint32_t *const destinationL2Id +#endif + ) +{ + if (srb_flagP) { TODO; } + return pdcp_data_req_drb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size, + sdu_buffer); +} + +void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind) +{ + /* nothing to do */ +} + +void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req) +{ + /* nothing to do */ +} + +//Dummy function needed due to LTE dependencies +void +pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){ + /* nothing to do */ +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c new file mode 100644 index 0000000000..ca51da3d5f --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -0,0 +1,198 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_ue_manager.h" + +#include +#include +#include + +#include "LOG/log.h" + +typedef struct { + pthread_mutex_t lock; + nr_pdcp_ue_t **ue_list; + int ue_count; + int enb_flag; +} nr_pdcp_ue_manager_internal_t; + +nr_pdcp_ue_manager_t *new_nr_pdcp_ue_manager(int enb_flag) +{ + nr_pdcp_ue_manager_internal_t *ret; + + ret = calloc(1, sizeof(nr_pdcp_ue_manager_internal_t)); + if (ret == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (pthread_mutex_init(&ret->lock, NULL)) abort(); + ret->enb_flag = enb_flag; + + return ret; +} + +int nr_pdcp_manager_get_enb_flag(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->enb_flag; +} + +void nr_pdcp_manager_lock(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (pthread_mutex_lock(&m->lock)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (pthread_mutex_unlock(&m->lock)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *_m, int rnti) +{ + /* TODO: optimze */ + nr_pdcp_ue_manager_internal_t *m = _m; + int i; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + return m->ue_list[i]; + + LOG_D(PDCP, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti); + + m->ue_count++; + m->ue_list = realloc(m->ue_list, sizeof(nr_pdcp_ue_t *) * m->ue_count); + if (m->ue_list == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + m->ue_list[m->ue_count-1] = calloc(1, sizeof(nr_pdcp_ue_t)); + if (m->ue_list[m->ue_count-1] == NULL) { + LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + m->ue_list[m->ue_count-1]->rnti = rnti; + + return m->ue_list[m->ue_count-1]; +} + +/* must be called with lock acquired */ +void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *_m, int rnti) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + nr_pdcp_ue_t *ue; + int i; + int j; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + break; + + if (i == m->ue_count) { + LOG_D(PDCP, "%s:%d:%s: warning: ue %d not found\n", + __FILE__, __LINE__, __FUNCTION__, + rnti); + return; + } + + ue = m->ue_list[i]; + + for (j = 0; j < 2; j++) + if (ue->srb[j] != NULL) + ue->srb[j]->delete(ue->srb[j]); + + for (j = 0; j < 5; j++) + if (ue->drb[j] != NULL) + ue->drb[j]->delete(ue->drb[j]); + + free(ue); + + m->ue_count--; + if (m->ue_count == 0) { + free(m->ue_list); + m->ue_list = NULL; + return; + } + + memmove(&m->ue_list[i], &m->ue_list[i+1], + (m->ue_count - i) * sizeof(nr_pdcp_ue_t *)); + m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(nr_pdcp_ue_t *)); + if (m->ue_list == NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, nr_pdcp_entity_t *entity) +{ + if (srb_id < 1 || srb_id > 2) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + srb_id--; + + if (ue->srb[srb_id] != NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal, srb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->srb[srb_id] = entity; +} + +/* must be called with lock acquired */ +void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity_t *entity) +{ + if (drb_id < 1 || drb_id > 5) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + drb_id--; + + if (ue->drb[drb_id] != NULL) { + LOG_E(PDCP, "%s:%d:%s: fatal, drb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->drb[drb_id] = entity; +} + +int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + if (m->ue_count == 0) + return -1; + return m->ue_list[0]->rnti; +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h new file mode 100644 index 0000000000..0de2f024b3 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_PDCP_UE_MANAGER_H_ +#define _NR_PDCP_UE_MANAGER_H_ + +#include "nr_pdcp_entity.h" + +typedef void nr_pdcp_ue_manager_t; + +typedef struct nr_pdcp_ue_t { + int rnti; + nr_pdcp_entity_t *srb[2]; + nr_pdcp_entity_t *drb[5]; +} nr_pdcp_ue_t; + +/***********************************************************************/ +/* manager functions */ +/***********************************************************************/ + +nr_pdcp_ue_manager_t *new_nr_pdcp_ue_manager(int enb_flag); + +int nr_pdcp_manager_get_enb_flag(nr_pdcp_ue_manager_t *m); + +void nr_pdcp_manager_lock(nr_pdcp_ue_manager_t *m); +void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m); + +nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti); +void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti); + +/***********************************************************************/ +/* ue functions */ +/***********************************************************************/ + +void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, + nr_pdcp_entity_t *entity); +void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, + nr_pdcp_entity_t *entity); + +/***********************************************************************/ +/* hacks */ +/***********************************************************************/ + +/* returns -1 if no UE */ +int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *m); + +#endif /* _NR_PDCP_UE_MANAGER_H_ */ diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.c b/openair2/LAYER2/nr_rlc/asn1_utils.c index 46f7d90da5..43d55af1ac 100644 --- a/openair2/LAYER2/nr_rlc/asn1_utils.c +++ b/openair2/LAYER2/nr_rlc/asn1_utils.c @@ -21,14 +21,14 @@ #include "rlc.h" -int decode_t_reordering(int v) +int decode_t_reassembly(int v) { - static int tab[32] = { - 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, - 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 1600 + static int tab[31] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, + 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200 }; - if (v < 0 || v > 31) { + if (v < 0 || v > 30) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -72,11 +72,13 @@ int decode_t_poll_retransmit(int v) int decode_poll_pdu(int v) { - static int tab[8] = { - 4, 8, 16, 32, 64, 128, 256, -1 /* -1 means infinity */ + static int tab[24] = { + 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 6144, 8192, 12288, + 16384, 20480, 24576, 28672, 32768, 40960, 49152, 57344, 65536 + -1 /* -1 means infinity */ }; - if (v < 0 || v > 7) { + if (v < 0 || v > 23) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -86,12 +88,23 @@ int decode_poll_pdu(int v) int decode_poll_byte(int v) { - static int tab[15] = { - 25, 50, 75, 100, 125, 250, 375, 500, 750, 1000, 1250, 1500, 2000, 3000, + static int tab[44] = { + /* KB */ + 1024 * 1, 1024 * 2, 1024 * 5, 1024 * 8, 1024 * 10, + 1024 * 15, 1024 * 25, 1024 * 50, 1024 * 75, 1024 * 100, + 1024 * 125, 1024 * 250, 1024 * 375, 1024 * 500, 1024 * 750, + 1024 * 1000, 1024 * 1250, 1024 * 1500, 1024 * 2000, 1024 * 3000, + 1024 * 4000, 1024 * 4500, 1024 * 5000, 1024 * 5500, 1024 * 6000, + 1024 * 6500, 1024 * 7000, 1024 * 7500, + /* MB */ + 1024 * 1024 * 8, 1024 * 1024 * 9, 1024 * 1024 * 10, 1024 * 1024 * 11, + 1024 * 1024 * 12, 1024 * 1024 * 13, 1024 * 1024 * 14, 1024 * 1024 * 15, + 1024 * 1024 * 16, 1024 * 1024 * 17, 1024 * 1024 * 18, 1024 * 1024 * 20, + 1024 * 1024 * 25, 1024 * 1024 * 30, 1024 * 1024 * 40, -1 /* -1 means infinity */ }; - if (v < 0 || v > 14) { + if (v < 0 || v > 43) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } @@ -114,10 +127,24 @@ int decode_max_retx_threshold(int v) return tab[v]; } -int decode_sn_field_length(int v) +int decode_sn_field_length_um(int v) { static int tab[2] = { - 5, 10 + 6, 12 + }; + + if (v < 0 || v > 1) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_sn_field_length_am(int v) +{ + static int tab[2] = { + 12, 18 }; if (v < 0 || v > 1) { diff --git a/openair2/LAYER2/nr_rlc/asn1_utils.h b/openair2/LAYER2/nr_rlc/asn1_utils.h index 61394c9c69..6f010b02da 100644 --- a/openair2/LAYER2/nr_rlc/asn1_utils.h +++ b/openair2/LAYER2/nr_rlc/asn1_utils.h @@ -19,15 +19,16 @@ * contact@openairinterface.org */ -#ifndef _ASN1_UTILS_H_ -#define _ASN1_UTILS_H_ +#ifndef _OPENAIR2_LAYER2_NR_RLC_ASN1_UTILS_H_ +#define _OPENAIR2_LAYER2_NR_RLC_ASN1_UTILS_H_ -int decode_t_reordering(int v); +int decode_t_reassembly(int v); int decode_t_status_prohibit(int v); int decode_t_poll_retransmit(int v); int decode_poll_pdu(int v); int decode_poll_byte(int v); int decode_max_retx_threshold(int v); -int decode_sn_field_length(int v); +int decode_sn_field_length_um(int v); +int decode_sn_field_length_am(int v); -#endif /* _ASN1_UTILS_H_ */ +#endif /* _OPENAIR2_LAYER2_NR_RLC_ASN1_UTILS_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 8f3d49d8c2..78a49e4604 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -109,7 +109,8 @@ static void consider_retransmission(nr_rlc_entity_am_t *entity, * upper layers should deal with this condition, internally it's better * for the RLC code to keep going with this segment (we only remove * a segment that was ACKed) - */ + */ + LOG_D(RLC, "RLC segment to be added at the ReTx list \n"); nr_rlc_sdu_segment_list_append(&entity->retransmit_list, &entity->retransmit_end, cur); @@ -1588,6 +1589,8 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, sdu = nr_rlc_new_sdu(buffer, size, sdu_id); + LOG_D(RLC, "Created new RLC SDU and append it to the RLC list \n"); + nr_rlc_sdu_segment_list_append(&entity->tx_list, &entity->tx_end, sdu); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index bbc4acbd56..5048dd245e 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -27,19 +27,23 @@ #include "asn1_utils.h" #include "nr_rlc_ue_manager.h" #include "nr_rlc_entity.h" +#include "NR_RLC-BearerConfig.h" +#include "NR_DRB-ToAddMod.h" +#include "NR_DRB-ToAddModList.h" +#include "NR_SRB-ToAddModList.h" +#include "NR_DRB-ToReleaseList.h" +#include "NR_CellGroupConfig.h" +#include "NR_RLC-Config.h" #include static nr_rlc_ue_manager_t *nr_rlc_ue_manager; /* TODO: handle time a bit more properly */ -//#if 0 static uint64_t nr_rlc_current_time; static int nr_rlc_current_time_last_frame; static int nr_rlc_current_time_last_subframe; -//#endif -//#if 0 void mac_rlc_data_ind ( const module_id_t module_idP, const rnti_t rntiP, @@ -154,14 +158,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( mac_rlc_status_resp_t ret; nr_rlc_entity_t *rb; - /* TODO: handle time a bit more properly */ - if (nr_rlc_current_time_last_frame != frameP || - nr_rlc_current_time_last_subframe != subframeP) { - nr_rlc_current_time++; - nr_rlc_current_time_last_frame = frameP; - nr_rlc_current_time_last_subframe = subframeP; - } - nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rntiP); @@ -195,7 +191,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( ret.head_sdu_is_segmented = 0; return ret; } -//#endif rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( const module_id_t module_idP, @@ -254,7 +249,6 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( int oai_emulation; -//#if 0 rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const MBMS_flag_t MBMS_flagP, @@ -306,9 +300,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, return RLC_OP_STATUS_OK; } -//#endif -//#if 0 int rlc_module_init(int enb_flag) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; @@ -329,13 +321,10 @@ int rlc_module_init(int enb_flag) return 0; } -//#endif -//#if 0 void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP) { } -//#endif static void deliver_sdu(void *_ue, nr_rlc_entity_t *entity, char *buf, int size) { @@ -522,7 +511,7 @@ rb_found: #endif } -__attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) +static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) { nr_rlc_entity_t *nr_rlc_am; nr_rlc_ue_t *ue; @@ -532,7 +521,6 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * int srb_id = s->srb_Identity; int logical_channel_group; - //int t_reordering; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -575,7 +563,6 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * exit(1); } am = &r->choice.explicitValue.choice.am; - //t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); @@ -585,7 +572,6 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * } case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue: /* default values from 36.331 9.2.1 */ - //t_reordering = 35; t_status_prohibit = 0; t_poll_retransmit = 45; poll_pdu = -1; @@ -628,18 +614,17 @@ __attribute__ ((unused)) static void add_srb(int rnti, struct LTE_SRB_ToAddMod * nr_rlc_manager_unlock(nr_rlc_ue_manager); } -static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) { nr_rlc_entity_t *nr_rlc_am; nr_rlc_ue_t *ue; - struct LTE_RLC_Config *r = s->rlc_Config; - struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; int drb_id = s->drb_Identity; - int channel_id = *s->logicalChannelIdentity; + int channel_id = rlc_BearerConfig->logicalChannelIdentity; int logical_channel_group; - //int t_reordering; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -669,15 +654,20 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) } switch (r->present) { - case LTE_RLC_Config_PR_am: { - struct LTE_RLC_Config__am *am; - am = &r->choice.am; - //t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + case NR_RLC_Config_PR_am: { + struct NR_RLC_Config__am *am; + am = r->choice.am; + t_reassembly = decode_t_reassembly(am->dl_AM_RLC.t_Reassembly); t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte); max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold); + if (*am->dl_AM_RLC.sn_FieldLength != *am->ul_AM_RLC.sn_FieldLength) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + sn_field_length = decode_sn_field_length_am(*am->dl_AM_RLC.sn_FieldLength); break; } default: @@ -691,14 +681,6 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - /* hack: hardcode values for NR */ - t_poll_retransmit = 45; - t_reassembly = 35; - t_status_prohibit = 0; - poll_pdu = -1; - poll_byte = -1; - max_retx_threshold = 8; - sn_field_length = 12; nr_rlc_am = new_nr_rlc_entity_am(100000, 100000, deliver_sdu, ue, @@ -716,18 +698,17 @@ static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) nr_rlc_manager_unlock(nr_rlc_ue_manager); } -static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_t *rlc_BearerConfig) { nr_rlc_entity_t *nr_rlc_um; nr_rlc_ue_t *ue; - struct LTE_RLC_Config *r = s->rlc_Config; - struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + struct NR_LogicalChannelConfig *l = rlc_BearerConfig->mac_LogicalChannelConfig; int drb_id = s->drb_Identity; - int channel_id = *s->logicalChannelIdentity; + int channel_id = rlc_BearerConfig->logicalChannelIdentity; int logical_channel_group; - //int t_reordering; int sn_field_length; int t_reassembly; @@ -752,15 +733,15 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) } switch (r->present) { - case LTE_RLC_Config_PR_um_Bi_Directional: { - struct LTE_RLC_Config__um_Bi_Directional *um; - um = &r->choice.um_Bi_Directional; - //t_reordering = decode_t_reordering(um->dl_UM_RLC.t_Reordering); - if (um->dl_UM_RLC.sn_FieldLength != um->ul_UM_RLC.sn_FieldLength) { + case NR_RLC_Config_PR_um_Bi_Directional: { + struct NR_RLC_Config__um_Bi_Directional *um; + um = r->choice.um_Bi_Directional; + t_reassembly = decode_t_reassembly(um->dl_UM_RLC.t_Reassembly); + if (*um->dl_UM_RLC.sn_FieldLength != *um->ul_UM_RLC.sn_FieldLength) { LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - sn_field_length = decode_sn_field_length(um->dl_UM_RLC.sn_FieldLength); + sn_field_length = decode_sn_field_length_um(*um->dl_UM_RLC.sn_FieldLength); break; } default: @@ -774,9 +755,6 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - /* hack: hardcode values for NR */ - t_reassembly = 35; - sn_field_length = 6; nr_rlc_um = new_nr_rlc_entity_um(1000000, 1000000, deliver_sdu, ue, @@ -790,14 +768,14 @@ static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) nr_rlc_manager_unlock(nr_rlc_ue_manager); } -__attribute__ ((unused)) static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s) +static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, struct NR_RLC_BearerConfig *rlc_BearerConfig) { - switch (s->rlc_Config->present) { - case LTE_RLC_Config_PR_am: - add_drb_am(rnti, s); + switch (rlc_BearerConfig->rlc_Config->present) { + case NR_RLC_Config_PR_am: + add_drb_am(rnti, s, rlc_BearerConfig); break; - case LTE_RLC_Config_PR_um_Bi_Directional: - add_drb_um(rnti, s); + case NR_RLC_Config_PR_um_Bi_Directional: + add_drb_um(rnti, s, rlc_BearerConfig); break; default: LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n", @@ -806,7 +784,7 @@ __attribute__ ((unused)) static void add_drb(int rnti, struct LTE_DRB_ToAddMod * } } -//#if 0 +/* Dummy function due to dependency from LTE libraries */ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, const LTE_SRB_ToAddModList_t * const srb2add_listP, const LTE_DRB_ToAddModList_t * const drb2add_listP, @@ -814,6 +792,16 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, const uint32_t sourceL2Id, const uint32_t destinationL2Id) +{ + return 0; +} + +rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const LTE_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) { int rnti = ctxt_pP->rnti; int i; @@ -845,15 +833,13 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP if (drb2add_listP != NULL) { for (i = 0; i < drb2add_listP->list.count; i++) { - add_drb(rnti, drb2add_listP->list.array[i]); + add_drb(rnti, drb2add_listP->list.array[i], rlc_bearer2add_list->list.array[i]); } } return RLC_OP_STATUS_OK; } -//#endif -//#if 0 rlc_op_status_t rrc_rlc_config_req ( const protocol_ctxt_t* const ctxt_pP, const srb_flag_t srb_flagP, @@ -912,16 +898,12 @@ rlc_op_status_t rrc_rlc_config_req ( nr_rlc_manager_unlock(nr_rlc_ue_manager); return RLC_OP_STATUS_OK; } -//#endif -//#if 0 void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP) { /* nothing to do */ } -//#endif -//#if 0 rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) { LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, x->rnti); @@ -931,4 +913,10 @@ rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) return RLC_OP_STATUS_OK; } -//#endif + +void nr_rlc_tick(int frame, int subframe) +{ + if (frame != nr_rlc_current_time_last_frame || + subframe != nr_rlc_current_time_last_subframe) + nr_rlc_current_time++; +} diff --git a/openair2/LAYER2/nr_rlc/tests/LOG/log.h b/openair2/LAYER2/nr_rlc/tests/LOG/log.h index 5c9fcd643c..8ebc7e1909 100644 --- a/openair2/LAYER2/nr_rlc/tests/LOG/log.h +++ b/openair2/LAYER2/nr_rlc/tests/LOG/log.h @@ -1,5 +1,5 @@ -#ifndef _LOG_H_ -#define _LOG_H_ +#ifndef _NR_RLC_TESTS_LOG_H_ +#define _NR_RLC_TESTS_LOG_H_ #include @@ -7,4 +7,4 @@ #define LOG_D(x, ...) printf(__VA_ARGS__) #define LOG_W(x, ...) printf(__VA_ARGS__) -#endif /* _LOG_H_ */ +#endif /* _NR_RLC_TESTS_LOG_H_ */ diff --git a/openair2/LAYER2/rlc_v2/asn1_utils.h b/openair2/LAYER2/rlc_v2/asn1_utils.h index 61394c9c69..fadaf16f0a 100644 --- a/openair2/LAYER2/rlc_v2/asn1_utils.h +++ b/openair2/LAYER2/rlc_v2/asn1_utils.h @@ -19,8 +19,8 @@ * contact@openairinterface.org */ -#ifndef _ASN1_UTILS_H_ -#define _ASN1_UTILS_H_ +#ifndef _OPENAIR2_LAYER2_RLC_V2_ASN1_UTILS_H_ +#define _OPENAIR2_LAYER2_RLC_V2_ASN1_UTILS_H_ int decode_t_reordering(int v); int decode_t_status_prohibit(int v); @@ -30,4 +30,4 @@ int decode_poll_byte(int v); int decode_max_retx_threshold(int v); int decode_sn_field_length(int v); -#endif /* _ASN1_UTILS_H_ */ +#endif /* _OPENAIR2_LAYER2_RLC_V2_ASN1_UTILS_H_ */ diff --git a/openair2/LAYER2/rlc_v2/tests/LOG/log.h b/openair2/LAYER2/rlc_v2/tests/LOG/log.h index 5c9fcd643c..89d85090b1 100644 --- a/openair2/LAYER2/rlc_v2/tests/LOG/log.h +++ b/openair2/LAYER2/rlc_v2/tests/LOG/log.h @@ -1,5 +1,5 @@ -#ifndef _LOG_H_ -#define _LOG_H_ +#ifndef _RLC_V2_TESTS_LOG_H_ +#define _RLC_V2_TESTS_LOG_H_ #include @@ -7,4 +7,4 @@ #define LOG_D(x, ...) printf(__VA_ARGS__) #define LOG_W(x, ...) printf(__VA_ARGS__) -#endif /* _LOG_H_ */ +#endif /* _RLC_V2_TESTS_LOG_H_ */ diff --git a/openair2/M2AP/m2ap_MCE_interface_management.c b/openair2/M2AP/m2ap_MCE_interface_management.c index 1bef834179..e162c9a5de 100644 --- a/openair2/M2AP/m2ap_MCE_interface_management.c +++ b/openair2/M2AP/m2ap_MCE_interface_management.c @@ -521,6 +521,7 @@ int MCE_send_MBMS_SCHEDULING_INFORMATION(instance_t instance, /*uint32_t assoc_i mbsfn_subframe_configuration->radioframeAllocationPeriod = m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_period; mbsfn_subframe_configuration->radioframeAllocationOffset = m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_offset; if(m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].is_four_sf){ + LOG_I(M2AP,"is_four_sf\n"); mbsfn_subframe_configuration->subframeAllocation.present = M2AP_MBSFN_Subframe_Configuration__subframeAllocation_PR_fourFrames; mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf = MALLOC(3); mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation) & 0xFF); @@ -530,6 +531,7 @@ int MCE_send_MBMS_SCHEDULING_INFORMATION(instance_t instance, /*uint32_t assoc_i mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.bits_unused = 0; }else{ + LOG_I(M2AP,"is_one_sf\n"); mbsfn_subframe_configuration->subframeAllocation.present = M2AP_MBSFN_Subframe_Configuration__subframeAllocation_PR_oneFrame; mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.buf = MALLOC(1); mbsfn_subframe_configuration->subframeAllocation.choice.oneFrame.size = 1; @@ -1357,11 +1359,10 @@ int MCE_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, -int MCE_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - M2AP_M2AP_PDU_t *pdu){ +int MCE_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,module_id_t du_mod_idP){ + AssertFatal(1==0,"Not implemented yet\n"); + } /* @@ -1378,16 +1379,138 @@ int MCE_handle_MBMS_SERVICE_COUNTING_RESPONSE(instance_t instance, uint32_t assoc_id, uint32_t stream, M2AP_M2AP_PDU_t *pdu){ - AssertFatal(1==0,"Not implemented yet\n"); + //int i; + //AssertFatal(1==0,"Not implemented yet\n"); + LOG_D(M2AP, "MCE_handle_MBMS_SERVICE_COUNTING_RESPONSE\n"); + + AssertFatal(pdu->present == M2AP_M2AP_PDU_PR_successfulOutcome, + "pdu->present != M2AP_M2AP_PDU_PR_successfulOutcome\n"); + AssertFatal(pdu->choice.successfulOutcome.procedureCode == M2AP_ProcedureCode_id_mbmsServiceCounting, + "pdu->choice.successfulOutcome->procedureCode != M2AP_ProcedureCode_id_mbmsServiceCounting\n"); + AssertFatal(pdu->choice.successfulOutcome.criticality == M2AP_Criticality_reject, + "pdu->choice.successfulOutcome->criticality != M2AP_Criticality_reject\n"); + AssertFatal(pdu->choice.successfulOutcome.value.present == M2AP_SuccessfulOutcome__value_PR_MbmsServiceCountingResponse, + "pdu->choice.successfulOutcome.value.present != M2AP_SuccessfulOutcome__value_PR_MbmsServiceCountingResponse\n"); + + + M2AP_MbmsServiceCountingResponse_t *in = &pdu->choice.successfulOutcome.value.choice.MbmsServiceCountingResponse; + //M2AP_MbmsServiceCountingResponse_Ies_t *ie; + //int MCE_MBMS_M2AP_ID=-1; + //int ENB_MBMS_M2AP_ID=-1; + + + MessageDef *msg_g = itti_alloc_new_message(TASK_M2AP_MCE,M2AP_MBMS_SERVICE_COUNTING_RESP); //TODO + + LOG_D(M2AP, "M2AP: MbmsServiceCounting-Resp: protocolIEs.list.count %d\n", + in->protocolIEs.list.count); + for (int i=0;i < in->protocolIEs.list.count; i++) { + //ie = in->protocolIEs.list.array[i]; + // switch (ie->id) { + // case M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID: + // AssertFatal(ie->criticality == M2AP_Criticality_reject, + // "ie->criticality != M2AP_Criticality_reject\n"); + // AssertFatal(ie->value.present == M2AP_SessionStartResponse_Ies__value_PR_MCE_MBMS_M2AP_ID, + // "ie->value.present != M2AP_sessionStartResponse_IEs__value_PR_MCE_MBMS_M2AP_ID\n"); + // MCE_MBMS_M2AP_ID=ie->value.choice.MCE_MBMS_M2AP_ID; + // LOG_D(M2AP, "M2AP: SessionStart-Resp: MCE_MBMS_M2AP_ID %d\n", + // MCE_MBMS_M2AP_ID); + // break; + // case M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID: + // AssertFatal(ie->criticality == M2AP_Criticality_reject, + // "ie->criticality != M2AP_Criticality_reject\n"); + // AssertFatal(ie->value.present == M2AP_SessionStartResponse_Ies__value_PR_ENB_MBMS_M2AP_ID, + // "ie->value.present != M2AP_sessionStartResponse_Ies__value_PR_ENB_MBMS_M2AP_ID\n"); + // ENB_MBMS_M2AP_ID=ie->value.choice.ENB_MBMS_M2AP_ID; + // LOG_D(M2AP, "M2AP: SessionStart-Resp: ENB_MBMS_M2AP_ID %d\n", + // ENB_MBMS_M2AP_ID); + // break; + // } + } + + //AssertFatal(MCE_MBMS_M2AP_ID!=-1,"MCE_MBMS_M2AP_ID was not sent\n"); + //AssertFatal(ENB_MBMS_M2AP_ID!=-1,"ENB_MBMS_M2AP_ID was not sent\n"); + //M2AP_SESSION_START_RESP(msg_p). +// MSC_LOG_RX_MESSAGE( +// MSC_M2AP_MCE, +// MSC_M2AP_ENB, + //return 0; +// 0, +// 0, +// MSC_AS_TIME_FMT" MCE_handle_M2_SESSION_START_RESPONSE successfulOutcome assoc_id %d", +// 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), +// assoc_id); +// + //LOG_D(M2AP, "Sending ITTI message to ENB_APP with assoc_id (%d->%d)\n", + //assoc_id,ENB_MODULE_ID_TO_INSTANCE(assoc_id)); + + itti_send_msg_to_task(TASK_MCE_APP, ENB_MODULE_ID_TO_INSTANCE(assoc_id), msg_g); + return 0; + } -int MCE_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - M2AP_M2AP_PDU_t *pdu){ - AssertFatal(1==0,"Not implemented yet\n"); +int MCE_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance, module_id_t du_mod_idP){ + + M2AP_M2AP_PDU_t pdu; + M2AP_MbmsServiceCountingRequest_t *out; + M2AP_MbmsServiceCountingRequest_Ies_t *ie; + + uint8_t *buffer; + uint32_t len; + //int i=0; + //int j=0; + + /* Create */ + /* 0. pdu Type */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage; + //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t)); + pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_mbmsServiceCounting; + pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_MbmsServiceCountingRequest; + out = &pdu.choice.initiatingMessage.value.choice.MbmsServiceCountingRequest; + + /* mandatory */ + /* c1. MCCH_Update_Time */ //long + ie=(M2AP_MbmsServiceCountingRequest_Ies_t *)calloc(1,sizeof(M2AP_MbmsSchedulingInformation_Ies_t)); + ie->id = M2AP_ProtocolIE_ID_id_MCCH_Update_Time; + ie->criticality = M2AP_Criticality_reject; + ie->value.present = M2AP_MbmsServiceCountingRequest_Ies__value_PR_MCCH_Update_Time; + //ie->value.choice.MCCH_Update_Time = ; + //ie->value.choice.MCCH_Update_Time = m2ap_mbms_scheduling_information->mcch_update_time; + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + /* mandatory */ + /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long + ie = (M2AP_MbmsServiceCountingRequest_Ies_t *)calloc(1, sizeof(M2AP_MbmsServiceCountingRequest_Ies_t)); + ie->id = M2AP_ProtocolIE_ID_id_MBSFN_Area_ID; + ie->criticality = M2AP_Criticality_reject; + ie->value.present = M2AP_MbmsServiceCountingRequest_Ies__value_PR_MBSFN_Area_ID; + //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //? + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + /* c2. TMGI (integrer value) */ + ie = (M2AP_MbmsServiceCountingRequest_Ies_t *)calloc(1, sizeof(M2AP_MbmsServiceCountingRequest_Ies_t )); + ie->id = M2AP_ProtocolIE_ID_id_MBMS_Counting_Request_Session; + ie->criticality = M2AP_Criticality_reject; + ie->value.present = M2AP_MbmsServiceCountingRequest_Ies__value_PR_MBMS_Counting_Request_Session; + + //M2AP_MBMS_Counting_Request_Session_t * m2ap_mbms_counting_request_session = &ie->value.choice.MBMS_Counting_Request_Session; + + //&ie->choice.TMGI.pLMN_Identity); + //INT16_TO_OCTET_STRING(0,&ie->choice.TMGI.serviceId); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(M2AP, "Failed to encode MBMS Service Counting Results Report\n"); + return -1; + } + + return 0; } diff --git a/openair2/M2AP/m2ap_MCE_interface_management.h b/openair2/M2AP/m2ap_MCE_interface_management.h index 6b899e9ea2..2b1d5824af 100644 --- a/openair2/M2AP/m2ap_MCE_interface_management.h +++ b/openair2/M2AP/m2ap_MCE_interface_management.h @@ -150,10 +150,7 @@ int MCE_handle_MBMS_SESSION_UPDATE_RESPONSE(instance_t instance, uint32_t stream, M2AP_M2AP_PDU_t *pdu); -int MCE_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - M2AP_M2AP_PDU_t *pdu); +int MCE_handle_MBMS_SESSION_UPDATE_FAILURE(instance_t instance,module_id_t du_mod_idP); /* * Service Counting Request @@ -165,10 +162,7 @@ int MCE_handle_MBMS_SERVICE_COUNTING_RESPONSE(instance_t instance, uint32_t stream, M2AP_M2AP_PDU_t *pdu); -int MCE_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - M2AP_M2AP_PDU_t *pdu); +int MCE_handle_MBMS_SESSION_COUNTING_FAILURE(instance_t instance, module_id_t du_mod_idP); /* * Service Counting Results Report */ diff --git a/openair2/M2AP/m2ap_eNB.c b/openair2/M2AP/m2ap_eNB.c index 206b7cf8ca..39c769a43d 100644 --- a/openair2/M2AP/m2ap_eNB.c +++ b/openair2/M2AP/m2ap_eNB.c @@ -142,6 +142,22 @@ void m2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa sctp_new_association_resp->ulp_cnx_id); //m2ap_handle_m2_setup_message(instance_p, m2ap_enb_data_p, // sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); + + sleep(4); + int index; + /* Trying to connect to the provided list of eNB ip address */ + for (index = 0; index < instance_p->nb_m2; index++) { + //M2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n", + // instance_id, instance->eNB_id); + m2ap_eNB_register_eNB(instance_p, + &instance_p->target_mce_m2_ip_address[index], + &instance_p->enb_m2_ip_address, + instance_p->sctp_in_streams, + instance_p->sctp_out_streams, + instance_p->enb_port_for_M2C, + instance_p->multi_sd); + } + return; } @@ -304,6 +320,8 @@ void m2ap_eNB_handle_register_eNB(instance_t instance, DevCheck(new_instance->mcc == m2ap_register_eNB->mcc, new_instance->mcc, m2ap_register_eNB->mcc, 0); DevCheck(new_instance->mnc == m2ap_register_eNB->mnc, new_instance->mnc, m2ap_register_eNB->mnc, 0); M2AP_WARN("eNB[%d] already registered\n", instance); + + } else { new_instance = calloc(1, sizeof(m2ap_eNB_instance_t)); DevAssert(new_instance != NULL); diff --git a/openair2/M2AP/m2ap_eNB_interface_management.c b/openair2/M2AP/m2ap_eNB_interface_management.c index 95b8372025..9649d919c3 100644 --- a/openair2/M2AP/m2ap_eNB_interface_management.c +++ b/openair2/M2AP/m2ap_eNB_interface_management.c @@ -163,8 +163,12 @@ int eNB_handle_MBMS_SCHEDULING_INFORMATION(instance_t instance, M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_period = m2ap_mbsfn_sf_configuration->radioframeAllocationPeriod; M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_offset = m2ap_mbsfn_sf_configuration->radioframeAllocationOffset; if( m2ap_mbsfn_sf_configuration->subframeAllocation.present == M2AP_MBSFN_Subframe_Configuration__subframeAllocation_PR_fourFrames ) { + LOG_I(RRC,"is_four_sf\n"); + M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].is_four_sf = 1; M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation = m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[0] | (m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[1]<<8) | (m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[0]<<16); }else{ + LOG_I(RRC,"is_one_sf\n"); + M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].is_four_sf = 0; M2AP_MBMS_SCHEDULING_INFORMATION(message_p).mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation = (m2ap_mbsfn_sf_configuration->subframeAllocation.choice.oneFrame.buf[0] >> 2) & 0x3F; } } @@ -1262,46 +1266,226 @@ int eNB_handle_MBMS_SERVICE_COUNTING_REQ(instance_t instance, uint32_t stream, M2AP_M2AP_PDU_t *pdu) { - LOG_D(M2AP, "eNB_handle_MBMS_SERVICE_COUNTING_REQUEST assoc_id %d\n",assoc_id); - MessageDef *message_p; + LOG_D(M2AP, "eNB_handle_MBMS_SERVICE_COUNTING_REQUEST assoc_id %d\n",assoc_id); + + //MessageDef *message_p; //M2AP_MbmsServiceCountingRequest_t *container; //M2AP_MbmsServiceCountingRequest_Ies_t *ie; + M2AP_MbmsServiceCountingRequest_t *in; + M2AP_MbmsServiceCountingRequest_Ies_t *ie; //int i = 0; + int j; DevAssert(pdu != NULL); // container = &pdu->choice.initiatingMessage.value.choice.MbmsServiceCountingRequest; + in = &pdu->choice.initiatingMessage.value.choice.MbmsServiceCountingRequest; /* M2 Setup Request == Non UE-related procedure -> stream 0 */ if (stream != 0) { - LOG_D(M2AP, "[SCTP %d] Received MMBS session start request on stream != 0 (%d)\n", + LOG_D(M2AP, "[SCTP %d] Received MMBS service Counting Request on stream != 0 (%d)\n", assoc_id, stream); } - message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SERVICE_COUNTING_REQ); + for (j=0;j < in->protocolIEs.list.count; j++) { + ie = in->protocolIEs.list.array[j]; + switch (ie->id) { + case M2AP_ProtocolIE_ID_id_MCCH_Update_Time: + AssertFatal(ie->criticality == M2AP_Criticality_reject, + "ie->criticality != M2AP_Criticality_reject\n"); + AssertFatal(ie->value.present == M2AP_MbmsServiceCountingRequest_Ies__value_PR_MCCH_Update_Time, + "ie->value.present != M2AP_MbmsServiceCountingRequest_Ies__value_PR_MCCH_Update_Time\n"); + LOG_D(M2AP, "M2AP: : MCCH_Update_Time \n"); + break; + case M2AP_ProtocolIE_ID_id_MBSFN_Area_ID: + AssertFatal(ie->criticality == M2AP_Criticality_reject, + "ie->criticality != M2AP_Criticality_reject\n"); + AssertFatal(ie->value.present == M2AP_MbmsServiceCountingRequest_Ies__value_PR_MBSFN_Area_ID, + "ie->value.present != M2AP_MbmsServiceCountingRequest_Ies__value_PR_MBSFN_Area_ID\n"); + LOG_D(M2AP, "M2AP: : MBSFN_Area_ID \n"); + break; + case M2AP_ProtocolIE_ID_id_MBMS_Counting_Request_Session: + AssertFatal(ie->criticality == M2AP_Criticality_reject, + "ie->criticality != M2AP_Criticality_reject\n"); + AssertFatal(ie->value.present == M2AP_MbmsServiceCountingRequest_Ies__value_PR_MBMS_Counting_Request_Session, + "ie->value.present != M2AP_MbmsServiceCountingRequest_Ies__value_PR_MBMS_Counting_Request_Session\n"); + LOG_D(M2AP, "M2AP: : MBMS_Counting_Request_Session \n"); + + //ie->value.choice.MBMS_Counting_Request_Session.list.count; + + break; + + } + } - itti_send_msg_to_task(TASK_ENB_APP, ENB_MODULE_ID_TO_INSTANCE(instance), message_p); - + //message_p = itti_alloc_new_message (TASK_M2AP_ENB, M2AP_MBMS_SERVICE_COUNTING_REQ); return 0; } int eNB_send_MBMS_SERVICE_COUNTING_REPORT(instance_t instance, m2ap_mbms_service_counting_report_t * m2ap_mbms_service_counting_report) { - AssertFatal(1==0,"Not implemented yet\n"); + M2AP_M2AP_PDU_t pdu; + M2AP_MbmsServiceCountingResultsReport_t *out; + M2AP_MbmsServiceCountingResultsReport_Ies_t *ie; + + uint8_t *buffer; + uint32_t len; + //int i = 0; + // + // memset(&pdu, 0, sizeof(pdu)); + pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage; + //pdu.choice.initiatingMessage = (M2AP_InitiatingMessage_t *)calloc(1, sizeof(M2AP_InitiatingMessage_t)); + pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_mbmsServiceCountingResultsReport; + pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_MbmsServiceCountingResultsReport; + out = &pdu.choice.initiatingMessage.value.choice.MbmsServiceCountingResultsReport; + + + /* Create */ + /* 0. Message Type */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = M2AP_M2AP_PDU_PR_initiatingMessage; + //pdu.choice.successfulOutcome = (M2AP_SuccessfulOutcome_t *)calloc(1, sizeof(M2AP_SuccessfulOutcome_t)); + pdu.choice.initiatingMessage.procedureCode = M2AP_ProcedureCode_id_mbmsServiceCountingResultsReport; + pdu.choice.initiatingMessage.criticality = M2AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = M2AP_InitiatingMessage__value_PR_MbmsServiceCountingResultsReport; + out = &pdu.choice.initiatingMessage.value.choice.MbmsServiceCountingResultsReport; + + /* mandatory */ + /* c1. MBSFN_Area_ID (integer value) */ //long + ie = (M2AP_MbmsServiceCountingResultsReport_Ies_t *)calloc(1, sizeof(M2AP_MbmsServiceCountingResultsReport_Ies_t)); + ie->id = M2AP_ProtocolIE_ID_id_MBSFN_Area_ID; + ie->criticality = M2AP_Criticality_reject; + ie->value.present = M2AP_MbmsServiceCountingResultsReport_Ies__value_PR_MBSFN_Area_ID; + //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //? + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + /* c1. MBSFN_Area_ID (integer value) */ //long + ie = (M2AP_MbmsServiceCountingResultsReport_Ies_t *)calloc(1, sizeof(M2AP_MbmsServiceCountingResultsReport_Ies_t)); + ie->id = M2AP_ProtocolIE_ID_id_MBMS_Counting_Result_List; + ie->criticality = M2AP_Criticality_reject; + ie->value.present = M2AP_MbmsServiceCountingResultsReport_Ies__value_PR_MBMS_Counting_Result_List; + //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //? + M2AP_MBMS_Counting_Result_List_t * m2ap_mbms_counting_result_list = &ie->value.choice.MBMS_Counting_Result_List; + + M2AP_MBMS_Counting_Result_Item_t * m2ap_mbms_counting_result_item = (M2AP_MBMS_Counting_Result_Item_t*)calloc(1,sizeof(M2AP_MBMS_Counting_Result_Item_t)); + m2ap_mbms_counting_result_item->id = M2AP_ProtocolIE_ID_id_MBMS_Counting_Result_Item; + m2ap_mbms_counting_result_item->criticality = M2AP_Criticality_reject; + m2ap_mbms_counting_result_item->value.present = M2AP_MBMS_Counting_Result_Item__value_PR_MBMS_Counting_Result; + M2AP_MBMS_Counting_Result_t * m2ap_mbms_counting_result = &m2ap_mbms_counting_result_item->value.choice.MBMS_Counting_Result; + + M2AP_TMGI_t * tmgi = &m2ap_mbms_counting_result->tmgi; + MCC_MNC_TO_PLMNID(0,0,3,&tmgi->pLMNidentity);/*instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,*/ + uint8_t TMGI[5] = {4,3,2,1,0}; + OCTET_STRING_fromBuf(&tmgi->serviceID,(const char*)&TMGI[2],3); + + //M2AP_CountingResult_t * m2ap_counting_result = &m2ap_mbms_counting_result->countingResult; + + ASN_SEQUENCE_ADD(&m2ap_mbms_counting_result_list->list,m2ap_mbms_counting_result_item); + + + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(M2AP, "Failed to encode MBMS Service Counting Results Report\n"); + return -1; + } return 0; } + int eNB_send_MBMS_SERVICE_COUNTING_RESP(instance_t instance, m2ap_mbms_service_counting_resp_t * m2ap_mbms_service_counting_resp) { AssertFatal(1==0,"Not implemented yet\n"); + M2AP_M2AP_PDU_t pdu; + M2AP_MbmsServiceCountingResponse_t *out; + M2AP_MbmsServiceCountingResponse_Ies_t *ie; + + uint8_t *buffer; + uint32_t len; + //int i = 0; + + /* Create */ + /* 0. Message Type */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = M2AP_M2AP_PDU_PR_successfulOutcome; + //pdu.choice.successfulOutcome = (M2AP_SuccessfulOutcome_t *)calloc(1, sizeof(M2AP_SuccessfulOutcome_t)); + pdu.choice.successfulOutcome.procedureCode = M2AP_ProcedureCode_id_mbmsServiceCounting; + pdu.choice.successfulOutcome.criticality = M2AP_Criticality_reject; + pdu.choice.successfulOutcome.value.present = M2AP_SuccessfulOutcome__value_PR_MbmsServiceCountingResponse; + out = &pdu.choice.successfulOutcome.value.choice.MbmsServiceCountingResponse; + + + /* mandatory */ + /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long + ie = (M2AP_MbmsServiceCountingResponse_Ies_t*)calloc(1, sizeof(M2AP_MbmsServiceCountingResponse_Ies_t)); + ie->id = M2AP_ProtocolIE_ID_id_MCE_MBMS_M2AP_ID; + ie->criticality = M2AP_Criticality_reject; + ie->value.present = M2AP_MbmsServiceCountingResponse_Ies__value_PR_CriticalityDiagnostics; + //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //? + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(M2AP, "Failed to encode MBMS Service Counting Results Report\n"); + return -1; + } + + return 0; return 0; } + int eNB_send_MBMS_SERVICE_COUNTING_FAILURE(instance_t instance, m2ap_mbms_service_counting_failure_t * m2ap_mbms_service_counting_failure) { - AssertFatal(1==0,"Not implemented yet\n"); + M2AP_M2AP_PDU_t pdu; + M2AP_MbmsServiceCountingFailure_t *out; + M2AP_MbmsServiceCountingFailure_Ies_t *ie; + + uint8_t *buffer; + uint32_t len; + //int i = 0; + + /* Create */ + /* 0. Message Type */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = M2AP_M2AP_PDU_PR_unsuccessfulOutcome; + //pdu.choice.successfulOutcome = (M2AP_SuccessfulOutcome_t *)calloc(1, sizeof(M2AP_SuccessfulOutcome_t)); + pdu.choice.unsuccessfulOutcome.procedureCode = M2AP_ProcedureCode_id_mbmsServiceCounting; + pdu.choice.unsuccessfulOutcome.criticality = M2AP_Criticality_reject; + pdu.choice.unsuccessfulOutcome.value.present = M2AP_UnsuccessfulOutcome__value_PR_MbmsServiceCountingFailure; + out = &pdu.choice.unsuccessfulOutcome.value.choice.MbmsServiceCountingFailure; + + + /* mandatory */ + /* c1. MCE_MBMS_M2AP_ID (integer value) */ //long + ie = (M2AP_MbmsServiceCountingFailure_Ies_t*)calloc(1, sizeof(M2AP_MbmsServiceCountingFailure_Ies_t)); + ie->id = M2AP_ProtocolIE_ID_id_ENB_MBMS_M2AP_ID; + ie->criticality = M2AP_Criticality_reject; + ie->value.present = M2AP_MbmsServiceCountingFailure_Ies__value_PR_CriticalityDiagnostics; + //ie->value.choice.MCE_MBMS_M2AP_ID = /*F1AP_get_next_transaction_identifier(enb_mod_idP, du_mod_idP);*/ //? + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + /* c2. Cause */ + ie = (M2AP_MbmsServiceCountingFailure_Ies_t *)calloc(1, sizeof(M2AP_MbmsServiceCountingFailure_Ies_t)); + ie->id = M2AP_ProtocolIE_ID_id_Cause; + ie->criticality = M2AP_Criticality_ignore; + ie->value.present = M2AP_MbmsServiceCountingFailure_Ies__value_PR_Cause; + ie->value.choice.Cause.present = M2AP_Cause_PR_radioNetwork; + ie->value.choice.Cause.choice.radioNetwork = M2AP_CauseRadioNetwork_unspecified; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + + if (m2ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(M2AP, "Failed to encode MBMS Service Counting Results Report\n"); + return -1; + } + + return 0; } diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 6f7454c321..817c863f7b 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -372,7 +372,8 @@ void *MCE_app_task(void *args_p) { // /* Try to register each MCE with MCE each other */ if (is_m3ap_MCE_enabled() /*&& !NODE_IS_DU(RC.rrc[0]->node_type)*/) { - ///*m3_register_mce_pending =*/ MCE_app_register_m3 (mce_id_start, mce_id_end); + ///*m3_register_mce_pending =*/ + MCE_app_register_m3 (mce_id_start, mce_id_end); } do { @@ -627,7 +628,7 @@ void *MCE_app_task(void *args_p) { //} - /*m3_register_mce_pending =*/ MCE_app_register_m3 (mce_id_start, mce_id_end); + /*m3_register_mce_pending =*/ //MCE_app_register_m3 (mce_id_start, mce_id_end); //MCE_app_send_m2ap_session_start_req(0); break; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index daab32c51f..99dd8bb71d 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -41,6 +41,7 @@ #include "executables/softmodem-common.h" #define MAX_IF_MODULES 100 +//#define UL_HARQ_PRINT NR_IF_Module_t *if_inst[MAX_IF_MODULES]; NR_Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; @@ -75,62 +76,8 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } -void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl) { - // TODO - int max_harq_rounds = 4; // TODO define macro - int num_ucis = UL_info->uci_ind.num_ucis; - nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; +void handle_nr_ulsch(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) { - for (int i = 0; i < num_ucis; i++) { - switch (uci_list[i].pdu_type) { - case NFAPI_NR_UCI_PDCCH_PDU_TYPE: break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - if (get_softmodem_params()->phy_test == 0) { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; - // handle harq - int harq_idx_s = 0; - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_pdu->harq->num_harq; harq_bit++) { - // search for the right harq process - for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) { - if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { - if (uci_pdu->harq->harq_list[harq_bit].harq_value == 0) - sched_ctrl->harq_processes[harq_idx].round++; - if ((uci_pdu->harq->harq_list[harq_bit].harq_value == 1) || - (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds)) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - harq_idx_s = harq_idx + 1; - break; - } - // if gNB fails to receive a ACK/NACK - else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) && - (sched_ctrl->harq_processes[harq_idx].is_waiting)) { - sched_ctrl->harq_processes[harq_idx].round++; - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - } - } - } - } - break; - } - - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: break; - } - } - - UL_info->uci_ind.num_ucis = 0; -} - - -void handle_nr_ulsch(NR_UL_IND_t *UL_info) { if(nfapi_mode == 1) { if (UL_info->crc_ind.number_crcs>0) { //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); @@ -157,6 +104,8 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) { UL_info->rx_ind.pdu_list[i].rnti) { LOG_D(PHY, "UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].crc_indication_rel8.crc_flag:%d\n", j, UL_info->crc_ind.crc_list[j].tb_crc_status); + handle_nr_ul_harq(UL_info->slot, sched_ctrl, stats, UL_info->crc_ind.crc_list[j]); + if (UL_info->crc_ind.crc_list[j].tb_crc_status == 1) { // CRC error indication LOG_D(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC error) \n",UL_info->frame,UL_info->slot); @@ -168,7 +117,8 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) { (uint8_t *)NULL, UL_info->rx_ind.pdu_list[i].pdu_length, UL_info->rx_ind.pdu_list[i].timing_advance, - UL_info->rx_ind.pdu_list[i].ul_cqi); + UL_info->rx_ind.pdu_list[i].ul_cqi, + UL_info->rx_ind.pdu_list[i].rssi); } else { LOG_D(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->slot); nr_rx_sdu(UL_info->module_id, @@ -179,7 +129,8 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) { UL_info->rx_ind.pdu_list[i].pdu, UL_info->rx_ind.pdu_list[i].pdu_length, UL_info->rx_ind.pdu_list[i].timing_advance, - UL_info->rx_ind.pdu_list[i].ul_cqi); + UL_info->rx_ind.pdu_list[i].ul_cqi, + UL_info->rx_ind.pdu_list[i].rssi); } break; } @@ -207,7 +158,6 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { NR_Sched_Rsp_t *sched_info = &Sched_INFO[module_id][CC_id]; NR_IF_Module_t *ifi = if_inst[module_id]; gNB_MAC_INST *mac = RC.nrmac[module_id]; - LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rach_pdus:%d rx_ind:%d crcs:%d]\n", UL_info->frame,UL_info->slot, module_id,CC_id, UL_info->rach_ind.number_of_pdus, @@ -228,10 +178,11 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { // clear DL/UL info for new scheduling round clear_nr_nfapi_information(mac,CC_id,UL_info->frame,UL_info->slot); handle_nr_rach(UL_info); - handle_nr_uci(UL_info, &mac->UE_list.UE_sched_ctrl[0]); + + handle_nr_uci(UL_info,&mac->UE_list.UE_sched_ctrl[0],&mac->UE_list.mac_stats[0],mac->pucch_target_snrx10); // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; - handle_nr_ulsch(UL_info); + handle_nr_ulsch(UL_info, &mac->UE_list.UE_sched_ctrl[0],&mac->UE_list.mac_stats[0]); if (nfapi_mode != 1) { if (ifi->CC_mask == ((1<config[CC_id]; int spf = get_spf(cfg); gNB_dlsch_ulsch_scheduler(module_id, - UL_info->frame, - UL_info->slot, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%spf); @@ -256,13 +205,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { sched_info->DL_req = &mac->DL_req[CC_id]; sched_info->UL_dci_req = &mac->UL_dci_req[CC_id]; - if ((mac->common_channels[CC_id].ServingCellConfigCommon->tdd_UL_DL_ConfigurationCommon==NULL) || - (is_nr_UL_slot(mac->common_channels[CC_id].ServingCellConfigCommon,UL_info->slot)>0)) { - //printf("NR_UL_indication: this is an UL slot. UL_info: frame %d, slot %d. UL_tti_req: frame %d, slot %d\n",UL_info->frame,UL_info->slot,mac->UL_tti_req[CC_id].SFN,mac->UL_tti_req[CC_id].Slot); - sched_info->UL_tti_req = &mac->UL_tti_req[CC_id]; - } - else - sched_info->UL_tti_req = NULL; + sched_info->UL_tti_req = &mac->UL_tti_req[CC_id]; sched_info->TX_req = &mac->TX_req[CC_id]; #ifdef DUMP_FAPI diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index b18831b546..91cc965473 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -117,13 +117,6 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra){ nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx); - if (mac->generate_nr_prach){ - //uint16_t monitoring_slot_period, monitoring_offset; - uint16_t rach_frame = mac->scheduled_response.ul_config->sfn; - uint16_t rx_rach_frame = (rach_frame + mac->RA_offset) % MAX_FRAME_NUMBER; // compensate 2 frames offset delay at gNB side - uint16_t rach_slot = mac->scheduled_response.ul_config->slot; - nr_ue_msg2_scheduler(module_id, rx_rach_frame, rach_slot, &mac->msg2_rx_frame, &mac->msg2_rx_slot); - } } switch(ret){ @@ -154,7 +147,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; if (!dl_info->dci_ind && !dl_info->rx_ind) { - // UL indication to schedule reception DCI reception + // UL indication to schedule DCI reception nr_ue_scheduler(dl_info, NULL); } else { // UL indication after reception of DCI or DL PDU @@ -174,13 +167,16 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ for(i=0; idci_ind->number_of_dcis; ++i){ LOG_D(MAC,">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n",i,dl_info->dci_ind->number_of_dcis); - ret_mask |= (handle_dci(dl_info->module_id, + int8_t ret = handle_dci(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - dl_info->dci_ind->dci_list+i)<< FAPI_NR_DCI_IND); + dl_info->dci_ind->dci_list+i); - AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is void!\n" ); - nr_ue_if_module_inst[module_id]->scheduled_response(&mac->scheduled_response); + ret_mask |= (ret << FAPI_NR_DCI_IND); + if (ret >= 0) { + AssertFatal( nr_ue_if_module_inst[module_id] != NULL, "IF module is void!\n" ); + nr_ue_if_module_inst[module_id]->scheduled_response(&mac->scheduled_response); + } } } diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index 41fb3ddc3a..de42d67624 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -800,7 +800,37 @@ void dl_config_req_UE_MAC_dci(int sfn, UE_mac_inst[ue_id].first_ULSCH_Tx = 1; } } - } else { + } + //else if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE) { + // // BCH case: Last parameter is 1 if first time synchronization and zero + // // otherwise. Not sure which value to put for our case. + // if (UE_mac_inst[Mod_id].UE_mode[0] == NOT_SYNCHED){ + // dl_phy_sync_success(Mod_id, sfn, 0, 1); + // LOG_E(MAC, + // "%s(): Received MIB: UE_mode: %d, sfn/sf: %d.%d\n", + // __func__, + // UE_mac_inst[Mod_id].UE_mode[0], + // sfn, + // sf); + // UE_mac_inst[Mod_id].UE_mode[0] = PRACH; + // } else { + // dl_phy_sync_success(Mod_id, sfn, 0, 0); + // } + //} else if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_MCH_PDU_TYPE){ + // if (UE_mac_inst[Mod_id].UE_mode[0] == NOT_SYNCHED) { + // /* this check is in the code before refactoring, but I don't know + // * why. Leave it in here for the moment */ + // continue; + // } + // nfapi_dl_config_request_pdu_t *dl_config_pdu_tmp = &dl_config_pdu_list[i]; + // const int pdu_index = dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index; + // ue_send_mch_sdu(Mod_id, 0, sfn, + // tx_request_pdu_list[pdu_index].segments[0].segment_data, + // tx_request_pdu_list[pdu_index].segments[0].segment_length, + // 0,0); + + //} + else { LOG_W(MAC, "can not handle special RNTI %x\n", rnti); } } diff --git a/openair2/RRC/LTE/L2_interface.c b/openair2/RRC/LTE/L2_interface.c index 68017be85b..d9682b466f 100644 --- a/openair2/RRC/LTE/L2_interface.c +++ b/openair2/RRC/LTE/L2_interface.c @@ -28,6 +28,15 @@ * \email: raymond.knopp@eurecom.fr */ +/*! \file l2_interface.c + * \brief layer 2 interface, added support for FeMBMS RRC sublayer + * \author Javier Morgade + * \date 2020 + * \version 1.0 + * \email: javier.morgade@ieee.org + */ + + #include "platform_types.h" #include "rrc_defs.h" #include "rrc_extern.h" @@ -65,6 +74,9 @@ mac_rrc_data_req( uint8_t Sdu_size = 0; uint8_t sfn = (uint8_t)((frameP>>2)&0xff); + uint8_t sfn_fembms = (uint8_t)((frameP>>4)&0xff); + sfn_fembms = sfn_fembms<<2; + if (LOG_DEBUGFLAG(DEBUG_RRC)) { LOG_D(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%ld\n",Mod_idP,Srb_id); } @@ -72,12 +84,14 @@ mac_rrc_data_req( eNB_RRC_INST *rrc; rrc_eNB_carrier_data_t *carrier; LTE_BCCH_BCH_Message_t *mib; + LTE_BCCH_BCH_Message_MBMS_t *mib_fembms; rrc = RC.rrc[Mod_idP]; carrier = &rrc->carrier[0]; mib = &carrier->mib; + mib_fembms = &carrier->mib_fembms; if((Srb_id & RAB_OFFSET) == BCCH_SI_MBMS){ - if (frameP%4 == 0) { + if (frameP%8 == 0) { memcpy(&buffer_pP[0], RC.rrc[Mod_idP]->carrier[CC_id].SIB1_MBMS, RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1_MBMS); @@ -159,6 +173,22 @@ mac_rrc_data_req( return(3); } + if( (Srb_id & RAB_OFFSET ) == MIBCH_MBMS) { + mib_fembms->message.systemFrameNumber_r14.buf = &sfn_fembms; + enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_BCH_Message_MBMS, + NULL, + (void *)mib_fembms, + carrier->MIB_FeMBMS, + 24); + LOG_I(RRC,"Encoded MIB MBMS for frame %d (%p), bits %lu %x,%x,%x %x bits_unused %d\n",sfn_fembms>>2,carrier->MIB_FeMBMS,enc_rval.encoded,carrier->MIB_FeMBMS[0],carrier->MIB_FeMBMS[1],carrier->MIB_FeMBMS[2],mib_fembms->message.systemFrameNumber_r14.buf[0],mib_fembms->message.systemFrameNumber_r14.bits_unused); + buffer_pP[0]=carrier->MIB_FeMBMS[0]; + buffer_pP[1]=carrier->MIB_FeMBMS[1]; + buffer_pP[2]=carrier->MIB_FeMBMS[2]; + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return(3); + } + if( (Srb_id & RAB_OFFSET ) == CCCH) { struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(RC.rrc[Mod_idP],rnti); @@ -203,8 +233,10 @@ mac_rrc_data_req( RC.rrc[Mod_idP]->carrier[CC_id].MCCH_MESSAGE[mbsfn_sync_area], RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]); + LOG_D(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP); + if (LOG_DEBUGFLAG(DEBUG_RRC)) { - LOG_W(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP); + LOG_D(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP); for (int i=0; icarrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]; i++) { LOG_T(RRC,"%x.",buffer_pP[i]); @@ -216,6 +248,29 @@ mac_rrc_data_req( return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]); } + if((Srb_id & RAB_OFFSET) == MCCH_COUNTING) { + if(RC.rrc[Mod_idP]->carrier[CC_id].MCCH_MESS_COUNTING[mbsfn_sync_area].Active==0) { + return 0; // this parameter is set in function init_mcch in rrc_eNB.c + } + + memcpy(&buffer_pP[0], + RC.rrc[Mod_idP]->carrier[CC_id].MCCH_MESSAGE_COUNTING[mbsfn_sync_area], + RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE_COUNTING[mbsfn_sync_area]); + + if (LOG_DEBUGFLAG(DEBUG_RRC)) { + LOG_W(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE_COUNTING \n",Mod_idP,frameP); + + for (int i=0; icarrier[CC_id].sizeof_MCCH_MESSAGE_COUNTING[mbsfn_sync_area]; i++) { + LOG_T(RRC,"%x.",buffer_pP[i]); + } + + LOG_T(RRC,"\n"); + } /* LOG_DEBUGFLAG(DEBUG_RRC) */ + + return (RC.rrc[Mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE_COUNTING[mbsfn_sync_area]); + } + + if ((Srb_id & RAB_OFFSET) == BCCH_SIB1_BR) { memcpy(&buffer_pP[0], RC.rrc[Mod_idP]->carrier[CC_id].SIB1_BR, diff --git a/openair2/RRC/LTE/L2_interface_ue.c b/openair2/RRC/LTE/L2_interface_ue.c index 61ab63955d..8c55dbaeb5 100644 --- a/openair2/RRC/LTE/L2_interface_ue.c +++ b/openair2/RRC/LTE/L2_interface_ue.c @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -/*! \file l2_interface.c +/*! \file l2_interface_ue.c * \brief layer 2 interface, used to support different RRC sublayer * \author Raymond Knopp and Navid Nikaein * \date 2010-2014 @@ -28,6 +28,16 @@ * \email: raymond.knopp@eurecom.fr */ + +/*! \file l2_interface_ue.c + * \brief layer 2 interface, added support for FeMBMS RRC sublayer + * \author J. Morgade + * \date 2020 + * \version 1.0 + * \email: javier.morgade@ieee.org + */ + + #include "platform_types.h" #include "rrc_defs.h" #include "rrc_extern.h" @@ -219,6 +229,7 @@ mac_rrc_data_ind_ue( if ((srb_idP & RAB_OFFSET) == MCCH) { LOG_T(RRC,"[UE %d] Frame %d: Received SDU on MBSFN sync area %d for MCCH on SRB %ld from eNB %d\n", module_idP,frameP, mbsfn_sync_areaP, srb_idP & RAB_OFFSET,eNB_indexP); + { MessageDef *message_p; int msg_sdu_size = sizeof(RRC_MAC_MCCH_DATA_IND (message_p).sdu); diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 9ede543003..09e6245fec 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -28,6 +28,14 @@ * \email: raymond.knopp@eurecom.fr and navid.nikaein@eurecom.fr */ +/*! \file asn1_msg.c + * \brief added primitives to build the asn1 messages for FeMBMS + * \author Javier Morgade + * \date 2019-2020 + * \version 1.0 + * \email: javier.morgade@ieee.org + */ + #include #include #include /* for atoi(3) */ @@ -185,7 +193,8 @@ uint8_t get_adjacent_cell_mod_id(uint16_t phyCellId) { uint8_t do_MIB_FeMBMS(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_t additionalNonMBSFN, uint32_t frame) { asn_enc_rval_t enc_rval; LTE_BCCH_BCH_Message_MBMS_t *mib_fembms=&carrier->mib_fembms; - uint8_t sfn = (uint8_t)((frame>>2)&0xff); + frame=198; + uint8_t sfn = (uint8_t)((frame>>4)&0xff); uint16_t *spare = calloc(1,sizeof(uint16_t)); if( spare == NULL ) abort(); @@ -223,15 +232,16 @@ uint8_t do_MIB_FeMBMS(rrc_eNB_carrier_data_t *carrier, uint32_t N_RB_DL, uint32_ (uint32_t)mib_fembms->message.dl_Bandwidth_MBMS_r14, (uint32_t)additionalNonMBSFN, (uint32_t)sfn); + sfn = sfn<<2; mib_fembms->message.systemFrameNumber_r14.buf = &sfn; mib_fembms->message.systemFrameNumber_r14.size = 1; - mib_fembms->message.systemFrameNumber_r14.bits_unused=0; + mib_fembms->message.systemFrameNumber_r14.bits_unused=2; mib_fembms->message.spare.buf = (uint8_t *)spare; mib_fembms->message.spare.size = 2; - mib_fembms->message.spare.bits_unused = 6; // This makes a spare of 10 bits + mib_fembms->message.spare.bits_unused = 3; // This makes a spare of 10 bits //TODO additionalNonBMSFNSubframes-r14 INTEGER (0..3) ? //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - //xer_fprint(stdout, &asn_DEF_LTE_BCCH_BCH_Message_MBMS, (void *)mib_fembms); + xer_fprint(stdout, &asn_DEF_LTE_BCCH_BCH_Message_MBMS, (void *)mib_fembms); //} enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_BCH_Message_MBMS, NULL, @@ -387,7 +397,11 @@ uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier, // SystemInformation_t systemInformation; int num_plmn = configuration->num_plmn; - LTE_PLMN_IdentityInfo_t *PLMN_identity_info; + //LTE_PLMN_IdentityInfo_t *PLMN_identity_info; + LTE_PLMN_IdentityInfo_t * PLMN_identity_info = &carrier->PLMN_identity_info_MBMS[0]; + //LTE_MCC_MNC_Digit_t dummy_mcc[num_plmn][3], dummy_mnc[num_plmn][3]; + //LTE_MCC_MNC_Digit_t *dummy_mcc = &carrier->dummy_mcc_MBMS[0][0]; + //LTE_MCC_MNC_Digit_t *dummy_mnc = &carrier->dummy_mnc_MBMS[0][0]; LTE_MCC_MNC_Digit_t *dummy_mcc_0; LTE_MCC_MNC_Digit_t *dummy_mcc_1; LTE_MCC_MNC_Digit_t *dummy_mcc_2; @@ -395,7 +409,9 @@ uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier, LTE_MCC_MNC_Digit_t *dummy_mnc_1; LTE_MCC_MNC_Digit_t *dummy_mnc_2; asn_enc_rval_t enc_rval; - LTE_SchedulingInfo_MBMS_r14_t *schedulingInfo; + //LTE_SchedulingInfo_MBMS_r14_t *schedulingInfo; + //LTE_SchedulingInfo_MBMS_r14_t schedulingInfo; + LTE_SchedulingInfo_MBMS_r14_t *schedulingInfo = &carrier->schedulingInfo_MBMS; LTE_SIB_Type_t *sib_type; uint8_t *buffer = carrier->SIB1_MBMS; LTE_BCCH_DL_SCH_Message_MBMS_t *bcch_message = &carrier->siblock1_MBMS; @@ -408,6 +424,8 @@ uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier, // memcpy(&bcch_message.message.choice.c1.choice.systemInformationBlockType1,sib1,sizeof(SystemInformationBlockType1_t)); *sib1_MBMS = &bcch_message->message.choice.c1.choice.systemInformationBlockType1_MBMS_r14; PLMN_identity_info = CALLOC(1, sizeof(LTE_PLMN_IdentityInfo_t) * num_plmn); + //memset(&schedulingInfo,0,sizeof(LTE_SchedulingInfo_MBMS_r14_t)); + memset(schedulingInfo,0,sizeof(LTE_SchedulingInfo_MBMS_r14_t)); if (PLMN_identity_info == NULL) exit(1); @@ -528,7 +546,7 @@ uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier, MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.size= 1; MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf[0]=0x20<<2; // FDD: SF1 MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2; - MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__signallingMCS_r9_n7; + MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__signallingMCS_r9_n2; (MBSFN_Area1)->ext1 = CALLOC (1, sizeof(*(MBSFN_Area1)->ext1)); memset((MBSFN_Area1)->ext1,0,sizeof(*(MBSFN_Area1)->ext1)); MBSFN_Area1->ext1->subcarrierSpacingMBMS_r14 = CALLOC(1,sizeof(*( MBSFN_Area1->ext1)->subcarrierSpacingMBMS_r14)); @@ -541,18 +559,18 @@ uint8_t do_SIB1_MBMS(rrc_eNB_carrier_data_t *carrier, if(1) { (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14 = CALLOC(1,sizeof(struct LTE_NonMBSFN_SubframeConfig_r14)); memset((*sib1_MBMS)->nonMBSFN_SubframeConfig_r14,0,sizeof(struct LTE_NonMBSFN_SubframeConfig_r14)); - (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->radioFrameAllocationPeriod_r14 = LTE_NonMBSFN_SubframeConfig_r14__radioFrameAllocationPeriod_r14_rf8; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->radioFrameAllocationPeriod_r14 = LTE_NonMBSFN_SubframeConfig_r14__radioFrameAllocationPeriod_r14_rf4; (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->radioFrameAllocationOffset_r14 = 0; (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf = MALLOC(2); //100000001 byte(0)=10000000 byte(1)=xxxxxxx1 - (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf[0] = 0x80<<0; - (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf[1] = 0x1<<7; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf[0] = 0x8<<0; + (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf[1] = 0; (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.size = 2; (*sib1_MBMS)->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.bits_unused = 7; } //if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, (void *)bcch_message); + xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, (void *)bcch_message); //} enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, NULL, @@ -3198,6 +3216,42 @@ uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, ASN_SEQUENCE_ADD(&dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list, &rat); + /* request NR configuration */ + LTE_UECapabilityEnquiry_r8_IEs_t *r8 = &dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8; + LTE_UECapabilityEnquiry_v8a0_IEs_t r8_a0; + LTE_UECapabilityEnquiry_v1180_IEs_t r11_80; + LTE_UECapabilityEnquiry_v1310_IEs_t r13_10; + LTE_UECapabilityEnquiry_v1430_IEs_t r14_30; + LTE_UECapabilityEnquiry_v1510_IEs_t r15_10; + + memset(&r8_a0, 0, sizeof(r8_a0)); + memset(&r11_80, 0, sizeof(r11_80)); + memset(&r13_10, 0, sizeof(r13_10)); + memset(&r14_30, 0, sizeof(r14_30)); + memset(&r15_10, 0, sizeof(r15_10)); + + r8->nonCriticalExtension = &r8_a0; + r8_a0.nonCriticalExtension = &r11_80; + r11_80.nonCriticalExtension = &r13_10; + r13_10.nonCriticalExtension = &r14_30; + r14_30.nonCriticalExtension = &r15_10; + + /* TODO: no hardcoded values here */ + + OCTET_STRING_t req_freq; + unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x08, 0x18 }; // bands 7 & nr260 + + //unsigned char req_freq_buf[13] = { 0x00, 0xc0, 0x18, 0x01, 0x01, 0x30, 0x4b, 0x04, 0x0e, 0x08, 0x24, 0x04, 0xd0 }; +// unsigned char req_freq_buf[21] = { +//0x01, 0x60, 0x18, 0x05, 0x80, 0xc0, 0x04, 0x04, 0xc1, 0x2c, 0x10, 0x08, 0x20, 0x30, 0x40, 0xe0, 0x82, 0x40, 0x28, 0x80, 0x9a +// }; + + req_freq.buf = req_freq_buf; + req_freq.size = 5; +// req_freq.size = 21; + + r15_10.requestedFreqBandsNR_MRDC_r15 = &req_freq; if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_LTE_DL_DCCH_Message, (void *)&dl_dcch_msg); } @@ -3276,17 +3330,17 @@ uint8_t do_NR_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, /* TODO: no hardcoded values here */ OCTET_STRING_t req_freq; - //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x08, 0x18 }; // bands 7 & nr260 //unsigned char req_freq_buf[13] = { 0x00, 0xc0, 0x18, 0x01, 0x01, 0x30, 0x4b, 0x04, 0x0e, 0x08, 0x24, 0x04, 0xd0 }; - unsigned char req_freq_buf[21] = { -0x01, 0x60, 0x18, 0x05, 0x80, 0xc0, 0x04, 0x04, 0xc1, 0x2c, 0x10, 0x08, 0x20, 0x30, 0x40, 0xe0, 0x82, 0x40, 0x28, 0x80, 0x9a - }; +// unsigned char req_freq_buf[21] = { +//0x01, 0x60, 0x18, 0x05, 0x80, 0xc0, 0x04, 0x04, 0xc1, 0x2c, 0x10, 0x08, 0x20, 0x30, 0x40, 0xe0, 0x82, 0x40, 0x28, 0x80, 0x9a +// }; req_freq.buf = req_freq_buf; req_freq.size = 5; - req_freq.size = 21; +// req_freq.size = 21; r15_10.requestedFreqBandsNR_MRDC_r15 = &req_freq; diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index bdf992c76a..c5aa2bc0f8 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -155,14 +155,19 @@ static uint8_t check_trigger_meas_event( LTE_Q_OffsetRange_t ofs, LTE_Q_OffsetRange_t ocs, long a3_offset, LTE_TimeToTrigger_t ttt); static void decode_MBSFNAreaConfiguration(module_id_t module_idP, uint8_t eNB_index, frame_t frameP,uint8_t mbsfn_sync_area); +static void decode_MBMSCountingRequest(module_id_t module_idP, uint8_t eNB_index, frame_t frameP,uint8_t mbsfn_sync_area); + uint8_t rrc_ue_generate_SidelinkUEInformation( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index,LTE_SL_DestinationInfoList_r12_t *destinationInfoList, long *discTxResourceReq, SL_TRIGGER_t mode); - - - - - +void +rrc_ue_process_MBMSCountingRequest( + const protocol_ctxt_t *const ctxt_pP, + LTE_MBMSCountingRequest_r10_t *MBMSCountingRequest, + uint8_t eNB_index + ); + +protocol_ctxt_t ctxt_pP_local; /*------------------------------------------------------------------------------*/ @@ -520,6 +525,7 @@ static void rrc_ue_generate_RRCConnectionSetupComplete( LOG_D(RLC, "[FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCConnectionSetupComplete to eNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n", ctxt_pP->frame, ctxt_pP->module_id+NB_eNB_INST, size, eNB_index, rrc_mui, ctxt_pP->module_id+NB_eNB_INST, DCCH); + ctxt_pP_local.rnti = ctxt_pP->rnti; rrc_data_req_ue ( ctxt_pP, DCCH, @@ -1572,6 +1578,65 @@ rrc_ue_process_securityModeCommand( securityModeCommand->criticalExtensions.present); } +void +rrc_ue_process_MBMSCountingRequest( + const protocol_ctxt_t *const ctxt_pP, + LTE_MBMSCountingRequest_r10_t *MBMSCountingRequest, + uint8_t eNB_index +) +{ + asn_enc_rval_t enc_rval; + LTE_UL_DCCH_Message_t ul_dcch_msg; + struct LTE_CountingResponseInfo_r10 CountingResponse; + uint8_t buffer[200]; + //int i; + LOG_I(RRC,"[UE %d] Frame %d: Receiving from (MCCH), Processing MBMSCoutingRequest (eNB %d)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + eNB_index); + memset((void *)&ul_dcch_msg,0,sizeof(LTE_UL_DCCH_Message_t)); + memset((void *)&CountingResponse,0,sizeof(struct LTE_CountingResponseInfo_r10)); + + + ul_dcch_msg.message.present = LTE_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1.present = LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10; + LTE_MBMSCountingResponse_r10_t *MBMSCountingResponse = &ul_dcch_msg.message.choice.c1.choice.mbmsCountingResponse_r10; + + MBMSCountingResponse->criticalExtensions.present = LTE_MBMSCountingResponse_r10__criticalExtensions_PR_c1; + MBMSCountingResponse->criticalExtensions.choice.c1.present = LTE_MBMSCountingResponse_r10__criticalExtensions__c1_PR_countingResponse_r10; + LTE_MBMSCountingResponse_r10_IEs_t *MBMSCountingResponse_r10_IEs = &MBMSCountingResponse->criticalExtensions.choice.c1.choice.countingResponse_r10; + + MBMSCountingResponse_r10_IEs->mbsfn_AreaIndex_r10 = calloc(1,sizeof(long)); + // MBMSCountingResponse_r10_IEs->countingResponseList_r10 = calloc(1,sizeof(struct LTE_CountingResponseList_r10)); +// +// ASN_SEQUENCE_ADD( +// &MBMSCountingResponse->criticalExtensions.choice.c1.choice.countingResponse_r10.countingResponseList_r10.list, +// &CountingResponse); +// + + enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_UL_DCCH_Message, NULL, (void *) &ul_dcch_msg, buffer, 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)&ul_dcch_msg); + + + LOG_I(RRC,"MBMSCountingResponse Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + rrc_data_req_ue ( + &ctxt_pP_local, + DCCH, + rrc_mui++, + SDU_CONFIRM_NO, + (enc_rval.encoded + 7) / 8, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + +} + + //----------------------------------------------------------------------------- void rrc_ue_process_ueCapabilityEnquiry( @@ -2189,8 +2254,8 @@ rrc_ue_decode_dcch( #endif } -const char siWindowLength[8][5] = {"1ms","2ms","5ms","10ms","15ms","20ms","40ms","ERR"}; -const char siWindowLength_int[7] = {1,2,5,10,15,20,40}; +const char siWindowLength[9][5] = {"1ms","2ms","5ms","10ms","15ms","20ms","40ms","80ms","ERR"}; +const char siWindowLength_int[8] = {1,2,5,10,15,20,40,80}; const char SIBType[12][6] = {"SIB3","SIB4","SIB5","SIB6","SIB7","SIB8","SIB9","SIB10","SIB11","SIB12","SIB13","Spare"}; const char SIBPeriod[8][6]= {"rf8","rf16","rf32","rf64","rf128","rf256","rf512","ERR"}; @@ -2700,7 +2765,7 @@ int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_in //LOG_I( RRC, "TDD subframeAssignment : %ld\n", sib1_MBMS->tdd_Config->subframeAssignment ); //LOG_I( RRC, "TDD specialSubframePatterns : %ld\n", sib1_MBMS->tdd_Config->specialSubframePatterns ); //} - LOG_I( RRC, "siWindowLength : %s\n", siWindowLength[min(sib1_MBMS->si_WindowLength_r14,7)] ); + LOG_I( RRC, "siWindowLength : %s\n", siWindowLength[min(sib1_MBMS->si_WindowLength_r14,8)] ); LOG_I( RRC, "systemInfoValueTag : %ld\n", sib1_MBMS->systemInfoValueTag_r14 ); UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod_MBMS = siPeriod_int[sib1_MBMS->schedulingInfoList_MBMS_r14.list.array[0]->si_Periodicity_r14]; UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize_MBMS = siWindowLength_int[sib1_MBMS->si_WindowLength_r14]; @@ -2898,7 +2963,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, LOG_I( RRC, "TDD specialSubframePatterns : %ld\n", sib1->tdd_Config->specialSubframePatterns ); } - LOG_I( RRC, "siWindowLength : %s\n", siWindowLength[min(sib1->si_WindowLength,7)] ); + LOG_I( RRC, "siWindowLength : %s\n", siWindowLength[min(sib1->si_WindowLength,8)] ); LOG_I( RRC, "systemInfoValueTag : %ld\n", sib1->systemInfoValueTag ); UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod = siPeriod_int[sib1->schedulingInfoList.list.array[0]->si_Periodicity]; UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize = siWindowLength_int[sib1->si_WindowLength]; @@ -4225,7 +4290,7 @@ int decode_MCCH_Message( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB ctxt_pP->frame, mbsfn_sync_area); return 0; // avoid decoding to prevent memory bloating - } else if(UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State >= RRC_CONNECTED /*|| UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_RECONFIGURED*/){ + } else if(1/*UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State >= RRC_CONNECTED*/ /*|| UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_RECONFIGURED*/){ dec_rval = uper_decode_complete(NULL, &asn_DEF_LTE_MCCH_Message, (void **)&mcch, @@ -4244,6 +4309,7 @@ int decode_MCCH_Message( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_LTE_MCCH_Message, (void *)mcch); } + xer_fprint(stdout, &asn_DEF_LTE_MCCH_Message, (void *)mcch); if (mcch->message.present == LTE_MCCH_MessageType_PR_c1) { LOG_D(RRC,"[UE %d] Found mcch message \n", @@ -4265,7 +4331,29 @@ int decode_MCCH_Message( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB ctxt_pP->frame, mbsfn_sync_area); } + }else if(mcch->message.present == LTE_MCCH_MessageType_PR_later){ + LOG_D(RRC,"[UE %d] Found mcch message \n", + ctxt_pP->module_id); + if(mcch->message.choice.later.present == LTE_MCCH_MessageType__later_PR_c2){ + if(mcch->message.choice.later.choice.c2.present == LTE_MCCH_MessageType__later__c2_PR_mbmsCountingRequest_r10){ + LOG_I(RRC,"[UE %d] Frame %d : Found MBMSCountingRequest from eNB %d %p\n", + ctxt_pP->module_id, + ctxt_pP->frame, + eNB_index,&mcch->message.choice.later.choice.c2.choice.mbmsCountingRequest_r10); + + rrc_ue_process_MBMSCountingRequest(ctxt_pP,&mcch->message.choice.later.choice.c2.choice.mbmsCountingRequest_r10,eNB_index); + + decode_MBMSCountingRequest( + ctxt_pP->module_id, + eNB_index, + ctxt_pP->frame, + mbsfn_sync_area); + + + } + } } + } return 0; @@ -4323,7 +4411,7 @@ void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_index, f (struct LTE_NonMBSFN_SubframeConfig_r14 *)NULL, (LTE_MBSFN_AreaInfoList_r9_t *)NULL ); - if(UE_rrc_inst[ue_mod_idP].Info[eNB_index].State >= RRC_CONNECTED /*|| UE_rrc_inst[ue_mod_idP].Info[eNB_index].State == RRC_RECONFIGURED*/) + if(1/*UE_rrc_inst[ue_mod_idP].Info[eNB_index].State >= RRC_CONNECTED*/ /*|| UE_rrc_inst[ue_mod_idP].Info[eNB_index].State == RRC_RECONFIGURED*/) UE_rrc_inst[ue_mod_idP].Info[eNB_index].MCCHStatus[mbsfn_sync_area] = 1; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_idP, ENB_FLAG_NO, UE_rrc_inst[ue_mod_idP].Info[eNB_index].rnti, frameP, 0,eNB_index); // Config Radio Bearer for MBMS user data (similar way to configure for eNB side in init_MBMS function) @@ -4347,6 +4435,13 @@ void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_index, f // */ } +void decode_MBMSCountingRequest( module_id_t ue_mod_idP, uint8_t eNB_index, frame_t frameP, uint8_t mbsfn_sync_area ) { + //uint8_t i; + //protocol_ctxt_t ctxt; + + + +} //----------------------------------------------------------------------------- void *rrc_ue_task( void *args_p ) { diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 3c02c45bc1..c498e3c6fe 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -716,6 +716,9 @@ typedef struct { LTE_BCCH_BCH_Message_MBMS_t mib_fembms; LTE_BCCH_DL_SCH_Message_MBMS_t siblock1_MBMS; LTE_BCCH_DL_SCH_Message_MBMS_t systemInformation_MBMS; + LTE_SchedulingInfo_MBMS_r14_t schedulingInfo_MBMS; + LTE_PLMN_IdentityInfo_t PLMN_identity_info_MBMS[6]; + LTE_MCC_MNC_Digit_t dummy_mcc_MBMS[6][3], dummy_mnc_MBMS[6][3]; LTE_SystemInformationBlockType1_t *sib1; LTE_SystemInformationBlockType2_t *sib2; LTE_SystemInformationBlockType3_t *sib3; @@ -732,6 +735,12 @@ typedef struct { LTE_MCCH_Message_t mcch; LTE_MBSFNAreaConfiguration_r9_t *mcch_message; SRB_INFO MCCH_MESS[8];// MAX_MBSFN_AREA + uint8_t **MCCH_MESSAGE_COUNTING; // MAX_MBSFN_AREA + uint8_t sizeof_MCCH_MESSAGE_COUNTING[8];// MAX_MBSFN_AREA + LTE_MCCH_Message_t mcch_counting; + LTE_MBMSCountingRequest_r10_t *mcch_message_counting; + SRB_INFO MCCH_MESS_COUNTING[8];// MAX_MBSFN_AREA + //TTN - SIB 18,19,21 for D2D LTE_SystemInformationBlockType18_r12_t *sib18; LTE_SystemInformationBlockType19_r12_t *sib19; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 1d44751dca..a6775bbf8a 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -231,6 +231,7 @@ init_SI( RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sib1_MBMS->nonMBSFN_SubframeConfig_r14->subframeAllocation_r14.buf); } + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].FeMBMS_flag=1; //AssertFatal(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_SIB1 != 255,"FATAL, RC.rrc[enb_mod_idP].carrier[CC_id].sizeof_SIB1 == 255"); } @@ -496,11 +497,18 @@ init_SI( (LTE_PMCH_InfoList_r9_t *) NULL, sib1_v13ext, RC.rrc[ctxt_pP->module_id]->carrier[CC_id].FeMBMS_flag, - (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, + (carrier->sib1_MBMS==NULL?(LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL:(LTE_BCCH_DL_SCH_Message_MBMS_t *)carrier->sib1_MBMS),//(LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, (LTE_SchedulingInfo_MBMS_r14_t *) NULL, - (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, - (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (carrier->sib1_MBMS==NULL + ? (struct LTE_NonMBSFN_SubframeConfig_r14 *)NULL + : (struct LTE_NonMBSFN_SubframeConfig_r14 *)carrier->sib1_MBMS->nonMBSFN_SubframeConfig_r14),//(struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, + (carrier->sib1_MBMS==NULL + ? (LTE_SystemInformationBlockType1_MBMS_r14_t *)NULL + : (LTE_SystemInformationBlockType1_MBMS_r14_t *)carrier->sib1_MBMS->systemInformationBlockType13_r14),//(LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, + (carrier->sib1_MBMS==NULL + ? (LTE_MBSFN_AreaInfoList_r9_t *)NULL + : (LTE_MBSFN_AreaInfoList_r9_t *)&carrier->sib1_MBMS->systemInformationBlockType13_r14->mbsfn_AreaInfoList_r9),//(LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *)NULL ); } @@ -584,7 +592,8 @@ init_MCCH( (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } @@ -994,11 +1003,14 @@ void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag) { pthread_mutex_unlock(&lock_ue_freelist); } +extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); +extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); + void release_UE_in_freeList(module_id_t mod_id) { int i, j, CC_id, pdu_number; protocol_ctxt_t ctxt; - LTE_eNB_ULSCH_t *ulsch = NULL; - LTE_eNB_DLSCH_t *dlsch = NULL; nfapi_ul_config_request_body_t *ul_req_tmp = NULL; PHY_VARS_eNB *eNB_PHY = NULL; struct rrc_eNB_ue_context_s *ue_context_pP = NULL; @@ -1031,33 +1043,18 @@ void release_UE_in_freeList(module_id_t mod_id) { for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { eNB_PHY = RC.eNB[mod_id][CC_id]; + int id; + // clean ULSCH entries for rnti + id = find_ulsch(rnti,eNB_PHY,SEARCH_EXIST); - for (i=0; iulsch[i]; + if (id>=0) clean_eNb_ulsch(eNB_PHY->ulsch[id]); - if((ulsch != NULL) && (ulsch->rnti == rnti)) { - void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); - LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); - clean_eNb_ulsch(ulsch); - } + // clean DLSCH entries for rnti + id = find_dlsch(rnti,eNB_PHY,SEARCH_EXIST); - dlsch = eNB_PHY->dlsch[i][0]; - - if((dlsch != NULL) && (dlsch->rnti == rnti)) { - void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); - LOG_I(RRC, "clean_eNb_dlsch dlsch[%d] UE %x \n", i, rnti); - clean_eNb_dlsch(dlsch); - } - } - - ulsch = eNB_PHY->ulsch[i]; - - if((ulsch != NULL) && (ulsch->rnti == rnti)) { - void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); - LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); - clean_eNb_ulsch(ulsch); - } + if (id>=0) clean_eNb_dlsch(eNB_PHY->dlsch[id][0]); + // clean UCI entries for rnti for (i=0; iuci_vars[i].rnti == rnti) { LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti); @@ -1065,6 +1062,41 @@ void release_UE_in_freeList(module_id_t mod_id) { } } + /* + for (i=0; iulsch[i]; + + if((ulsch != NULL) && (ulsch->rnti == rnti)) { + void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); + LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); + clean_eNb_ulsch(ulsch); + } + + dlsch = eNB_PHY->dlsch[i][0]; + + if((dlsch != NULL) && (dlsch->rnti == rnti)) { + void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); + LOG_I(RRC, "clean_eNb_dlsch dlsch[%d] UE %x \n", i, rnti); + clean_eNb_dlsch(dlsch); + } + } + + ulsch = eNB_PHY->ulsch[i]; + + if((ulsch != NULL) && (ulsch->rnti == rnti)) { + void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); + LOG_I(RRC, "clean_eNb_ulsch ulsch[%d] UE %x\n", i, rnti); + clean_eNb_ulsch(ulsch); + } + + for (i=0; iuci_vars[i].rnti == rnti) { + LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti); + memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI)); + } + } + */ + if (flexran_agent_get_rrc_xface(mod_id)) { flexran_agent_get_rrc_xface(mod_id)->flexran_agent_notify_ue_state_change( mod_id, rnti, PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED); @@ -1458,7 +1490,8 @@ rrc_eNB_generate_RRCConnectionReestablishment( (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); break; } @@ -2160,7 +2193,6 @@ rrc_eNB_generate_RRCConnectionRelease( uint8_t buffer[RRC_BUF_SIZE]; uint16_t size = 0; int release_num; - memset(buffer, 0, RRC_BUF_SIZE); T(T_ENB_RRC_CONNECTION_RELEASE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); @@ -3251,7 +3283,8 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t MeasObj2->measObjectId = 2; MeasObj2->measObject.present = LTE_MeasObjectToAddMod__measObject_PR_measObjectNR_r15; - MeasObj2->measObject.choice.measObjectNR_r15.carrierFreq_r15 =641272; //634000; //(634000 = 3.51GHz) (640000 = 3.6GHz) (641272 = 3619.08MHz = 3600 + 30/1000*106*12/2) (642256 is for 3.6GHz and absoluteFrequencySSB = 642016) + MeasObj2->measObject.choice.measObjectNR_r15.carrierFreq_r15 = 641272; + //634000; //(634000 = 3.51GHz) (640000 = 3.6GHz) (641272 = 3619.08MHz = 3600 + 30/1000*106*12/2) (642256 is for 3.6GHz and absoluteFrequencySSB = 642016) MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.present = LTE_MTC_SSB_NR_r15__periodicityAndOffset_r15_PR_sf20_r15; MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.choice.sf20_r15 = 0; MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.ssb_Duration_r15 = LTE_MTC_SSB_NR_r15__ssb_Duration_r15_sf4; @@ -3563,20 +3596,19 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); - /* Refresh SRBs/DRBs */ rrc_pdcp_config_asn1_req(ctxt_pP, - *SRB_configList2, // NULL, - *DRB_configList, - NULL, - 0xff, // already configured during the securitymodecommand - NULL, - NULL, - NULL + *SRB_configList2, // NULL, + *DRB_configList, + NULL, + 0xff, // already configured during the securitymodecommand + NULL, + NULL, + NULL #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , (LTE_PMCH_InfoList_r9_t *) NULL + , (LTE_PMCH_InfoList_r9_t *) NULL #endif - , NULL); + , NULL); /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { @@ -3589,7 +3621,7 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t 0, 0 #endif - ); + ); } free(Sparams); @@ -4636,7 +4668,7 @@ rrc_eNB_process_MeasurementReport( for (int e_rab=0; e_rab < X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded; e_rab++) { X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id; X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].gtp_teid = ue_context_pP->ue_context.e_rab[e_rab].param.gtp_teid; - X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].drb_ID = ue_context_pP->ue_context.DRB_configList->list.array[e_rab]->drb_Identity; + X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].drb_ID = ue_context_pP->ue_context.DRB_configList->list.array[e_rab]->drb_Identity; memcpy(&X2AP_ENDC_SGNB_ADDITION_REQ(msg).e_rabs_tobeadded[e_rab].sgw_addr, &ue_context_pP->ue_context.e_rab[e_rab].param.sgw_addr, sizeof(transport_layer_addr_t)); @@ -5758,7 +5790,8 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); // Configure target eNB SRB2 /// SRB2 @@ -6310,20 +6343,19 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct ue_context_pP->ue_context.rnti, rrc_eNB_mui, size); - /* Refresh SRBs/DRBs */ rrc_pdcp_config_asn1_req(ctxt_pP, - *SRB_configList2, // NULL, - *DRB_configList, - NULL, - 0xff, // already configured during the securitymodecommand - NULL, - NULL, - NULL + *SRB_configList2, // NULL, + *DRB_configList, + NULL, + 0xff, // already configured during the securitymodecommand + NULL, + NULL, + NULL #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) - , (LTE_PMCH_InfoList_r9_t *) NULL + , (LTE_PMCH_InfoList_r9_t *) NULL #endif - , NULL); + , NULL); /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { @@ -6336,7 +6368,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct 0, 0 #endif - ); + ); } free(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ); @@ -6382,6 +6414,7 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc NULL, NULL, (LTE_PMCH_InfoList_r9_t *) NULL, NULL); + if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { rrc_rlc_config_asn1_req(ctxt_pP, ue_context_p->ue_context.SRB_configList, @@ -6438,7 +6471,8 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } @@ -6521,6 +6555,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( kUPenc, (LTE_PMCH_InfoList_r9_t *) NULL, NULL); + /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) { rrc_rlc_config_asn1_req(ctxt_pP, @@ -6530,7 +6565,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (LTE_PMCH_InfoList_r9_t *) NULL, 0, 0 - ); + ); } /* Set the SRB active in UE context */ @@ -6654,7 +6689,8 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } } else { // remove LCHAN from MAC/PHY @@ -6713,7 +6749,8 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); } } // end else of if (ue_context_pP->ue_context.DRB_active[drb_id] == 0) @@ -6875,7 +6912,8 @@ rrc_eNB_generate_RRCConnectionSetup( (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t *) NULL ); break; } @@ -7009,6 +7047,16 @@ char openair_rrc_eNB_configuration( return 0; } +static +void rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(protocol_ctxt_t *const ctxt_pP, + const int CC_id) { + struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, ctxt_pP->rnti); + rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, + ue_context_p, + CC_id); + ue_context_p->ue_context.ul_failure_timer = 500; // 500 milliseconds to send the message and remove temporary entry +} + /*------------------------------------------------------------------------------*/ int rrc_eNB_decode_ccch( @@ -7087,12 +7135,14 @@ rrc_eNB_decode_ccch( uint16_t c_rnti = 0; if (rrcConnectionReestablishmentRequest->ue_Identity.physCellId != RC.rrc[ctxt_pP->module_id]->carrier[CC_id].physCellId) { + /* UE was moving from previous cell so quickly that RRCConnectionReestablishment for previous cell was recieved in this cell */ LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest ue_Identity.physCellId(%ld) is not equal to current physCellId(%d), let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), rrcConnectionReestablishmentRequest->ue_Identity.physCellId, RC.rrc[ctxt_pP->module_id]->carrier[CC_id].physCellId); - rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(ctxt_pP, + CC_id); break; } @@ -7105,10 +7155,12 @@ rrc_eNB_decode_ccch( if (rrcConnectionReestablishmentRequest->ue_Identity.c_RNTI.size == 0 || rrcConnectionReestablishmentRequest->ue_Identity.c_RNTI.size > 2) { + /* c_RNTI range error should not happen */ LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest c_RNTI range error, let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); - rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(ctxt_pP, + CC_id); break; } @@ -7120,7 +7172,8 @@ rrc_eNB_decode_ccch( LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" LTE_RRCConnectionReestablishmentRequest without UE context, let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); - rrc_eNB_generate_RRCConnectionReestablishmentReject(ctxt_pP, ue_context_p, CC_id); + rrc_eNB_generate_RRCConnectionReestablishmentReject_unknown_UE(ctxt_pP, + CC_id); break; } @@ -7187,8 +7240,10 @@ rrc_eNB_decode_ccch( if(ue_context_p->ue_context.ue_reestablishment_timer > 0) { LOG_E(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" RRRCConnectionReconfigurationComplete(Previous) don't receive, delete the Previous UE\n", - PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + PROTOCOL_RRC_CTXT_UE_FMT" RRRCConnectionReconfigurationComplete(Previous) don't receive, delete the Previous UE,\nprevious Status %d, new Status RRC_RECONFIGURED\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p->ue_context.Status + ); ue_context_p->ue_context.Status = RRC_RECONFIGURED; protocol_ctxt_t ctxt_old_p; PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt_old_p, @@ -7773,8 +7828,7 @@ rrc_eNB_decode_dcch( LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_HO_EXECUTION (xid %ld)\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); - } - else if(ue_context_p->ue_context.Status == RRC_NR_NSA){ + } else if(ue_context_p->ue_context.Status == RRC_NR_NSA) { //Looking for a condition to trigger S1AP E-RAB-Modification-indication, based on the reception of RRCConnectionReconfigurationComplete //including NR specific elements. if(ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.criticalExtensions.choice.rrcConnectionReconfigurationComplete_r8. @@ -7802,8 +7856,7 @@ rrc_eNB_decode_dcch( } } } - } - else { + } else { dedicated_DRB = 0; ue_context_p->ue_context.Status = RRC_RECONFIGURED; LOG_I(RRC, @@ -7812,7 +7865,6 @@ rrc_eNB_decode_dcch( } ue_context_p->ue_context.reestablishment_xid = -1; - } else { dedicated_DRB = 1; ue_context_p->ue_context.Status = RRC_RECONFIGURED; @@ -8348,6 +8400,7 @@ rrc_eNB_decode_dcch( case LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10: T(T_ENB_RRC_MBMS_COUNTING_RESPONSE_R10, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); + LOG_E(RRC, "THINH [LTE_UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10]\n"); break; case LTE_UL_DCCH_MessageType__c1_PR_interFreqRSTDMeasurementIndication_r10: @@ -8375,46 +8428,46 @@ rrc_eNB_decode_dcch( case LTE_UL_DCCH_MessageType__messageClassExtension_PR_c2: //SidelinkUEInformation if(ul_dcch_msg->message.choice.messageClassExtension.choice.c2.present == - LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_scgFailureInformationNR_r15){ + LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_scgFailureInformationNR_r15) { if (ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15. - criticalExtensions.present == LTE_SCGFailureInformationNR_r15__criticalExtensions_PR_c1){ + criticalExtensions.present == LTE_SCGFailureInformationNR_r15__criticalExtensions_PR_c1) { if (ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. - choice.c1.present == LTE_SCGFailureInformationNR_r15__criticalExtensions__c1_PR_scgFailureInformationNR_r15){ + choice.c1.present == LTE_SCGFailureInformationNR_r15__criticalExtensions__c1_PR_scgFailureInformationNR_r15) { if (ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. - choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15!=NULL) { + choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15!=NULL) { LOG_E(RRC, "Received NR scgFailureInformation from UE, failure type: %ld \n", - ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. - choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15->failureType_r15); + ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.scgFailureInformationNR_r15.criticalExtensions. + choice.c1.choice.scgFailureInformationNR_r15.failureReportSCG_NR_r15->failureType_r15); xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void *)ul_dcch_msg); } } } - } - else if(ul_dcch_msg->message.choice.messageClassExtension.choice.c2.present == LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12){ + } else if(ul_dcch_msg->message.choice.messageClassExtension.choice.c2.present == LTE_UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12) { //case UL_DCCH_MessageType__messageClassExtension__c2_PR_sidelinkUEInformation_r12: //SidelinkUEInformation LOG_I(RRC,"THINH [LTE_UL_DCCH_MessageType__messageClassExtension_PR_c2]\n"); LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, - "[MSG] RRC SidelinkUEInformation \n"); + "[MSG] RRC SidelinkUEInformation \n"); MSC_LOG_RX_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - Rx_sdu, - sdu_sizeP, - MSC_AS_TIME_FMT" SidelinkUEInformation UE %x size %u", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_p->ue_context.rnti, - sdu_sizeP); - LOG_I(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " - "(SidelinkUEInformation) ---> RRC_eNB\n", - PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), - DCCH, + MSC_RRC_ENB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" SidelinkUEInformation UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, sdu_sizeP); + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(SidelinkUEInformation) ---> RRC_eNB\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); rrc_eNB_process_SidelinkUEInformation( ctxt_pP, ue_context_p, &ul_dcch_msg->message.choice.messageClassExtension.choice.c2.choice.sidelinkUEInformation_r12); - } + } + break; default: @@ -8581,17 +8634,14 @@ void rrc_enb_init(void) { //----------------------------------------------------------------------------- void process_successful_rlc_sdu_indication(int instance, - int rnti, - int message_id) -{ + int rnti, + int message_id) { int release_num; int release_total; RRC_release_ctrl_t *release_ctrl; - /* Check if the message sent was RRC Connection Release. * If yes then continue the release process. */ - pthread_mutex_lock(&rrc_release_freelist); if (rrc_release_info.num_UEs > 0) { @@ -8633,14 +8683,11 @@ void process_successful_rlc_sdu_indication(int instance, } //----------------------------------------------------------------------------- -void process_unsuccessful_rlc_sdu_indication(int instance, int rnti) -{ +void process_unsuccessful_rlc_sdu_indication(int instance, int rnti) { int release_num; int release_total; RRC_release_ctrl_t *release_ctrl; - /* radio link failure detected by RLC layer, remove UE properly */ - pthread_mutex_lock(&rrc_release_freelist); /* first, check if the rnti is in the list rrc_release_info.RRC_release_ctrl */ @@ -8708,8 +8755,7 @@ void process_rlc_sdu_indication(int instance, int rnti, int is_successful, int srb_id, - int message_id) -{ + int message_id) { if (is_successful) process_successful_rlc_sdu_indication(instance, rnti, message_id); else @@ -9057,42 +9103,46 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP, unsigned char buffer[8192]; int size; ue_context = rrc_eNB_get_ue_context(RC.rrc[enb_mod_idP], m->rnti); - ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded; - int j=0; - while(j < m->nb_e_rabs_admitted_tobeadded) { - for (int e_rab_idx=0; e_rab_idxue_context.setup_e_rabs; e_rab_idx++) { - //Update ue_context information with gNB's address and new GTP tunnel ID - if( ue_context->ue_context.e_rab[e_rab_idx].param.e_rab_id == m->e_rabs_admitted_tobeadded[j].e_rab_id) { - memcpy(ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].buffer, - m->e_rabs_admitted_tobeadded[j].gnb_addr.buffer, - m->e_rabs_admitted_tobeadded[j].gnb_addr.length); - ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].length = m->e_rabs_admitted_tobeadded[j].gnb_addr.length; - ue_context->ue_context.gnb_gtp_endc_teid[e_rab_idx] = m->e_rabs_admitted_tobeadded[j].gtp_teid; - ue_context->ue_context.e_rab[e_rab_idx].status = E_RAB_STATUS_TOMODIFY; - break; + if (ue_context) { + ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded; + int j=0; + + while(j < m->nb_e_rabs_admitted_tobeadded) { + for (int e_rab_idx=0; e_rab_idxue_context.setup_e_rabs; e_rab_idx++) { + //Update ue_context information with gNB's address and new GTP tunnel ID + if( ue_context->ue_context.e_rab[e_rab_idx].param.e_rab_id == m->e_rabs_admitted_tobeadded[j].e_rab_id) { + memcpy(ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].buffer, + m->e_rabs_admitted_tobeadded[j].gnb_addr.buffer, + m->e_rabs_admitted_tobeadded[j].gnb_addr.length); + ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].length = m->e_rabs_admitted_tobeadded[j].gnb_addr.length; + ue_context->ue_context.gnb_gtp_endc_teid[e_rab_idx] = m->e_rabs_admitted_tobeadded[j].gtp_teid; + ue_context->ue_context.e_rab[e_rab_idx].status = E_RAB_STATUS_TOMODIFY; + break; + } } + + j++; } - j++; + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + 0, + ENB_FLAG_YES, + m->rnti, + 0, 0); + size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf); + rrc_data_req(&ctxt, + DCCH, + rrc_eNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); + } else { + LOG_E(F1AP, "no ue_context for RNTI %x, acknowledging release\n", m->rnti); } - - PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, - 0, - ENB_FLAG_YES, - m->rnti, - 0, 0); - size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf); - rrc_data_req(&ctxt, - DCCH, - rrc_eNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); } - //----------------------------------------------------------------------------- void *rrc_enb_process_itti_msg(void *notUsed) { MessageDef *msg_p; @@ -9427,8 +9477,8 @@ void *rrc_enb_process_itti_msg(void *notUsed) { break; case M2AP_MCE_CONFIGURATION_UPDATE: - rrc_eNB_process_M2AP_MCE_CONFIGURATION_UPDATE(&ctxt,&M2AP_MCE_CONFIGURATION_UPDATE(msg_p)); - break; + rrc_eNB_process_M2AP_MCE_CONFIGURATION_UPDATE(&ctxt,&M2AP_MCE_CONFIGURATION_UPDATE(msg_p)); + break; case RLC_SDU_INDICATION: process_rlc_sdu_indication(instance, @@ -9472,7 +9522,7 @@ rrc_enb_task( //if (go_nr) rrc_go_nr(); } } - } +} /*------------------------------------------------------------------------------*/ void diff --git a/openair2/RRC/LTE/rrc_eNB_M2AP.c b/openair2/RRC/LTE/rrc_eNB_M2AP.c index bd586dfc71..98a72895a0 100644 --- a/openair2/RRC/LTE/rrc_eNB_M2AP.c +++ b/openair2/RRC/LTE/rrc_eNB_M2AP.c @@ -63,6 +63,71 @@ rrc_M2AP_openair_rrc_top_init_MBMS(int eMBMS_active){ } +static uint8_t rrc_M2AP_do_MBSFNCountingRequest( + uint8_t Mod_id, + uint8_t sync_area, + uint8_t *buffer, + LTE_MCCH_Message_t *mcch_message, + LTE_MBMSCountingRequest_r10_t **mbsfnCoutingRequest, + const m2ap_mbms_service_counting_req_t *const m2ap_mbms_service_counting_req +) { + //int i,j,k; + + asn_enc_rval_t enc_rval; + //LTE_MBSFN_SubframeConfig_t *mbsfn_SubframeConfig1; + //LTE_PMCH_Info_r9_t *pmch_Info_1; + //LTE_MBMS_SessionInfo_r9_t *mbms_Session_1; + // MBMS_SessionInfo_r9_t *mbms_Session_2; + //eNB_RRC_INST *rrc = RC.rrc[Mod_id]; + //rrc_eNB_carrier_data_t *carrier = &rrc->carrier[0]; + memset(mcch_message,0,sizeof(LTE_MCCH_Message_t)); + //mcch_message->message.present = LTE_MCCH_MessageType_PR_c1; + mcch_message->message.present = LTE_MCCH_MessageType_PR_later; + //mcch_message->message.choice.c1.present = LTE_MCCH_MessageType__c1_PR_mbsfnAreaConfiguration_r9; + mcch_message->message.choice.later.present = LTE_MCCH_MessageType__later_PR_c2; + mcch_message->message.choice.later.choice.c2.present = LTE_MCCH_MessageType__later__c2_PR_mbmsCountingRequest_r10; + *mbsfnCoutingRequest = &mcch_message->message.choice.later.choice.c2.choice.mbmsCountingRequest_r10; + + + //LTE_CountingRequestList_r10_t countingRequestList_r10; // A_SEQUENCE_OF(struct LTE_CountingRequestInfo_r10) list; + struct LTE_CountingRequestInfo_r10 *lte_counting_request_info; //LTE_TMGI_r9_t tmgi_r10; + lte_counting_request_info = CALLOC(1,sizeof(struct LTE_CountingRequestInfo_r10)); + uint8_t TMGI[5] = {4,3,2,1,0}; + lte_counting_request_info->tmgi_r10.plmn_Id_r9.present = LTE_TMGI_r9__plmn_Id_r9_PR_plmn_Index_r9; + lte_counting_request_info->tmgi_r10.plmn_Id_r9.choice.plmn_Index_r9= 1; + memset(<e_counting_request_info->tmgi_r10.serviceId_r9,0,sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(<e_counting_request_info->tmgi_r10.serviceId_r9,(const char*)&TMGI[2],3); + ASN_SEQUENCE_ADD(&(*mbsfnCoutingRequest)->countingRequestList_r10.list,lte_counting_request_info); + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout,&asn_DEF_LTE_MCCH_Message,(void *)mcch_message); + } + + xer_fprint(stdout,&asn_DEF_LTE_MCCH_Message,(void *)mcch_message); + + enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_MCCH_Message, + NULL, + (void *)mcch_message, + buffer, + 100); + + if(enc_rval.encoded == -1) { + LOG_I(RRC, "[eNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_I(RRC,"[eNB] MCCH Message Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + + if (enc_rval.encoded==-1) { + msg("[RRC] ASN1 : MCCH encoding failed for MBSFNAreaConfiguration\n"); + return(-1); + } + + return((enc_rval.encoded+7)/8); + +} + static uint8_t rrc_M2AP_do_MBSFNAreaConfig( uint8_t Mod_id, @@ -96,6 +161,7 @@ static uint8_t rrc_M2AP_do_MBSFNAreaConfig( mbsfn_SubframeConfig1->radioframeAllocationPeriod= m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_period;//LTE_MBSFN_SubframeConfig__radioframeAllocationPeriod_n4; mbsfn_SubframeConfig1->radioframeAllocationOffset= m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].radioframe_allocation_offset; if(m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].is_four_sf){ + LOG_I(RRC,"is_four_sf\n"); mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames; mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(3); mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[i].mbms_sf_config_list[j].subframe_allocation) & 0xFF); @@ -106,6 +172,7 @@ static uint8_t rrc_M2AP_do_MBSFNAreaConfig( }else { + LOG_I(RRC,"is_one_sf\n"); mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame; mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1); mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1; @@ -128,7 +195,8 @@ static uint8_t rrc_M2AP_do_MBSFNAreaConfig( */ pmch_Info_1->pmch_Config_r9.sf_AllocEnd_r9= m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].allocated_sf_end; pmch_Info_1->pmch_Config_r9.dataMCS_r9= m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].data_mcs; - pmch_Info_1->pmch_Config_r9.mch_SchedulingPeriod_r9= LTE_PMCH_Config_r9__mch_SchedulingPeriod_r9_rf16; + //pmch_Info_1->pmch_Config_r9.mch_SchedulingPeriod_r9= LTE_PMCH_Config_r9__mch_SchedulingPeriod_r9_rf16; + pmch_Info_1->pmch_Config_r9.mch_SchedulingPeriod_r9 = m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].mch_scheduling_period; // MBMSs-SessionInfoList-r9 for(k=0; k < m2ap_mbms_scheduling_information->mbms_area_config_list[i].pmch_config_list[j].num_mbms_session_list; k++){ // pmch_Info_1->mbms_SessionInfoList_r9 = CALLOC(1,sizeof(struct MBMS_SessionInfoList_r9)); @@ -240,6 +308,9 @@ static void rrc_M2AP_init_MCCH( RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE = malloc(RC.rrc[enb_mod_idP]->carrier[CC_id].num_mbsfn_sync_area * sizeof(uint8_t *)); + + RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE_COUNTING = + malloc(RC.rrc[enb_mod_idP]->carrier[CC_id].num_mbsfn_sync_area * sizeof(uint8_t *)); for (sync_area = 0; sync_area < RC.rrc[enb_mod_idP]->carrier[CC_id].num_mbsfn_sync_area; sync_area++) { RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] = 0; @@ -253,6 +324,20 @@ static void rrc_M2AP_init_MCCH( &RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message, m2ap_mbms_scheduling_information ); + + RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE_COUNTING[sync_area] = 0; + RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE_COUNTING[sync_area] = (uint8_t *) malloc16(32); + AssertFatal(RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE_COUNTING[sync_area] != NULL, + "[eNB %d]init_MCCH: FATAL, no memory for MCCH MESSAGE allocated \n", enb_mod_idP); + + RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE_COUNTING[sync_area] = rrc_M2AP_do_MBSFNCountingRequest(enb_mod_idP, + sync_area, + (uint8_t *)RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE_COUNTING[sync_area], + &RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_counting, + &RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message_counting, + NULL//m2ap_mbms_scheduling_information + ); + LOG_I(RRC, "mcch message pointer %p for sync area %d \n", RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESSAGE[sync_area], sync_area); @@ -269,6 +354,8 @@ static void rrc_M2AP_init_MCCH( AssertFatal(RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] != 255, "RC.rrc[enb_mod_idP]->carrier[CC_id].sizeof_MCCH_MESSAGE[sync_area] == 255"); RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESS[sync_area].Active = 1; + + RC.rrc[enb_mod_idP]->carrier[CC_id].MCCH_MESS_COUNTING[sync_area].Active = 1; } @@ -297,17 +384,348 @@ static void rrc_M2AP_init_MCCH( (LTE_MBSFN_AreaInfoList_r9_t *) NULL, (LTE_PMCH_InfoList_r9_t *) & (RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message->pmch_InfoList_r9), (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL, - 0, - (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, - (LTE_SchedulingInfo_MBMS_r14_t *) NULL, - (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, - (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + 0, + (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, + (LTE_SchedulingInfo_MBMS_r14_t *) NULL, + (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, + (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*)(RC.rrc[enb_mod_idP]->carrier[CC_id].mcch_message) ); } return; } + + +static uint8_t rrc_M2AP_do_SIB1_MBMS_SIB13( + const protocol_ctxt_t *const ctxt_pP, + uint8_t Mod_id, + int CC_id, + const m2ap_setup_resp_t *const m2ap_setup_resp, + const m2ap_mbms_scheduling_information_t *const m2ap_mbms_scheduling_information +){ + + int i,j,l; + + eNB_RRC_INST *rrc = RC.rrc[ctxt_pP->module_id]; + rrc_eNB_carrier_data_t *carrier=&rrc->carrier[CC_id]; + + + struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *sib13_part=NULL; + LTE_MBSFN_SubframeConfigList_t *MBSFNSubframeConfigList/*,*MBSFNSubframeConfigList_copy*/; + + asn_enc_rval_t enc_rval; + + LTE_BCCH_DL_SCH_Message_t *bcch_message = &RC.rrc[Mod_id]->carrier[CC_id].systemInformation; + LTE_BCCH_DL_SCH_Message_MBMS_t *bcch_message_fembms = &RC.rrc[Mod_id]->carrier[CC_id].siblock1_MBMS; + uint8_t *buffer; + uint8_t *buffer_fembms; + LTE_SystemInformationBlockType2_t **sib2; + + + LTE_MBSFN_AreaInfoList_r9_t *MBSFNArea_list/*,*MBSFNArea_list_copy*/; + LTE_SystemInformationBlockType13_r9_t **sib13 = &RC.rrc[Mod_id]->carrier[CC_id].sib13; + struct LTE_MBSFN_AreaInfo_r9 *MBSFN_Area1; + + LTE_SystemInformationBlockType1_MBMS_r14_t **sib1_MBMS = &RC.rrc[Mod_id]->carrier[CC_id].sib1_MBMS; + + + + if(ctxt_pP->brOption){ + buffer = RC.rrc[Mod_id]->carrier[CC_id].SIB23_BR; + sib2 = &RC.rrc[Mod_id]->carrier[CC_id].sib2_BR; + LOG_I(RRC,"Running SIB2/3 Encoding for eMTC\n"); + + + }else + { + buffer = RC.rrc[Mod_id]->carrier[CC_id].SIB23; + sib2 = &RC.rrc[Mod_id]->carrier[CC_id].sib2; + } + + buffer_fembms = RC.rrc[Mod_id]->carrier[CC_id].SIB1_MBMS; + + + if (bcch_message) { + //memset(bcch_message,0,sizeof(LTE_BCCH_DL_SCH_Message_t)); + } else { + LOG_E(RRC,"[eNB %d] BCCH_MESSAGE is null, exiting\n", Mod_id); + exit(-1); + } + + if (!sib2) { + LOG_E(RRC,"[eNB %d] sib2 is null, exiting\n", Mod_id); + exit(-1); + } + + if(!sib13){ + LOG_I(RRC,"[eNB %d] sib13 is null, it should get created\n",Mod_id); + } + + + if(!sib1_MBMS){ + LOG_I(RRC,"[eNB %d] sib1_MBMS is null, it should get created\n",Mod_id); + } + + //if (!sib3) { + // LOG_E(RRC,"[eNB %d] sib3 is null, exiting\n", Mod_id); + // exit(-1); + //} + + for (i=0; i < bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count; i++) { + struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo; + typeandinfo = bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i]; + switch(typeandinfo->present) { + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_NOTHING: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920: + *sib13=&typeandinfo->choice.sib13_v920; + (*sib13)->notificationConfig_r9.notificationRepetitionCoeff_r9=LTE_MBMS_NotificationConfig_r9__notificationRepetitionCoeff_r9_n2; + (*sib13)->notificationConfig_r9.notificationOffset_r9=0; + (*sib13)->notificationConfig_r9.notificationSF_Index_r9=1; + // MBSFN-AreaInfoList + MBSFNArea_list= &(*sib13)->mbsfn_AreaInfoList_r9;//CALLOC(1,sizeof(*MBSFNArea_list)); + memset(MBSFNArea_list,0,sizeof(*MBSFNArea_list)); + + for( j=0; j < m2ap_setup_resp->num_mcch_config_per_mbsfn; j++){ + // MBSFN Area 1 + MBSFN_Area1= CALLOC(1, sizeof(*MBSFN_Area1)); + MBSFN_Area1->mbsfn_AreaId_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].mbsfn_area; + MBSFN_Area1->non_MBSFNregionLength= m2ap_setup_resp->mcch_config_per_mbsfn[j].pdcch_length; + MBSFN_Area1->notificationIndicator_r9= 0; + MBSFN_Area1->mcch_Config_r9.mcch_RepetitionPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].repetition_period;//LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__mcch_RepetitionPeriod_r9_rf32; + MBSFN_Area1->mcch_Config_r9.mcch_Offset_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].offset; // in accordance with mbsfn subframe configuration in sib2 + MBSFN_Area1->mcch_Config_r9.mcch_ModificationPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].modification_period; + + // Subframe Allocation Info + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf= MALLOC(1); + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.size= 1; + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf[0]=m2ap_setup_resp->mcch_config_per_mbsfn[j].subframe_allocation_info<<2; // FDD: SF1 + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2; + MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= m2ap_setup_resp->mcch_config_per_mbsfn[j].mcs; + ASN_SEQUENCE_ADD(&MBSFNArea_list->list,MBSFN_Area1); + } + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib14_v1130: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib15_v1130: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib16_v1130: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib17_v1250: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib19_v1250: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib20_v1310: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib21_v1430: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib24_v1530: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib25_v1530: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib26_v1530: + break; + case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2: + + LOG_I(RRC,"Adding MBSFN subframe Configuration 1 to SIB2, %p %p\n",&typeandinfo->choice.sib2,*sib2); + + for(j=0; j < m2ap_mbms_scheduling_information->num_mbms_area_config_list ; j++) { + + (&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList = CALLOC(1,sizeof(struct LTE_MBSFN_SubframeConfigList)); + MBSFNSubframeConfigList = (&typeandinfo->choice.sib2)->mbsfn_SubframeConfigList; + + for(l=0; l < m2ap_mbms_scheduling_information->mbms_area_config_list[j].num_mbms_sf_config_list; l++){ + LTE_MBSFN_SubframeConfig_t *sib2_mbsfn_SubframeConfig1; + sib2_mbsfn_SubframeConfig1= CALLOC(1,sizeof(*sib2_mbsfn_SubframeConfig1)); + memset((void *)sib2_mbsfn_SubframeConfig1,0,sizeof(*sib2_mbsfn_SubframeConfig1)); + + sib2_mbsfn_SubframeConfig1->radioframeAllocationPeriod = m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].radioframe_allocation_period; + sib2_mbsfn_SubframeConfig1->radioframeAllocationOffset = m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].radioframe_allocation_offset; + + + if(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].is_four_sf){ + LOG_I(RRC,"is_four_sf\n"); + sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames; + + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(3); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 3; + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 0; + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation) & 0xFF); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>8) & 0xFF); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>16) & 0xFF); + + }else{ + LOG_I(RRC,"is_one_sf\n"); + sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame; + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1; + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2; + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation<<2); + + + } + + ASN_SEQUENCE_ADD(&MBSFNSubframeConfigList->list,sib2_mbsfn_SubframeConfig1); + } + } + + break; + + } + } + + + if(*sib13==NULL){ + sib13_part = CALLOC(1,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member)); + memset(sib13_part,0,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member)); + sib13_part->present = LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920; + + *sib13 = &sib13_part->choice.sib13_v920; + + (*sib13)->notificationConfig_r9.notificationRepetitionCoeff_r9=LTE_MBMS_NotificationConfig_r9__notificationRepetitionCoeff_r9_n2; + (*sib13)->notificationConfig_r9.notificationOffset_r9=0; + (*sib13)->notificationConfig_r9.notificationSF_Index_r9=1; + + // MBSFN-AreaInfoList + MBSFNArea_list= &(*sib13)->mbsfn_AreaInfoList_r9;//CALLOC(1,sizeof(*MBSFNArea_list)); + memset(MBSFNArea_list,0,sizeof(*MBSFNArea_list)); + + for( i=0; i < m2ap_setup_resp->num_mcch_config_per_mbsfn; i++){ + // MBSFN Area 1 + MBSFN_Area1= CALLOC(1, sizeof(*MBSFN_Area1)); + MBSFN_Area1->mbsfn_AreaId_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].mbsfn_area; + MBSFN_Area1->non_MBSFNregionLength= m2ap_setup_resp->mcch_config_per_mbsfn[i].pdcch_length; + MBSFN_Area1->notificationIndicator_r9= 0; + MBSFN_Area1->mcch_Config_r9.mcch_RepetitionPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].repetition_period;//LTE_MBSFN_AreaInfo_r9__mcch_Config_r9__mcch_RepetitionPeriod_r9_rf32; + MBSFN_Area1->mcch_Config_r9.mcch_Offset_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].offset; // in accordance with mbsfn subframe configuration in sib2 + MBSFN_Area1->mcch_Config_r9.mcch_ModificationPeriod_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].modification_period; + + // Subframe Allocation Info + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf= MALLOC(1); + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.size= 1; + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.buf[0]=m2ap_setup_resp->mcch_config_per_mbsfn[i].subframe_allocation_info<<2; // FDD: SF1 + MBSFN_Area1->mcch_Config_r9.sf_AllocInfo_r9.bits_unused= 2; + MBSFN_Area1->mcch_Config_r9.signallingMCS_r9= m2ap_setup_resp->mcch_config_per_mbsfn[i].mcs; + ASN_SEQUENCE_ADD(&MBSFNArea_list->list,MBSFN_Area1); + } + + ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation.criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list, sib13_part); + + } + + *sib1_MBMS = &bcch_message_fembms->message.choice.c1.choice.systemInformationBlockType1_MBMS_r14; + + + if((*sib1_MBMS)->systemInformationBlockType13_r14==NULL){ + (*sib1_MBMS)->systemInformationBlockType13_r14 = CALLOC(1,sizeof(struct LTE_SystemInformationBlockType13_r9)); + memset((*sib1_MBMS)->systemInformationBlockType13_r14,0,sizeof(struct LTE_SystemInformationBlockType13_r9)); + } + + + memcpy((*sib1_MBMS)->systemInformationBlockType13_r14,*sib13,sizeof(struct LTE_SystemInformationBlockType13_r9)); + + enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message_MBMS, + NULL, + (void *)bcch_message_fembms, + buffer_fembms, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + LOG_I(RRC,"[eNB] MBMS SIB1_MBMS SystemInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + + if (enc_rval.encoded==-1) { + msg("[RRC] ASN1 : SI encoding failed for SIB23\n"); + return(-1); + } + + + + //xer_fprint(stdout, &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message); + + enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_BCCH_DL_SCH_Message, + NULL, + (void *)bcch_message, + buffer, + 900); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + LOG_I(RRC,"[eNB] MBMS SIB2 SystemInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + + if (enc_rval.encoded==-1) { + msg("[RRC] ASN1 : SI encoding failed for SIB23\n"); + return(-1); + } + + carrier->MBMS_flag =1; + + if (NODE_IS_MONOLITHIC(rrc->node_type)) { + rrc_mac_config_req_eNB(ctxt_pP->module_id, CC_id, + 0,0,0,0,0, + 0, + 0xfffd,//rnti + (LTE_BCCH_BCH_Message_t *)NULL, + (LTE_RadioResourceConfigCommonSIB_t *) NULL, + (LTE_RadioResourceConfigCommonSIB_t *) NULL, + (struct LTE_PhysicalConfigDedicated *)NULL, + (LTE_SCellToAddMod_r10_t *)NULL, + //(struct LTE_PhysicalConfigDedicatedSCell_r10 *)NULL, + (LTE_MeasObjectToAddMod_t **) NULL, + (LTE_MAC_MainConfig_t *) NULL, + 0, + (struct LTE_LogicalChannelConfig *)NULL, + (LTE_MeasGapConfig_t *) NULL, + (LTE_TDD_Config_t *) NULL, + (LTE_MobilityControlInfo_t *)NULL, + (LTE_SchedulingInfoList_t *) NULL, + 0, NULL, + (LTE_AdditionalSpectrumEmission_t *)NULL, + (LTE_MBSFN_SubframeConfigList_t *) carrier->sib2->mbsfn_SubframeConfigList, + carrier->MBMS_flag, + (LTE_MBSFN_AreaInfoList_r9_t *) & carrier->sib13->mbsfn_AreaInfoList_r9, + (LTE_PMCH_InfoList_r9_t *) NULL + , + (LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL + , + carrier->FeMBMS_flag, + (LTE_BCCH_DL_SCH_Message_MBMS_t *) NULL, + (LTE_SchedulingInfo_MBMS_r14_t *) NULL, + (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, + (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL + ); + } + + RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_SIB23 = ((enc_rval.encoded+7)/8); + + return 0; +} //static uint8_t rrc_M2AP_do_SIB1( // const protocol_ctxt_t *const ctxt_pP, // uint8_t Mod_id, @@ -501,21 +919,23 @@ static uint8_t rrc_M2AP_do_SIB23_SIB2( if(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].is_four_sf){ + LOG_I(RRC,"is_four_sf\n"); sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames; sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(3); sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 3; sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 0; - sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation) & 0xFF); - sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation>>8) & 0xFF); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation) & 0xFF); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>8) & 0xFF); sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>16) & 0xFF); }else{ + LOG_I(RRC,"is_one_sf\n"); sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame; sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1); sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1; sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2; - sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation<<2); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation<<2); } @@ -580,7 +1000,8 @@ static uint8_t rrc_M2AP_do_SIB23_SIB2( (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL ); } @@ -752,7 +1173,8 @@ for( i=0; i < m2ap_setup_resp->num_mcch_config_per_mbsfn; i++){ (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL ); } @@ -917,20 +1339,22 @@ static uint8_t rrc_M2AP_do_SIB23_SIB2_SIB13( if(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].is_four_sf){ sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames; + LOG_I(RRC,"rrc_M2AP_do_SIB23_SIB2_SIB13 is_four_sf\n"); sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(3); sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 3; sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 0; - sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation) & 0xFF); - sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation>>8) & 0xFF); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[2] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation) & 0xFF); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[1] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>8) & 0xFF); sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0] = ((m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation>>16) & 0xFF); }else{ + LOG_I(RRC,"rrc_M2AP_do_SIB23_SIB2_SIB13 rs_one_sf\n"); sib2_mbsfn_SubframeConfig1->subframeAllocation.present= LTE_MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame; sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf= MALLOC(1); sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.size= 1; sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.bits_unused= 2; - sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[j].subframe_allocation<<2); + sib2_mbsfn_SubframeConfig1->subframeAllocation.choice.oneFrame.buf[0]=(m2ap_mbms_scheduling_information->mbms_area_config_list[j].mbms_sf_config_list[l].subframe_allocation<<2); } @@ -1030,7 +1454,8 @@ static uint8_t rrc_M2AP_do_SIB23_SIB2_SIB13( (LTE_SchedulingInfo_MBMS_r14_t *) NULL, (struct LTE_NonMBSFN_SubframeConfig_r14 *) NULL, (LTE_SystemInformationBlockType1_MBMS_r14_t *) NULL, - (LTE_MBSFN_AreaInfoList_r9_t *) NULL + (LTE_MBSFN_AreaInfoList_r9_t *) NULL, + (LTE_MBSFNAreaConfiguration_r9_t*) NULL ); } @@ -1122,7 +1547,11 @@ rrc_eNB_process_M2AP_MBMS_SESSION_START_REQ( rrc_M2AP_do_SIB23_SIB2(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_mbms_scheduling_information_g); rrc_M2AP_do_SIB23_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp_g); }else{ - rrc_M2AP_do_SIB23_SIB2_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp_g,m2ap_mbms_scheduling_information_g); + if(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].FeMBMS_flag){ + rrc_M2AP_do_SIB1_MBMS_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp_g,m2ap_mbms_scheduling_information_g); + }else{ + rrc_M2AP_do_SIB23_SIB2_SIB13(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_setup_resp_g,m2ap_mbms_scheduling_information_g); + } } rrc_M2AP_init_MCCH(ctxt_pP,ctxt_pP->module_id,CC_id,m2ap_mbms_scheduling_information_g); rrc_M2AP_init_MBMS(ctxt_pP->module_id, CC_id, 0); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index eeb16c3087..9a53a5bbe0 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -379,6 +379,8 @@ typedef struct { NR_BCCH_BCH_Message_t mib; int ssb_SubcarrierOffset; int pdsch_AntennaPorts; + int pusch_TargetSNRx10; + int pucch_TargetSNRx10; NR_BCCH_DL_SCH_Message_t *siblock1; NR_ServingCellConfigCommon_t *servingcellconfigcommon; NR_CellGroupConfig_t *secondaryCellGroup[MAX_NR_RRC_UE_CONTEXTS]; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1f341cfdf9..5721d05aee 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -186,6 +186,8 @@ static void init_NR_SI(gNB_RRC_INST *rrc) { rrc_mac_config_req_gNB(rrc->module_id, rrc->carrier.ssb_SubcarrierOffset, rrc->carrier.pdsch_AntennaPorts, + rrc->carrier.pusch_TargetSNRx10, + rrc->carrier.pucch_TargetSNRx10, (NR_ServingCellConfigCommon_t *)rrc->carrier.servingcellconfigcommon, 0, 0, // WIP hardcoded rnti @@ -265,6 +267,8 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu rrc->carrier.servingcellconfigcommon = configuration->scc; rrc->carrier.ssb_SubcarrierOffset = configuration->ssb_SubcarrierOffset; rrc->carrier.pdsch_AntennaPorts = configuration->pdsch_AntennaPorts; + rrc->carrier.pusch_TargetSNRx10 = configuration->pusch_TargetSNRx10; + rrc->carrier.pucch_TargetSNRx10 = configuration->pucch_TargetSNRx10; /// System Information INIT LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" Checking release \n",PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt)); init_NR_SI(rrc); diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 22e31aa48a..78f39c16d7 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -36,11 +36,34 @@ //#include "NR_UE-CapabilityRAT-ContainerList.h" #include "LTE_UE-CapabilityRAT-ContainerList.h" #include "NR_CG-Config.h" +//#include "NR_SRB-ToAddModList.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h" #include "executables/softmodem-common.h" #include +extern boolean_t nr_rrc_pdcp_config_asn1_req( + const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc + #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 + #endif + ,rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const NR_SRB_ToAddModList_t * const srb2add_listP, + const NR_DRB_ToAddModList_t * const drb2add_listP, + const NR_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) { struct rrc_gNB_ue_context_s *ue_context_p = NULL; @@ -238,10 +261,33 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ rrc_mac_config_req_gNB(rrc->module_id, rrc->carrier.ssb_SubcarrierOffset, rrc->carrier.pdsch_AntennaPorts, + rrc->carrier.pusch_TargetSNRx10, + rrc->carrier.pucch_TargetSNRx10, NULL, 1, // add_ue flag ue_context_p->ue_id_rnti, ue_context_p->ue_context.secondaryCellGroup); + + nr_rrc_pdcp_config_asn1_req( + &ctxt, + (NR_SRB_ToAddModList_t *) NULL, + ue_context_p->ue_context.rb_config->drb_ToAddModList , + ue_context_p->ue_context.rb_config->drb_ToReleaseList, + 0xff, + NULL, + NULL, + NULL, + NULL, + NULL, + ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); + + nr_rrc_rlc_config_asn1_req (&ctxt, + (NR_SRB_ToAddModList_t *) NULL, + ue_context_p->ue_context.rb_config->drb_ToAddModList, + ue_context_p->ue_context.rb_config->drb_ToReleaseList, + (LTE_PMCH_InfoList_r9_t *) NULL, + ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); + } diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index cfaef5072e..5863b8102b 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -66,6 +66,22 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco RLC_BearerConfig->reestablishRLC=calloc(1,sizeof(*RLC_BearerConfig->reestablishRLC)); *RLC_BearerConfig->reestablishRLC=NR_RLC_BearerConfig__reestablishRLC_true; RLC_BearerConfig->rlc_Config=calloc(1,sizeof(*RLC_BearerConfig->rlc_Config)); + +#if 0 + + // RLC UM Bi-directional Bearer configuration + RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_um_Bi_Directional; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional)); + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); + *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + +#else + + // RLC AM Bearer configuration RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; RLC_BearerConfig->rlc_Config->choice.am = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am)); RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); @@ -78,6 +94,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco *RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15; + +#endif + RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters)); RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; @@ -150,9 +169,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions= calloc(1,sizeof(struct NR_CFRA__occasions)); memcpy(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->rach_ConfigGeneric, &servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric, sizeof(NR_RACH_ConfigGeneric_t)); - //secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= calloc(1,sizeof(long)); - //*secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion = NR_CFRA__occasions__ssb_perRACH_Occasion_one; - secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= NULL; + secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion= calloc(1,sizeof(long)); + *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->occasions->ssb_perRACH_Occasion = NR_CFRA__occasions__ssb_perRACH_Occasion_one; secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb; secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb = calloc(1,sizeof(struct NR_CFRA__resources__ssb)); secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0; @@ -948,7 +966,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco srs_res0->resourceMapping.repetitionFactor=NR_SRS_Resource__resourceMapping__repetitionFactor_n1; srs_res0->freqDomainPosition=0; srs_res0->freqDomainShift=0; - srs_res0->freqHopping.c_SRS = 61; + srs_res0->freqHopping.c_SRS = 0; srs_res0->freqHopping.b_SRS=0; srs_res0->freqHopping.b_hop=0; srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither; @@ -2078,7 +2096,7 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; - drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity=5; + drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5; drb_ToAddMod->drb_Identity = 1; drb_ToAddMod->reestablishPDCP = NULL; drb_ToAddMod->recoverPDCP = NULL; diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index 6a037b8ee3..bd77272747 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -116,7 +116,9 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa /* some sanity check - to be refined at some point */ if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n"); - abort(); + // Allow for a gracious exit when we kill first the gNB, then the eNB + //abort(); + return; } x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams; diff --git a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h index 8f2908e52a..18b60aa611 100644 --- a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h +++ b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniLogMgrEntity.h @@ -16,13 +16,13 @@ #include "NwEvt.h" #include "NwLog.h" +#ifndef __NW_MINI_LOG_MGR_H__ +#define __NW_MINI_LOG_MGR_H__ + #ifndef NW_ASSERT #define NW_ASSERT assert #endif -#ifndef __NW_MINI_LOG_MGR_H__ -#define __NW_MINI_LOG_MGR_H__ - extern uint32_t g_log_level; diff --git a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h index b17228c9cf..a1f16ff89b 100644 --- a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h +++ b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniTmrMgrEntity.h @@ -17,13 +17,13 @@ #include "NwEvt.h" #include "NwLog.h" +#ifndef __NW_MINI_TMR_MGR_H__ +#define __NW_MINI_TMR_MGR_H__ + #ifndef NW_ASSERT #define NW_ASSERT assert #endif -#ifndef __NW_MINI_TMR_MGR_H__ -#define __NW_MINI_TMR_MGR_H__ - typedef struct { NwEventT ev; void* timeoutArg; diff --git a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h index 2e19ebbb8e..568c5b0796 100644 --- a/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h +++ b/openair3/GTPV1-U/nw-gtpv1u/test-app/nw-helloworld/NwMiniUdpEntity.h @@ -17,13 +17,13 @@ #include "NwEvt.h" #include "NwLog.h" +#ifndef __NW_MINI_UDP_ENTITY_H__ +#define __NW_MINI_UDP_ENTITY_H__ + #ifndef NW_ASSERT #define NW_ASSERT assert #endif -#ifndef __NW_MINI_UDP_ENTITY_H__ -#define __NW_MINI_UDP_ENTITY_H__ - typedef struct { uint32_t hSocket; NwEventT ev; diff --git a/openair3/M3AP/m3ap_MCE.c b/openair3/M3AP/m3ap_MCE.c index 232b0c0ece..dec9b96897 100644 --- a/openair3/M3AP/m3ap_MCE.c +++ b/openair3/M3AP/m3ap_MCE.c @@ -142,6 +142,20 @@ void m3ap_MCE_handle_sctp_association_resp(instance_t instance, sctp_new_associa sctp_new_association_resp->ulp_cnx_id); //m3ap_handle_m3_setup_message(instance_p, m3ap_enb_data_p, //sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); + sleep(4); + int index; + /* Trying to connect to the provided list of eNB ip address */ + for (index = 0; index < instance_p->nb_m3; index++) { + //M2AP_INFO("eNB[%d] eNB id %u acting as an initiator (client)\n", + // instance_id, instance->eNB_id); + m3ap_MCE_register_MCE(instance_p, + &instance_p->target_mme_m3_ip_address[index], + &instance_p->mme_m3_ip_address, + instance_p->sctp_in_streams, + instance_p->sctp_out_streams, + instance_p->mce_port_for_M3C, + instance_p->multi_sd); + } return; } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index d086c0e13a..778c8165eb 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -90,6 +90,8 @@ typedef enum { USRP_B200_DEV, /*!\brief device is USRP X300/X310*/ USRP_X300_DEV, + /*!\brief device is USRP N300/N310*/ + USRP_N300_DEV, /*!\brief device is BLADE RF*/ BLADERF_DEV, /*!\brief device is LMSSDR (SoDeRa)*/ @@ -104,7 +106,7 @@ typedef enum { UEDv2_DEV, MAX_RF_DEV_TYPE } dev_type_t; -#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2"} +#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","USRP N300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2"} /*!\brief transport protocol types */ typedef enum { @@ -434,6 +436,11 @@ struct openair0_device_t { * \param arg pointer to capabilities or configuration */ int (*trx_write_init)(openair0_device *device); + /* \brief Get internal parameter + * \param id parameter to get + * \return a pointer to the parameter + */ + void *(*get_internal_parameter)(char *id); }; /* type of device init function, implemented in shared lib */ diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index c72e7d4130..1d3c280f0e 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -288,7 +288,7 @@ int ethernet_tune(openair0_device *device, /******************* interface level options *************************/ case MTU_SIZE: /* change MTU of the eth interface */ ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)-1); ifr.ifr_mtu =value; if (ioctl(eth->sockfdd,SIOCSIFMTU,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the MTU"); @@ -298,7 +298,7 @@ int ethernet_tune(openair0_device *device, case TX_Q_LEN: /* change TX queue length of eth interface */ ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)-1); ifr.ifr_qlen =value; if (ioctl(eth->sockfdd,SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the txqueuelen"); diff --git a/targets/ARCH/ETHERNET/benetel/4g/benetel.c b/targets/ARCH/ETHERNET/benetel/4g/benetel.c new file mode 100644 index 0000000000..37f55c689f --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/benetel.c @@ -0,0 +1,386 @@ +/* + * 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 "common_lib.h" +#include "ethernet_lib.h" +#include "shared_buffers.h" +#include "low.h" +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +typedef struct { + eth_state_t e; + shared_buffers buffers; + rru_config_msg_type_t last_msg; + int capabilities_sent; + void *benetel_priv; + char *dpdk_main_command_line; +} benetel_eth_state_t; + +int trx_benetel_start(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + + +void trx_benetel_end(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); +} + + +int trx_benetel_stop(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_freq(openair0_device* device, + openair0_config_t *openair0_cfg, + int exmimo_dump_config) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_gains(openair0_device* device, + openair0_config_t *openair0_cfg) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_get_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_reset_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int ethernet_tune(openair0_device *device, + unsigned int option, + int value) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + +int trx_benetel_write_raw(openair0_device *device, + openair0_timestamp timestamp, + void **buff, int nsamps, int cc, int flags) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +int trx_benetel_read_raw(openair0_device *device, + openair0_timestamp *timestamp, + void **buff, int nsamps, int cc) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +char *msg_type(int t) +{ + static char *s[12] = { + "RAU_tick", + "RRU_capabilities", + "RRU_config", + "RRU_config_ok", + "RRU_start", + "RRU_stop", + "RRU_sync_ok", + "RRU_frame_resynch", + "RRU_MSG_max_num", + "RRU_check_sync", + "RRU_config_update", + "RRU_config_update_ok", + }; + + if (t < 0 || t > 11) return "UNKNOWN"; + return s[t]; +} + +int trx_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + printf(" rru_config_msg->type %d [%s]\n", rru_config_msg->type, + msg_type(rru_config_msg->type)); + + s->last_msg = rru_config_msg->type; + + return msg_len; +} + +int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + if (s->last_msg == RAU_tick && s->capabilities_sent == 0) { + RRU_capabilities_t *cap; + rru_config_msg->type = RRU_capabilities; + rru_config_msg->len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); + cap = (RRU_capabilities_t*)&rru_config_msg->msg[0]; + cap->FH_fmt = OAI_IF4p5_only; + cap->num_bands = 1; + cap->band_list[0] = 7; + cap->nb_rx[0] = 1; + cap->nb_tx[0] = 1; + cap->max_pdschReferenceSignalPower[0] = -27; + cap->max_rxgain[0] = 90; + + s->capabilities_sent = 1; + + return rru_config_msg->len; + } + if (s->last_msg == RRU_config) { + rru_config_msg->type = RRU_config_ok; + return 0; + } + if (s->last_msg == RRU_start) { + s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); + } + /* correct? */ + while (1) pause(); + + return 0; +} + +void benetel_fh_if4p5_south_in(RU_t *ru, + int *frame, + int *subframe) +{ + benetel_eth_state_t *s = ru->ifdevice.priv; + PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB; + LTE_DL_FRAME_PARMS *fp; + int symbol; + int32_t *rxdata; + int antenna = 0; + + lock_ul_buffer(&s->buffers, *subframe); +next: + while (!(s->buffers.ul_busy[*subframe] == 0x3fff || + s->buffers.prach_busy[*subframe] == 1)) + wait_ul_buffer(&s->buffers, *subframe); + if (s->buffers.prach_busy[*subframe] == 1) { + int i; + int antenna = 0; + uint16_t *in; + uint16_t *out; + in = (uint16_t *)s->buffers.prach[*subframe]; + out = (uint16_t *)ru->prach_rxsigF[antenna]; + for (i = 0; i < 840*2; i++) + out[i] = ntohs(in[i]); + s->buffers.prach_busy[*subframe] = 0; + ru->wakeup_prach_eNB(ru->eNB_list[0], ru, *frame, *subframe); + goto next; + } + + eNB = eNB_list[0]; + fp = &eNB->frame_parms; + for (symbol = 0; symbol < 14; symbol++) { + int i; + uint16_t *p = (uint16_t *)(&s->buffers.ul[*subframe][symbol*1200*4]); + for (i = 0; i < 1200*2; i++) { + p[i] = htons(p[i]); + } + rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size]; +#if 1 + memcpy(rxdata + 2048 - 600, + &s->buffers.ul[*subframe][symbol*1200*4], + 600 * 4); + memcpy(rxdata, + &s->buffers.ul[*subframe][symbol*1200*4] + 600*4, + 600 * 4); +#endif + } + + s->buffers.ul_busy[*subframe] = 0; + signal_ul_buffer(&s->buffers, *subframe); + unlock_ul_buffer(&s->buffers, *subframe); + + //printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *subframe); + + RU_proc_t *proc = &ru->proc; + extern uint16_t sf_ahead; + int f = *frame; + int sf = *subframe; + + //calculate timestamp_rx, timestamp_tx based on frame and subframe + proc->tti_rx = sf; + proc->frame_rx = f; + proc->timestamp_rx = ((proc->frame_rx * 10) + proc->tti_rx ) * fp->samples_per_tti ; + + if (get_nprocs()<=4) { + proc->tti_tx = (sf+sf_ahead)%10; + proc->frame_tx = (sf>(9-sf_ahead)) ? (f+1)&1023 : f; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,f); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,sf); + proc->symbol_mask[sf] = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff); + +} + +void benetel_fh_if4p5_south_out(RU_t *ru, + int frame, + int subframe, + uint64_t timestamp) +{ + benetel_eth_state_t *s = ru->ifdevice.priv; + PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB; + LTE_DL_FRAME_PARMS *fp; + int symbol; + int32_t *txdata; + int aa = 0; + + //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, subframe, timestamp); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + + lock_dl_buffer(&s->buffers, subframe); + if (s->buffers.dl_busy[subframe]) { + printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, subframe); + unlock_dl_buffer(&s->buffers, subframe); + return; + } + eNB = eNB_list[0]; + fp = &eNB->frame_parms; + if (ru->num_eNB != 1 || ru->nb_tx != 1 || fp->ofdm_symbol_size != 2048 || + fp->Ncp != NORMAL || fp->symbols_per_tti != 14) { + printf("%s:%d:%s: unsupported configuration\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + for (symbol = 0; symbol < 14; symbol++) { + txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size]; +#if 1 + memcpy(&s->buffers.dl[subframe][symbol*1200*4], + txdata + 2048 - 600, + 600 * 4); + memcpy(&s->buffers.dl[subframe][symbol*1200*4] + 600*4, + txdata + 1, + 600 * 4); +#endif + int i; + uint16_t *p = (uint16_t *)(&s->buffers.dl[subframe][symbol*1200*4]); + for (i = 0; i < 1200*2; i++) { + p[i] = htons(p[i]); + } + } + + s->buffers.dl_busy[subframe] = 0x3fff; + unlock_dl_buffer(&s->buffers, subframe); + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.frame_tx); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.tti_tx); + +} + +void *get_internal_parameter(char *name) +{ + printf("BENETEL: %s\n", __FUNCTION__); + + if (!strcmp(name, "fh_if4p5_south_in")) + return benetel_fh_if4p5_south_in; + if (!strcmp(name, "fh_if4p5_south_out")) + return benetel_fh_if4p5_south_out; + + return NULL; +} + +__attribute__((__visibility__("default"))) +int transport_init(openair0_device *device, + openair0_config_t *openair0_cfg, + eth_params_t * eth_params ) +{ + benetel_eth_state_t *eth; + + printf("BENETEL: %s\n", __FUNCTION__); + + device->Mod_id = 0; + device->transp_type = ETHERNET_TP; + device->trx_start_func = trx_benetel_start; + device->trx_get_stats_func = trx_benetel_get_stats; + device->trx_reset_stats_func = trx_benetel_reset_stats; + device->trx_end_func = trx_benetel_end; + device->trx_stop_func = trx_benetel_stop; + device->trx_set_freq_func = trx_benetel_set_freq; + device->trx_set_gains_func = trx_benetel_set_gains; + + device->trx_write_func = trx_benetel_write_raw; + device->trx_read_func = trx_benetel_read_raw; + + device->trx_ctlsend_func = trx_benetel_ctlsend; + device->trx_ctlrecv_func = trx_benetel_ctlrecv; + + device->get_internal_parameter = get_internal_parameter; + + eth = calloc(1, sizeof(benetel_eth_state_t)); + if (eth == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->e.flags = ETH_RAW_IF4p5_MODE; + eth->e.compression = NO_COMPRESS; + eth->e.if_name = eth_params->local_if_name; + device->priv = eth; + device->openair0_cfg=&openair0_cfg[0]; + + if (openair0_cfg->sdr_addrs == NULL) { + printf("benetel: fatal: sdr_addrs not set in configuration file\n"); + exit(1); + } + + eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs); + if (eth->dpdk_main_command_line == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->last_msg = -1; + + init_buffers(ð->buffers); + + return 0; +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c b/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c new file mode 100644 index 0000000000..9b64f01d44 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/dpdk_driver.c @@ -0,0 +1,787 @@ +/* license: to be defined */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "low.h" + +// HEADER DEFINITION +#define ANT_NUM buf[23] +#define PAYLOAD_1 buf[20] +#define PAYLOAD_2 buf[21] +#define ETH_TYPE buf[17] +#define SYMBOL buf[29] +#define SUBFRAME buf[28] +#define FRAME buf[27] + +static volatile bool force_quit; + +unsigned short iq[33600]; +unsigned char iq_swap[67200]; + +unsigned short *iq_ptr[14]; +unsigned int dl_start = 0; + +/* MAC updating enabled by default */ +static int mac_updating = 1; +#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 +#define MAX_PKT_BURST 32 +#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */ +#define MEMPOOL_CACHE_SIZE 256 +/* + * Configurable number of RX/TX ring descriptors + */ +#define RTE_TEST_RX_DESC_DEFAULT 1024 +#define RTE_TEST_TX_DESC_DEFAULT 1024 +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; +/* ethernet addresses of ports */ +static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; +/* mask of enabled ports */ +static uint32_t l2fwd_enabled_port_mask = 0; +/* list of enabled ports */ +static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; +static unsigned int l2fwd_rx_queue_per_lcore = 1; +#define MAX_RX_QUEUE_PER_LCORE 16 +#define MAX_TX_QUEUE_PER_PORT 16 +struct lcore_queue_conf { + unsigned n_rx_port; + unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; +} __rte_cache_aligned; +struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; +static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; +static struct rte_eth_conf port_conf = { + .rxmode = { + .split_hdr_size = 0, + .offloads = DEV_RX_OFFLOAD_CRC_STRIP, + .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME, + .split_hdr_size = 0, + .max_rx_pkt_len = 9500, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; +struct rte_mempool * l2fwd_pktmbuf_pool = NULL; +/* Per-port statistics struct */ +struct l2fwd_port_statistics { + uint64_t tx; + uint64_t rx; + uint64_t dropped; +} __rte_cache_aligned; +struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; +#define MAX_TIMER_PERIOD 86400 /* 1 day max */ +/* A tsc-based timer responsible for triggering statistics printout */ +static uint64_t timer_period = 10; /* default period is 10 seconds */ +/* Print out statistics on packets dropped */ +static void +print_stats(void) +{ + uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; + unsigned portid; + total_packets_dropped = 0; + total_packets_tx = 0; + total_packets_rx = 0; + const char clr[] = { 27, '[', '2', 'J', '\0' }; + const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + printf("\nPort statistics ===================================="); + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { + /* skip disabled ports */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("\nStatistics for port %u ------------------------------" + "\nPackets sent: %24"PRIu64 + "\nPackets received: %20"PRIu64 + "\nPackets dropped: %21"PRIu64, + portid, + port_statistics[portid].tx, + port_statistics[portid].rx, + port_statistics[portid].dropped); + total_packets_dropped += port_statistics[portid].dropped; + total_packets_tx += port_statistics[portid].tx; + total_packets_rx += port_statistics[portid].rx; + } + printf("\nAggregate statistics ===============================" + "\nTotal packets sent: %18"PRIu64 + "\nTotal packets received: %14"PRIu64 + "\nTotal packets dropped: %15"PRIu64, + total_packets_tx, + total_packets_rx, + total_packets_dropped); + printf("\n====================================================\n"); +} +static void +l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs) +{ + unsigned char *buf, *buf_tx; + unsigned int len; + struct ether_hdr *eth; + + unsigned dst_port; + int sent, prach_ctrl = 0; + struct rte_eth_dev_tx_buffer *buffer; + + unsigned char * IQ_ptr; + + ul_packet_t p; + + buf = rte_pktmbuf_mtod(m, unsigned char *); + //rte_memdump(stdout, "Rx Packet",buf ,34); + eth = rte_pktmbuf_mtod(m, struct ether_hdr *); + len = rte_pktmbuf_data_len(m); + + IQ_ptr = &buf[34]; + + //destination mac address (RRU MAC) + eth->d_addr.addr_bytes[0] = 0x02; + eth->d_addr.addr_bytes[1] = 0x00; + eth->d_addr.addr_bytes[2] = 0x5e; + eth->d_addr.addr_bytes[3] = 0x01; + eth->d_addr.addr_bytes[4] = 0x01; + eth->d_addr.addr_bytes[5] = 0x01; + + //source mac address (DU MAC) + eth->s_addr.addr_bytes[0] = 0xdd; + eth->s_addr.addr_bytes[1] = 0xdd; + eth->s_addr.addr_bytes[2] = 0xdd; + eth->s_addr.addr_bytes[3] = 0xdd; + eth->s_addr.addr_bytes[4] = 0xdd; + eth->s_addr.addr_bytes[5] = 0xdd; + + dst_port = l2fwd_dst_ports[portid]; + #if 1 + + if (buf[18] == 0xAA) //msg1 check + { + printf("\nHandshake MSG 1 Received\n"); + printf("\n====================================================\n"); + + buf[18] = 0xBB;//change to msg2 after receive msg1 + + printf("Handshake MSG 2 Sent\n"); + printf("\n====================================================\n"); + } + + #else + // Handshake Condition + if (buf[18] == 0x01 || buf[18] == 0x03) // ORAN handshake msgs. + { + if (buf[18] == 0x01) //msg1 check + { + printf("\nHandshake MSG 1 Received\n"); + printf("\n====================================================\n"); + + buf[18] = 0x02;//change to msg2 after receive msg1 + + printf("Handshake MSG 2 Sent\n"); + printf("\n====================================================\n"); + } + + else if(buf[18] == 0x03) //msg3 check + { + printf("Handshake MSG 3 Sent\n"); + printf("\n====================================================\n"); + + buf[18] = 0x04; + + printf("Handshake MSG 4 Sent\n"); + printf("\n====================================================\n"); + } + } + #endif + // Trigger start send DL packets + if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && SYMBOL == 0x09 && ANT_NUM == 0x00 && dl_start == 0){ + + printf("\nU-Plane Started\n"); + printf("\n====================================================\n"); + + dl_start = 1; + } + + + if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x00) { + p.frame = FRAME; + p.subframe = SUBFRAME >> 4; + p.slot = 0; /* unused */ + p.symbol = SYMBOL; + p.antenna = 0; + memcpy(p.iq, IQ_ptr, 4800); + store_ul(bs, &p); + } + + // U-PLANE UL ANT_0 PROCESSING + if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x00 && dl_start == 1) + { + int tx_frame = FRAME; + int tx_subframe = SUBFRAME >> 4; + int tx_symbol = SYMBOL + 5; + if (tx_symbol > 13) { + tx_symbol -= 14; + tx_subframe++; + if (tx_subframe == 10) { + tx_subframe = 0; + tx_frame = (tx_frame + 1) & 255; + } + } + +// ANT_NUM = 0x00; +// SYMBOL = (SYMBOL + 5) % 14; + PAYLOAD_2 = 0xc8; + + FRAME = tx_frame; + SUBFRAME = tx_subframe << 4; + SYMBOL = tx_symbol; + + /* antenna 0 - send actual DL data (if available) */ + lock_dl_buffer(bs->buffers, tx_subframe); + if (!(bs->buffers->dl_busy[tx_subframe] & (1 << tx_symbol))) { + printf("%s: warning, DL underflow (sf.symbol %d.%d)\n", __FUNCTION__, + tx_subframe, tx_symbol); + memset(IQ_ptr, 0, 1200 * 4); + } else { + memcpy(IQ_ptr, bs->buffers->dl[tx_subframe] + tx_symbol * 1200*4, + 1200*4); + } + bs->buffers->dl_busy[tx_subframe] &= ~(1 << tx_symbol); + unlock_dl_buffer(bs->buffers, tx_subframe); + + // fill DL Data for ant 0 with 0 value +// memset(IQ_ptr, 0, 4800); + } + + // U-PLANE UL ANT_1 PROCESSING + else if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x01 && dl_start == 1) + { + +// ANT_NUM = 0x01; + SYMBOL = (SYMBOL + 5) % 14; + PAYLOAD_2 = 0xc8; + + // fill DL Data for ant 1 with 0 value + memset(IQ_ptr, 0, 4800); + } + + // U-PLANE PRACH PROCESSING + else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){ + if (ANT_NUM == 0) { + store_prach(bs, FRAME, SUBFRAME>>4, IQ_ptr); + } + + rte_pktmbuf_free(m); + return; + } + + // Send Packets + buffer = tx_buffer[dst_port]; + + sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); + + if (sent) + port_statistics[dst_port].tx += sent; + +} +/* main processing loop */ +static void +l2fwd_main_loop(benetel_t *bs) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_mbuf *m; + int sent; + unsigned lcore_id; + uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; + unsigned i, j, portid, nb_rx; + struct lcore_queue_conf *qconf; + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * + BURST_TX_DRAIN_US; + struct rte_eth_dev_tx_buffer *buffer; + prev_tsc = 0; + timer_tsc = 0; + lcore_id = rte_lcore_id(); + qconf = &lcore_queue_conf[lcore_id]; + if (qconf->n_rx_port == 0) { + RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); + return; + } + RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, + portid); + } + while (!force_quit) { + cur_tsc = rte_rdtsc(); + /* + * TX burst queue drain + */ + diff_tsc = cur_tsc - prev_tsc; + if (unlikely(diff_tsc > drain_tsc)) { + for (i = 0; i < qconf->n_rx_port; i++) { + portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; + buffer = tx_buffer[portid]; + sent = rte_eth_tx_buffer_flush(portid, 0, buffer); + if (sent) + port_statistics[portid].tx += sent; + } + /* if timer is enabled */ + if (timer_period > 0) { + /* advance the timer */ + timer_tsc += diff_tsc; + /* if timer has reached its timeout */ + if (unlikely(timer_tsc >= timer_period)) { + /* do this only on master core */ + if (lcore_id == rte_get_master_lcore()) { + //print_stats(); + /* reset the timer */ + timer_tsc = 0; + } + } + } + prev_tsc = cur_tsc; + } + /* + * Read packet from RX queues + */ + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + nb_rx = rte_eth_rx_burst(portid, 0, + pkts_burst, MAX_PKT_BURST); + port_statistics[portid].rx += nb_rx; + for (j = 0; j < nb_rx; j++) { + m = pkts_burst[j]; + rte_prefetch0(rte_pktmbuf_mtod(m, void *)); + l2fwd_simple_forward(m, portid, bs); + } + } + } +} +static int +l2fwd_launch_one_lcore(void *bs) +{ + l2fwd_main_loop(bs); + return 0; +} +/* display usage */ +static void +l2fwd_usage(const char *prgname) +{ + printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" + " -p PORTMASK: hexadecimal bitmask of ports to configure\n" + " -q NQ: number of queue (=ports) per lcore (default is 1)\n" + " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" + " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n" + " When enabled:\n" + " - The source MAC address is replaced by the TX port MAC address\n" + " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n", + prgname); +} +static int +l2fwd_parse_portmask(const char *portmask) +{ + char *end = NULL; + unsigned long pm; + /* parse hexadecimal string */ + pm = strtoul(portmask, &end, 16); + if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (pm == 0) + return -1; + return pm; +} +static unsigned int +l2fwd_parse_nqueue(const char *q_arg) +{ + char *end = NULL; + unsigned long n; + /* parse hexadecimal string */ + n = strtoul(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return 0; + if (n == 0) + return 0; + if (n >= MAX_RX_QUEUE_PER_LCORE) + return 0; + return n; +} +static int +l2fwd_parse_timer_period(const char *q_arg) +{ + char *end = NULL; + int n; + /* parse number string */ + n = strtol(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (n >= MAX_TIMER_PERIOD) + return -1; + return n; +} +static const char short_options[] = + "p:" /* portmask */ + "q:" /* number of queues */ + "T:" /* timer period */ + ; +#define CMD_LINE_OPT_MAC_UPDATING "mac-updating" +#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating" +enum { + /* long options mapped to a short option */ + /* first long only option value must be >= 256, so that we won't + * conflict with short options */ + CMD_LINE_OPT_MIN_NUM = 256, +}; +static const struct option lgopts[] = { + { CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1}, + { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0}, + {NULL, 0, 0, 0} +}; +/* Parse the argument given in the command line of the application */ +static int +l2fwd_parse_args(int argc, char **argv) +{ + int opt, ret, timer_secs; + char **argvopt; + int option_index; + char *prgname = argv[0]; + argvopt = argv; + while ((opt = getopt_long(argc, argvopt, short_options, + lgopts, &option_index)) != EOF) { + switch (opt) { + /* portmask */ + case 'p': + l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); + if (l2fwd_enabled_port_mask == 0) { + printf("invalid portmask\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* nqueue */ + case 'q': + l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); + if (l2fwd_rx_queue_per_lcore == 0) { + printf("invalid queue number\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* timer period */ + case 'T': + timer_secs = l2fwd_parse_timer_period(optarg); + if (timer_secs < 0) { + printf("invalid timer period\n"); + l2fwd_usage(prgname); + return -1; + } + timer_period = timer_secs; + break; + /* long options */ + case 0: + break; + default: + l2fwd_usage(prgname); + return -1; + } + } + if (optind >= 0) + argv[optind-1] = prgname; + ret = optind-1; + optind = 1; /* reset getopt lib */ + return ret; +} +/* Check the link status of all ports in up to 9s, and print them finally */ +static void +check_all_ports_link_status(uint32_t port_mask) +{ +#define CHECK_INTERVAL 100 /* 100ms */ +#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ + uint16_t portid; + uint8_t count, all_ports_up, print_flag = 0; + struct rte_eth_link link; + printf("\nChecking link status"); + fflush(stdout); + for (count = 0; count <= MAX_CHECK_TIME; count++) { + if (force_quit) + return; + all_ports_up = 1; + RTE_ETH_FOREACH_DEV(portid) { + if (force_quit) + return; + if ((port_mask & (1 << portid)) == 0) + continue; + memset(&link, 0, sizeof(link)); + rte_eth_link_get_nowait(portid, &link); + /* print link status if flag set */ + if (print_flag == 1) { + if (link.link_status) + printf( + "Port%d Link Up. Speed %u Mbps - %s\n", + portid, link.link_speed, + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + ("full-duplex") : ("half-duplex\n")); + else + printf("Port %d Link Down\n", portid); + continue; + } + /* clear all_ports_up flag if any link down */ + if (link.link_status == ETH_LINK_DOWN) { + all_ports_up = 0; + break; + } + } + /* after finally printing all link status, get out */ + if (print_flag == 1) + break; + if (all_ports_up == 0) { + printf("."); + fflush(stdout); + rte_delay_ms(CHECK_INTERVAL); + } + /* set the print_flag if all ports up or timeout */ + if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { + print_flag = 1; + printf("done\n"); + } + } +} +static void +signal_handler(int signum) +{ + if (signum == SIGINT || signum == SIGTERM) { + printf("\n\nSignal %d received, preparing to exit...\n", + signum); + force_quit = true; + } +} +int +dpdk_main(int argc, char **argv, benetel_t *bs) +{ + struct lcore_queue_conf *qconf; + int ret; + uint16_t nb_ports; + uint16_t nb_ports_available = 0; + uint16_t portid, last_port; + unsigned lcore_id, rx_lcore_id; + unsigned nb_ports_in_mask = 0; + unsigned int nb_lcores = 0; + unsigned int nb_mbufs; + /* init EAL */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); + argc -= ret; + argv += ret; + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + /* parse application arguments (after the EAL ones) */ + ret = l2fwd_parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); + printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled"); + /* convert to number of cycles */ + timer_period *= rte_get_timer_hz(); + nb_ports = rte_eth_dev_count_avail(); + if (nb_ports == 0) + rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); + /* check port mask to possible port mask */ + if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1)) + rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n", + (1 << nb_ports) - 1); + /* reset l2fwd_dst_ports */ + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) + l2fwd_dst_ports[portid] = 0; + last_port = 0; + /* + * Each logical core is assigned a dedicated TX queue on each port. + */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + if (nb_ports_in_mask % 2) { + l2fwd_dst_ports[portid] = last_port; + l2fwd_dst_ports[last_port] = portid; + } + else + last_port = portid; + nb_ports_in_mask++; + } + if (nb_ports_in_mask % 2) { + printf("Notice: odd number of ports in portmask.\n"); + l2fwd_dst_ports[last_port] = last_port; + } + rx_lcore_id = 0; + qconf = NULL; + /* Initialize the port/queue configuration of each logical core */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + /* get the lcore_id for this port */ + while (rte_lcore_is_enabled(rx_lcore_id) == 0 || + lcore_queue_conf[rx_lcore_id].n_rx_port == + l2fwd_rx_queue_per_lcore) { + rx_lcore_id++; + if (rx_lcore_id >= RTE_MAX_LCORE) + rte_exit(EXIT_FAILURE, "Not enough cores\n"); + } + if (qconf != &lcore_queue_conf[rx_lcore_id]) { + /* Assigned a new logical core in the loop above. */ + qconf = &lcore_queue_conf[rx_lcore_id]; + nb_lcores++; + } + qconf->rx_port_list[qconf->n_rx_port] = portid; + qconf->n_rx_port++; + printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); + } + nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + + nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); + /* create the mbuf pool */ + l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs, + MEMPOOL_CACHE_SIZE, 0, 9680, + rte_socket_id()); + if (l2fwd_pktmbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); + /* Initialise each port */ + RTE_ETH_FOREACH_DEV(portid) { + struct rte_eth_rxconf rxq_conf; + struct rte_eth_txconf txq_conf; + struct rte_eth_conf local_port_conf = port_conf; + struct rte_eth_dev_info dev_info; + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { + printf("Skipping disabled port %u\n", portid); + continue; + } + nb_ports_available++; + /* init port */ + printf("Initializing port %u... ", portid); + fflush(stdout); + rte_eth_dev_info_get(portid, &dev_info); + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) + local_port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_MBUF_FAST_FREE; + ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", + ret, portid); + ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, + &nb_txd); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot adjust number of descriptors: err=%d, port=%u\n", + ret, portid); + rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); + /* init one RX queue */ + fflush(stdout); + rxq_conf = dev_info.default_rxconf; + rxq_conf.offloads = local_port_conf.rxmode.offloads; + ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, + rte_eth_dev_socket_id(portid), + &rxq_conf, + l2fwd_pktmbuf_pool); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* init one TX queue on each port */ + fflush(stdout); + txq_conf = dev_info.default_txconf; + txq_conf.offloads = local_port_conf.txmode.offloads; + ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, + rte_eth_dev_socket_id(portid), + &txq_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* Initialize TX buffers */ + tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", + RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, + rte_eth_dev_socket_id(portid)); + if (tx_buffer[portid] == NULL) + rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", + portid); + rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); + ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], + rte_eth_tx_buffer_count_callback, + &port_statistics[portid].dropped); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot set error callback for tx buffer on port %u\n", + portid); + /* Start device */ + ret = rte_eth_dev_start(portid); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", + ret, portid); + printf("done: \n"); + rte_eth_promiscuous_enable(portid); + printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", + portid, + l2fwd_ports_eth_addr[portid].addr_bytes[0], + l2fwd_ports_eth_addr[portid].addr_bytes[1], + l2fwd_ports_eth_addr[portid].addr_bytes[2], + l2fwd_ports_eth_addr[portid].addr_bytes[3], + l2fwd_ports_eth_addr[portid].addr_bytes[4], + l2fwd_ports_eth_addr[portid].addr_bytes[5]); + /* initialize port stats */ + memset(&port_statistics, 0, sizeof(port_statistics)); + } + if (!nb_ports_available) { + rte_exit(EXIT_FAILURE, + "All available ports are disabled. Please set portmask.\n"); + } + check_all_ports_link_status(l2fwd_enabled_port_mask); + ret = 0; + /* launch per-lcore init on every lcore */ + rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER); + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (rte_eal_wait_lcore(lcore_id) < 0) { + ret = -1; + break; + } + } + RTE_ETH_FOREACH_DEV(portid) { + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rte_eth_dev_stop(portid); + rte_eth_dev_close(portid); + printf(" Done\n"); + } + printf("Bye...\n"); + return ret; +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/low.c b/targets/ARCH/ETHERNET/benetel/4g/low.c new file mode 100644 index 0000000000..038592d596 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/low.c @@ -0,0 +1,95 @@ +/* + * 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 "low.h" + +#include +#include +#include + +void store_ul(benetel_t *bs, ul_packet_t *ul) +{ + /* only antenna 0 for the moment */ + if (ul->antenna != 0) + return; + + if (ul->subframe != bs->next_subframe || + ul->symbol != bs->next_symbol) { + printf("%s: fatal, expected frame.sf.symbol %d.%d.%d, got %d.%d.%d\n", + __FUNCTION__, + bs->expected_benetel_frame, bs->next_subframe, bs->next_symbol, + ul->frame, ul->subframe, ul->symbol); + exit(1); + } + + lock_ul_buffer(bs->buffers, bs->next_subframe); + if (bs->buffers->ul_busy[bs->next_subframe] & (1 << bs->next_symbol)) { + printf("%s: warning, UL overflow (sf.symbol %d.%d)\n", __FUNCTION__, + bs->next_subframe, bs->next_symbol); + } + memcpy(bs->buffers->ul[bs->next_subframe] + bs->next_symbol * 1200*4, + ul->iq, 1200*4); + bs->buffers->ul_busy[bs->next_subframe] |= (1 << bs->next_symbol); + signal_ul_buffer(bs->buffers, bs->next_subframe); + unlock_ul_buffer(bs->buffers, bs->next_subframe); + + bs->next_symbol++; + if (bs->next_symbol == 14) { + bs->next_symbol = 0; + bs->next_subframe = (bs->next_subframe + 1) % 10; + if (bs->next_subframe == 0) { + bs->expected_benetel_frame++; + bs->expected_benetel_frame &= 255; + } + } +} + +void store_prach(benetel_t *bs, int frame, int subframe, void *data) +{ + static int last_frame = -1; + static int last_subframe = -1; + /* hack: antenna number is always 0, discard second packet with same f/sf */ + if (frame == last_frame && subframe == last_subframe) return; + last_frame = frame; + last_subframe = subframe; + + lock_ul_buffer(bs->buffers, subframe); + if (bs->buffers->prach_busy[subframe]) { + printf("store_prach: fatal: previous prach buffer not processed\n"); + unlock_ul_buffer(bs->buffers, subframe); + return; + } + bs->buffers->prach_busy[subframe] = 1; + memcpy(bs->buffers->prach[subframe], data, 849*4); + signal_ul_buffer(bs->buffers, subframe); + unlock_ul_buffer(bs->buffers, subframe); + +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); + +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + if (!strcmp(ifname, "dpdk")) + return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line); + printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname); + exit(1); +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/low.h b/targets/ARCH/ETHERNET/benetel/4g/low.h new file mode 100644 index 0000000000..5e75d9181e --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/low.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.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _BENETEL_4G_LOW_H_ +#define _BENETEL_4G_LOW_H_ + +#include "shared_buffers.h" + +typedef struct { + shared_buffers *buffers; + int next_subframe; + int next_symbol; + int expected_benetel_frame; + char *dpdk_main_command_line; +} benetel_t; + +typedef struct { + int frame; + int subframe; + int slot; + int symbol; + int antenna; + unsigned char iq[4800]; +} ul_packet_t; + +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); + +void store_ul(benetel_t *bs, ul_packet_t *ul); +void store_prach(benetel_t *bs, int frame, int subframe, void *data); + +#endif /* _BENETEL_4G_LOW_H_ */ diff --git a/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c b/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c new file mode 100644 index 0000000000..ecff473010 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/low_dpdk.c @@ -0,0 +1,118 @@ +/* + * 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 + */ + +/* those 2 lines for CPU_SET */ +#define _GNU_SOURCE +#include + +#include +#include +#include +#include + +#include "low.h" + +int dpdk_main(int argc, char **argv, benetel_t *); + +void *dpdk_thread(void *_bs) +{ + benetel_t *bs = _bs; + int n = 0; + char **v = NULL; // { "softmodem", "-n", "2", "-l", "8", "--", "-p", "0x2" }; + char *s = bs->dpdk_main_command_line; + char *tok; + + while ((tok = strtok(s, " ")) != NULL) { + n++; + v = realloc(v, n * sizeof(char *)); + if (v == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + v[n-1] = tok; + s = NULL; + } + + dpdk_main(n, v, bs); + exit(1); + return 0; +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + benetel_t *bs; + + bs = calloc(1, sizeof(benetel_t)); + if (bs == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + + bs->buffers = buffers; + + bs->expected_benetel_frame = 255; + + bs->dpdk_main_command_line = dpdk_main_command_line; + + pthread_attr_t attr; + + if (pthread_attr_init(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(12,&cpuset); + if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) { + printf("pthread_attr_setaffinity_np failed\n"); + exit(1); + } + + if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { + printf("pthread_attr_setschedpolicy failed\n"); + exit(1); + } + + struct sched_param params; + params.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_get_priority_max(SCHED_FIFO) == -1) { + printf("sched_get_priority_max failed\n"); + exit(1); + } + if (pthread_attr_setschedparam(&attr, ¶ms) != 0) { + printf("pthread_setschedparam failed\n"); + exit(1); + } + + pthread_t t; + if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) { + printf("%s: thread creation failed\n", __FUNCTION__); + exit(1); + } + + if (pthread_attr_destroy(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + return bs; +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c new file mode 100644 index 0000000000..492a15dfc3 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.c @@ -0,0 +1,114 @@ +/* + * 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 "shared_buffers.h" + +#include +#include +#include + +void init_buffers(shared_buffers *s) +{ + int subframe; + + memset(s, 0, sizeof(*s)); + + for (subframe = 0; subframe < 10; subframe++) { + if (pthread_mutex_init(&s->m_dl[subframe], NULL) != 0 || + pthread_cond_init(&s->c_dl[subframe], NULL) != 0 || + pthread_mutex_init(&s->m_ul[subframe], NULL) != 0 || + pthread_cond_init(&s->c_ul[subframe], NULL) != 0) { + printf("%s: error initializing mutex/cond\n", __FUNCTION__); + exit(1); + } + } + + /* in FDD the eNB's first transmitted DL subframe is 4 but the device + * needs to have subframes 1, 2 and 3 ready. Let's pretend there are ready. + */ + s->dl_busy[1] = 0x3fff; + s->dl_busy[2] = 0x3fff; + s->dl_busy[3] = 0x3fff; +} + +void lock_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_lock(&s->m_dl[subframe]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + exit(1); + } +} + +void unlock_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_unlock(&s->m_dl[subframe]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_wait(&s->c_dl[subframe], &s->m_dl[subframe]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_dl_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_broadcast(&s->c_dl[subframe]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} + +void lock_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_lock(&s->m_ul[subframe]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + exit(1); + } +} + +void unlock_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_mutex_unlock(&s->m_ul[subframe]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_wait(&s->c_ul[subframe], &s->m_ul[subframe]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_ul_buffer(shared_buffers *s, int subframe) +{ + if (pthread_cond_broadcast(&s->c_ul[subframe]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} diff --git a/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h new file mode 100644 index 0000000000..1d5040b95b --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/4g/shared_buffers.h @@ -0,0 +1,60 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _BENETEL_4G_SHARED_BUFFERS_H_ +#define _BENETEL_4G_SHARED_BUFFERS_H_ + +#include +#include + +typedef struct { + unsigned char dl[10][14*1200*4]; + unsigned char ul[10][14*1200*4]; + uint16_t dl_busy[10]; + uint16_t ul_busy[10]; + + pthread_mutex_t m_ul[10]; + pthread_cond_t c_ul[10]; + + pthread_mutex_t m_dl[10]; + pthread_cond_t c_dl[10]; + + unsigned char prach[10][849*4]; + unsigned char prach_busy[10]; + + /* statistics/error counting */ + int ul_overflow; + int dl_underflow; +} shared_buffers; + +void init_buffers(shared_buffers *s); + +void lock_dl_buffer(shared_buffers *s, int subframe); +void unlock_dl_buffer(shared_buffers *s, int subframe); +void wait_dl_buffer(shared_buffers *s, int subframe); +void signal_dl_buffer(shared_buffers *s, int subframe); + +void lock_ul_buffer(shared_buffers *s, int subframe); +void unlock_ul_buffer(shared_buffers *s, int subframe); +void wait_ul_buffer(shared_buffers *s, int subframe); +void signal_ul_buffer(shared_buffers *s, int subframe); + +#endif /* _BENETEL_4G_SHARED_BUFFERS_H_ */ diff --git a/targets/ARCH/ETHERNET/benetel/5g/benetel.c b/targets/ARCH/ETHERNET/benetel/5g/benetel.c new file mode 100644 index 0000000000..c1ae1afcc7 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/benetel.c @@ -0,0 +1,388 @@ +/* + * 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 "common_lib.h" +#include "ethernet_lib.h" +#include "shared_buffers.h" +#include "low.h" +#include "openair1/PHY/defs_gNB.h" + +typedef struct { + eth_state_t e; + shared_buffers buffers; + rru_config_msg_type_t last_msg; + int capabilities_sent; + void *benetel_priv; + char *dpdk_main_command_line; +} benetel_eth_state_t; + +int trx_benetel_start(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + + +void trx_benetel_end(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); +} + + +int trx_benetel_stop(openair0_device *device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_freq(openair0_device* device, + openair0_config_t *openair0_cfg, + int exmimo_dump_config) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_set_gains(openair0_device* device, + openair0_config_t *openair0_cfg) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_get_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int trx_benetel_reset_stats(openair0_device* device) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return(0); +} + + +int ethernet_tune(openair0_device *device, + unsigned int option, + int value) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return 0; +} + +int trx_benetel_write_raw(openair0_device *device, + openair0_timestamp timestamp, + void **buff, int nsamps, int cc, int flags) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +int trx_benetel_read_raw(openair0_device *device, + openair0_timestamp *timestamp, + void **buff, int nsamps, int cc) +{ + printf("BENETEL: %s\n", __FUNCTION__); + return nsamps*4; +} + +char *msg_type(int t) +{ + static char *s[12] = { + "RAU_tick", + "RRU_capabilities", + "RRU_config", + "RRU_config_ok", + "RRU_start", + "RRU_stop", + "RRU_sync_ok", + "RRU_frame_resynch", + "RRU_MSG_max_num", + "RRU_check_sync", + "RRU_config_update", + "RRU_config_update_ok", + }; + + if (t < 0 || t > 11) return "UNKNOWN"; + return s[t]; +} + +int trx_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + printf(" rru_config_msg->type %d [%s]\n", rru_config_msg->type, + msg_type(rru_config_msg->type)); + + s->last_msg = rru_config_msg->type; + + return msg_len; +} + +int trx_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len) +{ + RRU_CONFIG_msg_t *rru_config_msg = msg; + benetel_eth_state_t *s = device->priv; + + printf("BENETEL: %s\n", __FUNCTION__); + + if (s->last_msg == RAU_tick && s->capabilities_sent == 0) { + RRU_capabilities_t *cap; + rru_config_msg->type = RRU_capabilities; + rru_config_msg->len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); + cap = (RRU_capabilities_t*)&rru_config_msg->msg[0]; + cap->FH_fmt = OAI_IF4p5_only; + cap->num_bands = 1; + cap->band_list[0] = 78; + cap->nb_rx[0] = 1; + cap->nb_tx[0] = 1; + cap->max_pdschReferenceSignalPower[0] = -27; + cap->max_rxgain[0] = 90; + + s->capabilities_sent = 1; + + return rru_config_msg->len; + } +#if 0 + if (s->last_msg == RRU_config) { + rru_config_msg->type = RRU_config_ok; + return 0; + } + if (s->last_msg == RRU_start) { +printf("***************** benetel start\n"); + s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); + } +#endif + if (s->last_msg == RRU_config) { + rru_config_msg->type = RRU_config_ok; + s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line); + } + /* correct? */ +//printf("***************** benetel pause\n"); +// while (1) pause(); + + return 0; +} + +void benetel_fh_if4p5_south_in(RU_t *ru, + int *frame, + int *slot) +{ +//printf("XXX benetel_fh_if4p5_south_in %d %d\n", *frame, *slot); + benetel_eth_state_t *s = ru->ifdevice.priv; + NR_DL_FRAME_PARMS *fp; + int symbol; + int32_t *rxdata; + int antenna = 0; + + lock_ul_buffer(&s->buffers, *slot); +#if 1 +next: + while (!(s->buffers.ul_busy[*slot] == 0x3fff || + s->buffers.prach_busy[*slot] == 1)) + wait_ul_buffer(&s->buffers, *slot); + if (s->buffers.prach_busy[*slot] == 1) { + int i; + int antenna = 0; + uint16_t *in; + uint16_t *out; + in = (uint16_t *)s->buffers.prach[*slot]; + out = (uint16_t *)ru->prach_rxsigF[antenna]; + for (i = 0; i < 839*2; i++) + out[i] = ntohs(in[i]); + s->buffers.prach_busy[*slot] = 0; + //printf("prach for f.sl %d.%d\n", *frame, *slot); + //ru->wakeup_prach_gNB(ru->gNB_list[0], ru, *frame, *slot); + goto next; + } +#endif + + fp = ru->nr_frame_parms; + for (symbol = 0; symbol < 14; symbol++) { + int i; + uint16_t *p = (uint16_t *)(&s->buffers.ul[*slot][symbol*1272*4]); + for (i = 0; i < 1272*2; i++) { + p[i] = htons(p[i]); + } + rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size]; +#if 1 + memcpy(rxdata + 2048 - 1272/2, + &s->buffers.ul[*slot][symbol*1272*4], + (1272/2) * 4); + memcpy(rxdata, + &s->buffers.ul[*slot][symbol*1272*4] + (1272/2)*4, + (1272/2) * 4); +#endif + } + + s->buffers.ul_busy[*slot] = 0; + signal_ul_buffer(&s->buffers, *slot); + unlock_ul_buffer(&s->buffers, *slot); + + //printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *slot); + + RU_proc_t *proc = &ru->proc; + extern uint16_t sl_ahead; + int f = *frame; + int sl = *slot; + + //calculate timestamp_rx, timestamp_tx based on frame and slot + proc->tti_rx = sl; + proc->frame_rx = f; + /* TODO: be sure of samples_per_slot0 + FK: should use get_samples_per_slot(slot) + but for mu=1 its ok + */ + proc->timestamp_rx = ((proc->frame_rx * 20) + proc->tti_rx ) * fp->samples_per_slot0; + + if (get_nprocs()<=4) { + // why? what if there are more? + proc->tti_tx = (sl+sl_ahead)%20; + proc->frame_tx = (sl>(19-sl_ahead)) ? (f+1)&1023 : f; + } +} + +void benetel_fh_if4p5_south_out(RU_t *ru, + int frame, + int slot, + uint64_t timestamp) +{ +//printf("XXX benetel_fh_if4p5_south_out %d %d %ld\n", frame, slot, timestamp); + benetel_eth_state_t *s = ru->ifdevice.priv; + NR_DL_FRAME_PARMS *fp; + int symbol; + int32_t *txdata; + int aa = 0; + + //printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, slot, timestamp); + + lock_dl_buffer(&s->buffers, slot); + if (s->buffers.dl_busy[slot]) { + printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, slot); + unlock_dl_buffer(&s->buffers, slot); + return; + } + + fp = ru->nr_frame_parms; + if (ru->num_gNB != 1 || ru->nb_tx != 1 || fp->ofdm_symbol_size != 2048 || + fp->Ncp != NORMAL || fp->symbols_per_slot != 14) { + printf("%s:%d:%s: unsupported configuration\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + for (symbol = 0; symbol < 14; symbol++) { + txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size]; +#if 1 + memcpy(&s->buffers.dl[slot][symbol*1272*4], + txdata + 2048 - (1272/2), + (1272/2) * 4); + memcpy(&s->buffers.dl[slot][symbol*1272*4] + (1272/2)*4, + txdata, + (1272/2) * 4); +#endif + int i; + uint16_t *p = (uint16_t *)(&s->buffers.dl[slot][symbol*1272*4]); + for (i = 0; i < 1272*2; i++) { + p[i] = htons(p[i]); + } + } + + s->buffers.dl_busy[slot] = 0x3fff; + unlock_dl_buffer(&s->buffers, slot); +} + +void *get_internal_parameter(char *name) +{ + printf("BENETEL: %s\n", __FUNCTION__); + + if (!strcmp(name, "fh_if4p5_south_in")) + return benetel_fh_if4p5_south_in; + if (!strcmp(name, "fh_if4p5_south_out")) + return benetel_fh_if4p5_south_out; + + return NULL; +} + +__attribute__((__visibility__("default"))) +int transport_init(openair0_device *device, + openair0_config_t *openair0_cfg, + eth_params_t * eth_params ) +{ + benetel_eth_state_t *eth; + + printf("BENETEL: %s\n", __FUNCTION__); + + device->Mod_id = 0; + device->transp_type = ETHERNET_TP; + device->trx_start_func = trx_benetel_start; + device->trx_get_stats_func = trx_benetel_get_stats; + device->trx_reset_stats_func = trx_benetel_reset_stats; + device->trx_end_func = trx_benetel_end; + device->trx_stop_func = trx_benetel_stop; + device->trx_set_freq_func = trx_benetel_set_freq; + device->trx_set_gains_func = trx_benetel_set_gains; + + device->trx_write_func = trx_benetel_write_raw; + device->trx_read_func = trx_benetel_read_raw; + + device->trx_ctlsend_func = trx_benetel_ctlsend; + device->trx_ctlrecv_func = trx_benetel_ctlrecv; + + device->get_internal_parameter = get_internal_parameter; + + eth = calloc(1, sizeof(benetel_eth_state_t)); + if (eth == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->e.flags = ETH_RAW_IF4p5_MODE; + eth->e.compression = NO_COMPRESS; + eth->e.if_name = eth_params->local_if_name; + device->priv = eth; + device->openair0_cfg=&openair0_cfg[0]; + + if (openair0_cfg->sdr_addrs == NULL) { + printf("benetel: fatal: sdr_addrs not set in configuration file\n"); + exit(1); + } + + eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs); + if (eth->dpdk_main_command_line == NULL) { + AssertFatal(0==1, "out of memory\n"); + } + + eth->last_msg = -1; + + init_buffers(ð->buffers); + + return 0; +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c b/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c new file mode 100644 index 0000000000..b90702d331 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/dpdk_driver.c @@ -0,0 +1,856 @@ +/* license: to be defined */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "low.h" + +// HEADER DEFINITION +#define ANT_NUM buf[23] +#define PAYLOAD_1 buf[20] +#define PAYLOAD_2 buf[21] +#define ETH_TYPE buf[17] +#define SYMBOL buf[29] +#define SUBFRAME buf[28] +#define FRAME buf[27] + +static volatile bool force_quit; + +unsigned short iq[712320]; +unsigned char iq_swap[1424640]; + +unsigned short *iq_ptr[14]; +unsigned int dl_start = 0, slot_id_ctrl = 0, count_symbol = 0, sf = 0x10; + +/* MAC updating enabled by default */ +static int mac_updating = 1; +#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 +#define MAX_PKT_BURST 32 +#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */ +#define MEMPOOL_CACHE_SIZE 256 +/* + * Configurable number of RX/TX ring descriptors + */ +#define RTE_TEST_RX_DESC_DEFAULT 1024 +#define RTE_TEST_TX_DESC_DEFAULT 1024 +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; +/* ethernet addresses of ports */ +static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; +/* mask of enabled ports */ +static uint32_t l2fwd_enabled_port_mask = 0; +/* list of enabled ports */ +static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; +static unsigned int l2fwd_rx_queue_per_lcore = 1; +#define MAX_RX_QUEUE_PER_LCORE 16 +#define MAX_TX_QUEUE_PER_PORT 16 +struct lcore_queue_conf { + unsigned n_rx_port; + unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; +} __rte_cache_aligned; +struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; +static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; +static struct rte_eth_conf port_conf = { + .rxmode = { + .split_hdr_size = 0, + .offloads = DEV_RX_OFFLOAD_CRC_STRIP, + .offloads = DEV_RX_OFFLOAD_JUMBO_FRAME, + .split_hdr_size = 0, + .max_rx_pkt_len = 9500, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; +struct rte_mempool * l2fwd_pktmbuf_pool = NULL; +/* Per-port statistics struct */ +struct l2fwd_port_statistics { + uint64_t tx; + uint64_t rx; + uint64_t dropped; +} __rte_cache_aligned; +struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; +#define MAX_TIMER_PERIOD 86400 /* 1 day max */ +/* A tsc-based timer responsible for triggering statistics printout */ +static uint64_t timer_period = 10; /* default period is 10 seconds */ +/* Print out statistics on packets dropped */ +static void +print_stats(void) +{ + uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; + unsigned portid; + total_packets_dropped = 0; + total_packets_tx = 0; + total_packets_rx = 0; + const char clr[] = { 27, '[', '2', 'J', '\0' }; + const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + printf("\nPort statistics ===================================="); + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { + /* skip disabled ports */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("\nStatistics for port %u ------------------------------" + "\nPackets sent: %24"PRIu64 + "\nPackets received: %20"PRIu64 + "\nPackets dropped: %21"PRIu64, + portid, + port_statistics[portid].tx, + port_statistics[portid].rx, + port_statistics[portid].dropped); + total_packets_dropped += port_statistics[portid].dropped; + total_packets_tx += port_statistics[portid].tx; + total_packets_rx += port_statistics[portid].rx; + } + printf("\nAggregate statistics ===============================" + "\nTotal packets sent: %18"PRIu64 + "\nTotal packets received: %14"PRIu64 + "\nTotal packets dropped: %15"PRIu64, + total_packets_tx, + total_packets_rx, + total_packets_dropped); + printf("\n====================================================\n"); +} +static void +l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs) +{ + unsigned char *buf, *buf_tx; + unsigned int len; + struct ether_hdr *eth; + + unsigned dst_port; + int sent, prach_ctrl = 0; + struct rte_eth_dev_tx_buffer *buffer; + + unsigned char * IQ_ptr; + + ul_packet_t p; + + buf = rte_pktmbuf_mtod(m, unsigned char *); + //DD Debug + //rte_memdump(stdout, "Rx Packet",buf ,34); + eth = rte_pktmbuf_mtod(m, struct ether_hdr *); + len = rte_pktmbuf_data_len(m); + + IQ_ptr = &buf[34]; + if (portid == 0) + { + //destination mac address (RRU MAC) + /*eth->d_addr.addr_bytes[0] = 0x02; + eth->d_addr.addr_bytes[1] = 0x00; + eth->d_addr.addr_bytes[2] = 0x5e; + eth->d_addr.addr_bytes[3] = 0x01; + eth->d_addr.addr_bytes[4] = 0x01; + eth->d_addr.addr_bytes[5] = 0x01;*/ + + eth->d_addr.addr_bytes[0] = buf[6]; + eth->d_addr.addr_bytes[1] = buf[7]; + eth->d_addr.addr_bytes[2] = buf[8]; + eth->d_addr.addr_bytes[3] = buf[9]; + eth->d_addr.addr_bytes[4] = buf[10]; + eth->d_addr.addr_bytes[5] = buf[11]; + + //source mac address (DU MAC) + eth->s_addr.addr_bytes[0] = 0xdd; + eth->s_addr.addr_bytes[1] = 0xdd; + eth->s_addr.addr_bytes[2] = 0xdd; + eth->s_addr.addr_bytes[3] = 0xdd; + eth->s_addr.addr_bytes[4] = 0xdd; + eth->s_addr.addr_bytes[5] = 0xdd; + } + else + { + //destination mac address (RRU MAC) + /*eth->d_addr.addr_bytes[0] = 0x02; + eth->d_addr.addr_bytes[1] = 0x00; + eth->d_addr.addr_bytes[2] = 0x5e; + eth->d_addr.addr_bytes[3] = 0x01; + eth->d_addr.addr_bytes[4] = 0x01; + eth->d_addr.addr_bytes[5] = 0x01;*/ + + eth->d_addr.addr_bytes[0] = buf[6]; + eth->d_addr.addr_bytes[1] = buf[7]; + eth->d_addr.addr_bytes[2] = buf[8]; + eth->d_addr.addr_bytes[3] = buf[9]; + eth->d_addr.addr_bytes[4] = buf[10]; + eth->d_addr.addr_bytes[5] = buf[11]; + //source mac address (DU MAC) + eth->s_addr.addr_bytes[0] = 0xdd; + eth->s_addr.addr_bytes[1] = 0xdd; + eth->s_addr.addr_bytes[2] = 0xdd; + eth->s_addr.addr_bytes[3] = 0xdd; + eth->s_addr.addr_bytes[4] = 0xdd; + eth->s_addr.addr_bytes[5] = 0xde; + + } + dst_port = l2fwd_dst_ports[portid]; + //DD Debug + //printf("dstPort =%d\n", dst_port); + // Handshake Condition + if (buf[18] == 0xAA ) // ORAN handshake msgs. + { + printf("\n Start UP Request Received\n"); + printf("\n====================================================\n"); + + buf[18] = 0xBB;//change to msg2 after receive msg1 + + printf(" Start Up Response Sent\n"); + printf("\n====================================================\n"); + + } + + // Trigger start send DL packets + if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && SYMBOL == 0x46 && ANT_NUM == 0x00 && SUBFRAME == 0x00 && dl_start == 0){ + + printf("\nU-Plane Started\n"); + printf("\n====================================================\n"); + + dl_start = 1; + count_symbol = 28; + } + + + if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x00) { + int subframe = SUBFRAME >> 4; + int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); + p.frame = FRAME; + p.slot = subframe * 2 + slot; + p.symbol = SYMBOL & 0x3f; + p.antenna = 0; + memcpy(p.iq, IQ_ptr, 5088); + store_ul(bs, &p); + //if (p.symbol==0) printf("store ul f.sl.sy %d.%d.%d\n", p.frame, p.slot, p.symbol); + } + + // U-PLANE UL ANT_0 PROCESSING + if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x00 && dl_start == 1) + { + int frame = FRAME; + int subframe = SUBFRAME >> 4; + int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); + int symbol = SYMBOL & 0x3f; + int oai_slot; + + int tx_frame = frame; + int tx_subframe = subframe; + int tx_slot = slot; + int tx_symbol = symbol + 8; + + if (tx_symbol > 13) { + tx_symbol -= 14; + tx_slot++; + if (tx_slot == 2) { + tx_slot = 0; + tx_subframe++; + if (tx_subframe == 10) { + tx_subframe = 0; + tx_frame = (tx_frame + 1) & 255; + } + } + } + + ANT_NUM = 0x00; + + // Mask the symbol bits from UL packet received and apply the shift. + SYMBOL = ((SYMBOL & 0b00111111) + 8) % 14; + + ANT_NUM = 0x00; + SUBFRAME = sf; + + // Slot id control for DL + if(slot_id_ctrl > 13){ + SYMBOL = SYMBOL | 0b01000000; + } + + /* antenna 0 - send actual DL data (if available) */ + oai_slot = tx_subframe * 2 + tx_slot; + lock_dl_buffer(bs->buffers, oai_slot); + if (!(bs->buffers->dl_busy[oai_slot] & (1 << tx_symbol))) { + printf("%s: warning, DL underflow (sl.symbol %d.%d)\n", __FUNCTION__, + oai_slot, tx_symbol); + memset(IQ_ptr, 0, 1272 * 4); + } else { + memcpy(IQ_ptr, bs->buffers->dl[oai_slot] + tx_symbol * 1272*4, + 1272*4); + } + bs->buffers->dl_busy[oai_slot] &= ~(1 << tx_symbol); + unlock_dl_buffer(bs->buffers, oai_slot); + + // fill DL Data for ant 0 with 0 value +// memset(IQ_ptr, 0, 5088); + } + + // U-PLANE UL ANT_1 PROCESSING + if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x01 && dl_start == 1) + { + + // Mask the symbol bits from UL packet received and apply the shift. + SYMBOL = ((SYMBOL & 0b00111111) + 8) % 14; + + ANT_NUM = 0x01; + SUBFRAME = sf; + + slot_id_ctrl++; + + // Slot id control for DL + if(slot_id_ctrl > 13){ + SYMBOL = SYMBOL | 0b01000000; + + if(slot_id_ctrl > 27){ + slot_id_ctrl = 0; + sf = sf + 0x10; + + if (sf >0x90){ + sf = 0; + } + } + } + + // fill DL Data for ant 1 with 0 value + memset(IQ_ptr, 0, 5088); + } + + // U-PLANE PRACH PROCESSING + else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){ + if (ANT_NUM == 0) { + int subframe = SUBFRAME >> 4; + int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03); + if (subframe==9) { + //printf("store prach f.sf.sl %d.%d.%d %d\n", FRAME, subframe, slot, subframe * 2 + slot); + store_prach(bs, FRAME, slot /*subframe * 2 + slot*/, IQ_ptr); + } + } + rte_pktmbuf_free(m); + return; + } + + // Send Packets + buffer = tx_buffer[dst_port]; + + sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); + + if (sent) + port_statistics[dst_port].tx += sent; + +} +/* main processing loop */ +static void +l2fwd_main_loop(benetel_t *bs) +{ + struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; + struct rte_mbuf *m; + int sent; + unsigned lcore_id; + uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; + unsigned i, j, portid, nb_rx; + struct lcore_queue_conf *qconf; + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * + BURST_TX_DRAIN_US; + struct rte_eth_dev_tx_buffer *buffer; + prev_tsc = 0; + timer_tsc = 0; + lcore_id = rte_lcore_id(); + qconf = &lcore_queue_conf[lcore_id]; + if (qconf->n_rx_port == 0) { + RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); + return; + } + RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, + portid); + } + while (!force_quit) { + cur_tsc = rte_rdtsc(); + /* + * TX burst queue drain + */ + diff_tsc = cur_tsc - prev_tsc; + if (unlikely(diff_tsc > drain_tsc)) { + for (i = 0; i < qconf->n_rx_port; i++) { + portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; + buffer = tx_buffer[portid]; + sent = rte_eth_tx_buffer_flush(portid, 0, buffer); + if (sent) + port_statistics[portid].tx += sent; + } + /* if timer is enabled */ + if (timer_period > 0) { + /* advance the timer */ + timer_tsc += diff_tsc; + /* if timer has reached its timeout */ + if (unlikely(timer_tsc >= timer_period)) { + /* do this only on master core */ + if (lcore_id == rte_get_master_lcore()) { + print_stats(); + /* reset the timer */ + timer_tsc = 0; + } + } + } + prev_tsc = cur_tsc; + } + /* + * Read packet from RX queues + */ + for (i = 0; i < qconf->n_rx_port; i++) { + portid = qconf->rx_port_list[i]; + nb_rx = rte_eth_rx_burst(portid, 0, + pkts_burst, MAX_PKT_BURST); + port_statistics[portid].rx += nb_rx; + for (j = 0; j < nb_rx; j++) { + m = pkts_burst[j]; + rte_prefetch0(rte_pktmbuf_mtod(m, void *)); + l2fwd_simple_forward(m, portid, bs); + } + } + } +} +static int +l2fwd_launch_one_lcore(void *bs) +{ + l2fwd_main_loop(bs); + return 0; +} +/* display usage */ +static void +l2fwd_usage(const char *prgname) +{ + printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" + " -p PORTMASK: hexadecimal bitmask of ports to configure\n" + " -q NQ: number of queue (=ports) per lcore (default is 1)\n" + " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n" + " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n" + " When enabled:\n" + " - The source MAC address is replaced by the TX port MAC address\n" + " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n", + prgname); +} +static int +l2fwd_parse_portmask(const char *portmask) +{ + char *end = NULL; + unsigned long pm; + /* parse hexadecimal string */ + pm = strtoul(portmask, &end, 16); + if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (pm == 0) + return -1; + return pm; +} +static unsigned int +l2fwd_parse_nqueue(const char *q_arg) +{ + char *end = NULL; + unsigned long n; + /* parse hexadecimal string */ + n = strtoul(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return 0; + if (n == 0) + return 0; + if (n >= MAX_RX_QUEUE_PER_LCORE) + return 0; + return n; +} +static int +l2fwd_parse_timer_period(const char *q_arg) +{ + char *end = NULL; + int n; + /* parse number string */ + n = strtol(q_arg, &end, 10); + if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) + return -1; + if (n >= MAX_TIMER_PERIOD) + return -1; + return n; +} +static const char short_options[] = + "p:" /* portmask */ + "q:" /* number of queues */ + "T:" /* timer period */ + ; +#define CMD_LINE_OPT_MAC_UPDATING "mac-updating" +#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating" +enum { + /* long options mapped to a short option */ + /* first long only option value must be >= 256, so that we won't + * conflict with short options */ + CMD_LINE_OPT_MIN_NUM = 256, +}; +static const struct option lgopts[] = { + { CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1}, + { CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0}, + {NULL, 0, 0, 0} +}; +/* Parse the argument given in the command line of the application */ +static int +l2fwd_parse_args(int argc, char **argv) +{ + int opt, ret, timer_secs; + char **argvopt; + int option_index; + char *prgname = argv[0]; + argvopt = argv; + while ((opt = getopt_long(argc, argvopt, short_options, + lgopts, &option_index)) != EOF) { + switch (opt) { + /* portmask */ + case 'p': + l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); + if (l2fwd_enabled_port_mask == 0) { + printf("invalid portmask\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* nqueue */ + case 'q': + l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); + if (l2fwd_rx_queue_per_lcore == 0) { + printf("invalid queue number\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* timer period */ + case 'T': + timer_secs = l2fwd_parse_timer_period(optarg); + if (timer_secs < 0) { + printf("invalid timer period\n"); + l2fwd_usage(prgname); + return -1; + } + timer_period = timer_secs; + break; + /* long options */ + case 0: + break; + case 'proc-type': + break; + case 'socket-mem': + break; + case 'file-prefix': + l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); + if (l2fwd_rx_queue_per_lcore == 0) { + printf("invalid queue number\n"); + l2fwd_usage(prgname); + return -1; + } + break; + /* timer period */ + /* timer period */ + /* timer period */ + default: + l2fwd_usage(prgname); + return -1; + } + } + if (optind >= 0) + argv[optind-1] = prgname; + ret = optind-1; + optind = 1; /* reset getopt lib */ + return ret; +} +/* Check the link status of all ports in up to 9s, and print them finally */ +static void +check_all_ports_link_status(uint32_t port_mask) +{ +#define CHECK_INTERVAL 100 /* 100ms */ +#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ + uint16_t portid; + uint8_t count, all_ports_up, print_flag = 0; + struct rte_eth_link link; + printf("\nChecking link status"); + fflush(stdout); + for (count = 0; count <= MAX_CHECK_TIME; count++) { + if (force_quit) + return; + all_ports_up = 1; + RTE_ETH_FOREACH_DEV(portid) { + if (force_quit) + return; + if ((port_mask & (1 << portid)) == 0) + continue; + memset(&link, 0, sizeof(link)); + rte_eth_link_get_nowait(portid, &link); + /* print link status if flag set */ + if (print_flag == 1) { + if (link.link_status) + printf( + "Port%d Link Up. Speed %u Mbps - %s\n", + portid, link.link_speed, + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + ("full-duplex") : ("half-duplex\n")); + else + printf("Port %d Link Down\n", portid); + continue; + } + /* clear all_ports_up flag if any link down */ + if (link.link_status == ETH_LINK_DOWN) { + all_ports_up = 0; + break; + } + } + /* after finally printing all link status, get out */ + if (print_flag == 1) + break; + if (all_ports_up == 0) { + printf("."); + fflush(stdout); + rte_delay_ms(CHECK_INTERVAL); + } + /* set the print_flag if all ports up or timeout */ + if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { + print_flag = 1; + printf("done\n"); + } + } +} +static void +signal_handler(int signum) +{ + if (signum == SIGINT || signum == SIGTERM) { + printf("\n\nSignal %d received, preparing to exit...\n", + signum); + force_quit = true; + } +} +int +dpdk_main(int argc, char **argv, benetel_t *bs) +{ + struct lcore_queue_conf *qconf; + int ret; + uint16_t nb_ports; + uint16_t nb_ports_available = 0; + uint16_t portid, last_port; + unsigned lcore_id, rx_lcore_id; + unsigned nb_ports_in_mask = 0; + unsigned int nb_lcores = 0; + unsigned int nb_mbufs; + /* init EAL */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); + argc -= ret; + argv += ret; + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + /* parse application arguments (after the EAL ones) */ + ret = l2fwd_parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); + printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled"); + /* convert to number of cycles */ + timer_period *= rte_get_timer_hz(); + nb_ports = rte_eth_dev_count_avail(); + if (nb_ports == 0) + rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); + /* check port mask to possible port mask */ + if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1)) + rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n", + (1 << nb_ports) - 1); + /* reset l2fwd_dst_ports */ + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) + l2fwd_dst_ports[portid] = 0; + last_port = 0; + /* + * Each logical core is assigned a dedicated TX queue on each port. + */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + if (nb_ports_in_mask % 2) { + l2fwd_dst_ports[portid] = last_port; + l2fwd_dst_ports[last_port] = portid; + } + else + last_port = portid; + nb_ports_in_mask++; + } + if (nb_ports_in_mask % 2) { + printf("Notice: odd number of ports in portmask.\n"); + l2fwd_dst_ports[last_port] = last_port; + } + rx_lcore_id = 0; + qconf = NULL; + /* Initialize the port/queue configuration of each logical core */ + RTE_ETH_FOREACH_DEV(portid) { + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + /* get the lcore_id for this port */ + while (rte_lcore_is_enabled(rx_lcore_id) == 0 || + lcore_queue_conf[rx_lcore_id].n_rx_port == + l2fwd_rx_queue_per_lcore) { + rx_lcore_id++; + if (rx_lcore_id >= RTE_MAX_LCORE) + rte_exit(EXIT_FAILURE, "Not enough cores\n"); + } + if (qconf != &lcore_queue_conf[rx_lcore_id]) { + /* Assigned a new logical core in the loop above. */ + qconf = &lcore_queue_conf[rx_lcore_id]; + nb_lcores++; + } + qconf->rx_port_list[qconf->n_rx_port] = portid; + qconf->n_rx_port++; + printf("Lcore %u: RX port %u\n", rx_lcore_id, portid); + } + nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST + + nb_lcores * MEMPOOL_CACHE_SIZE), 8192U); + /* create the mbuf pool */ + //DD Debug + //printf ("Proc Type %d \n", rte_eal_process_type()); + l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs, + MEMPOOL_CACHE_SIZE, 0, 9680, + rte_socket_id()); + if (l2fwd_pktmbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); + /* Initialise each port */ + RTE_ETH_FOREACH_DEV(portid) { + struct rte_eth_rxconf rxq_conf; + struct rte_eth_txconf txq_conf; + struct rte_eth_conf local_port_conf = port_conf; + struct rte_eth_dev_info dev_info; + /* skip ports that are not enabled */ + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { + printf("Skipping disabled port %u\n", portid); + continue; + } + nb_ports_available++; + /* init port */ + printf("Initializing port %u... ", portid); + fflush(stdout); + rte_eth_dev_info_get(portid, &dev_info); + if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) + local_port_conf.txmode.offloads |= + DEV_TX_OFFLOAD_MBUF_FAST_FREE; + ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", + ret, portid); + ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, + &nb_txd); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot adjust number of descriptors: err=%d, port=%u\n", + ret, portid); + rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); + /* init one RX queue */ + fflush(stdout); + rxq_conf = dev_info.default_rxconf; + rxq_conf.offloads = local_port_conf.rxmode.offloads; + ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, + rte_eth_dev_socket_id(portid), + &rxq_conf, + l2fwd_pktmbuf_pool); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* init one TX queue on each port */ + fflush(stdout); + txq_conf = dev_info.default_txconf; + txq_conf.offloads = local_port_conf.txmode.offloads; + ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, + rte_eth_dev_socket_id(portid), + &txq_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", + ret, portid); + /* Initialize TX buffers */ + tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", + RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, + rte_eth_dev_socket_id(portid)); + if (tx_buffer[portid] == NULL) + rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", + portid); + rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); + ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], + rte_eth_tx_buffer_count_callback, + &port_statistics[portid].dropped); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Cannot set error callback for tx buffer on port %u\n", + portid); + /* Start device */ + ret = rte_eth_dev_start(portid); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", + ret, portid); + printf("done: \n"); + rte_eth_promiscuous_enable(portid); + printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", + portid, + l2fwd_ports_eth_addr[portid].addr_bytes[0], + l2fwd_ports_eth_addr[portid].addr_bytes[1], + l2fwd_ports_eth_addr[portid].addr_bytes[2], + l2fwd_ports_eth_addr[portid].addr_bytes[3], + l2fwd_ports_eth_addr[portid].addr_bytes[4], + l2fwd_ports_eth_addr[portid].addr_bytes[5]); + /* initialize port stats */ + memset(&port_statistics, 0, sizeof(port_statistics)); + } + if (!nb_ports_available) { + rte_exit(EXIT_FAILURE, + "All available ports are disabled. Please set portmask.\n"); + } + check_all_ports_link_status(l2fwd_enabled_port_mask); + ret = 0; + /* launch per-lcore init on every lcore */ + rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER); + RTE_LCORE_FOREACH_SLAVE(lcore_id) { + if (rte_eal_wait_lcore(lcore_id) < 0) { + ret = -1; + break; + } + } + RTE_ETH_FOREACH_DEV(portid) { + if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rte_eth_dev_stop(portid); + rte_eth_dev_close(portid); + printf(" Done\n"); + } + printf("Bye...\n"); + return ret; +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/low.c b/targets/ARCH/ETHERNET/benetel/5g/low.c new file mode 100644 index 0000000000..984e401421 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/low.c @@ -0,0 +1,97 @@ +/* + * 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 "low.h" + +#include +#include +#include + +void store_ul(benetel_t *bs, ul_packet_t *ul) +{ + /* only antenna 0 for the moment */ + if (ul->antenna != 0) + return; + + if (ul->slot != bs->next_slot || + ul->symbol != bs->next_symbol) { + printf("%s: fatal, expected frame.sl.symbol %d.%d.%d, got %d.%d.%d\n", + __FUNCTION__, + bs->expected_benetel_frame, bs->next_slot, bs->next_symbol, + ul->frame, ul->slot, ul->symbol); + exit(1); + } + + lock_ul_buffer(bs->buffers, bs->next_slot); + if (bs->buffers->ul_busy[bs->next_slot] & (1 << bs->next_symbol)) { + printf("%s: warning, UL overflow (sl.symbol %d.%d)\n", __FUNCTION__, + bs->next_slot, bs->next_symbol); + } + + memcpy(bs->buffers->ul[bs->next_slot] + bs->next_symbol * 1272*4, + ul->iq, 1272*4); + bs->buffers->ul_busy[bs->next_slot] |= (1 << bs->next_symbol); + signal_ul_buffer(bs->buffers, bs->next_slot); + unlock_ul_buffer(bs->buffers, bs->next_slot); + + bs->next_symbol++; + if (bs->next_symbol == 14) { + bs->next_symbol = 0; + bs->next_slot = (bs->next_slot + 1) % 20; + if (bs->next_slot == 0) { + bs->expected_benetel_frame++; + bs->expected_benetel_frame &= 255; + } + } +} + +void store_prach(benetel_t *bs, int frame, int slot, void *data) +{ + static int last_frame = -1; + static int last_slot = -1; + /* hack: antenna number is always 0, discard second packet with same f/sf */ + //if (frame == last_frame && slot == last_slot) return; + if (frame == last_frame && slot == last_slot) { printf("got f.sl %d.%d twice\n", frame, slot); return; } + last_frame = frame; + last_slot = slot; + + lock_ul_buffer(bs->buffers, slot); + if (bs->buffers->prach_busy[slot]) { + printf("store_prach: fatal: previous prach buffer not processed\n"); + unlock_ul_buffer(bs->buffers, slot); + return; + } + bs->buffers->prach_busy[slot] = 1; + memcpy(bs->buffers->prach[slot], data, 839*4); + signal_ul_buffer(bs->buffers, slot); + unlock_ul_buffer(bs->buffers, slot); + +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); + +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + if (!strcmp(ifname, "dpdk")) + return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line); + printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname); + exit(1); +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/low.h b/targets/ARCH/ETHERNET/benetel/5g/low.h new file mode 100644 index 0000000000..5e1daee9d1 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/low.h @@ -0,0 +1,48 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _BENETEL_5G_LOW_H_ +#define _BENETEL_5G_LOW_H_ + +#include "shared_buffers.h" + +typedef struct { + shared_buffers *buffers; + int next_slot; + int next_symbol; + int expected_benetel_frame; + char *dpdk_main_command_line; +} benetel_t; + +typedef struct { + int frame; + int slot; + int symbol; + int antenna; + unsigned char iq[5088]; +} ul_packet_t; + +void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line); + +void store_ul(benetel_t *bs, ul_packet_t *ul); +void store_prach(benetel_t *bs, int frame, int slot, void *data); + +#endif /* _BENETEL_5G_LOW_H_ */ diff --git a/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c b/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c new file mode 100644 index 0000000000..5e26f6782e --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/low_dpdk.c @@ -0,0 +1,118 @@ +/* + * 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 + */ + +/* those 2 lines for CPU_SET */ +#define _GNU_SOURCE +#include + +#include +#include +#include +#include + +#include "low.h" + +int dpdk_main(int argc, char **argv, benetel_t *); + +void *dpdk_thread(void *_bs) +{ + benetel_t *bs = _bs; + int n = 0; + char **v = NULL; // = { "softmodem", "-n", "2", "--file-prefix", "pg2", "-l", "6", "--", "-p", "0x1" }; + char *s = bs->dpdk_main_command_line; + char *tok; + + while ((tok = strtok(s, " ")) != NULL) { + n++; + v = realloc(v, n * sizeof(char *)); + if (v == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + v[n-1] = tok; + s = NULL; + } + + dpdk_main(n, v, bs); + exit(1); + return 0; +} + +void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line) +{ + benetel_t *bs; + + bs = calloc(1, sizeof(benetel_t)); + if (bs == NULL) { + printf("%s: out of memory\n", __FUNCTION__); + exit(1); + } + + bs->buffers = buffers; + + bs->expected_benetel_frame = 255; + + bs->dpdk_main_command_line = dpdk_main_command_line; + + pthread_attr_t attr; + + if (pthread_attr_init(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(10,&cpuset); + if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) { + printf("pthread_attr_setaffinity_np failed\n"); + exit(1); + } + + if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { + printf("pthread_attr_setschedpolicy failed\n"); + exit(1); + } + + struct sched_param params; + params.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (sched_get_priority_max(SCHED_FIFO) == -1) { + printf("sched_get_priority_max failed\n"); + exit(1); + } + if (pthread_attr_setschedparam(&attr, ¶ms) != 0) { + printf("pthread_setschedparam failed\n"); + exit(1); + } + + pthread_t t; + if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) { + printf("%s: thread creation failed\n", __FUNCTION__); + exit(1); + } + + if (pthread_attr_destroy(&attr) != 0) { + printf("pthread_attr_init failed\n"); + exit(1); + } + + return bs; +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c new file mode 100644 index 0000000000..b9da10b380 --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.c @@ -0,0 +1,118 @@ +/* + * 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 "shared_buffers.h" + +#include +#include +#include + +void init_buffers(shared_buffers *s) +{ + int slot; + + memset(s, 0, sizeof(*s)); + + for (slot = 0; slot < 20; slot++) { + if (pthread_mutex_init(&s->m_dl[slot], NULL) != 0 || + pthread_cond_init(&s->c_dl[slot], NULL) != 0 || + pthread_mutex_init(&s->m_ul[slot], NULL) != 0 || + pthread_cond_init(&s->c_ul[slot], NULL) != 0) { + printf("%s: error initializing mutex/cond\n", __FUNCTION__); + exit(1); + } + } + + /* the gNB's first transmitted DL slot is 6 but the device + * needs to have slots 1, 2 and 3, 4 and 5 ready. Let's pretend + * they are ready. + */ + s->dl_busy[1] = 0x3fff; + s->dl_busy[2] = 0x3fff; + s->dl_busy[3] = 0x3fff; + s->dl_busy[4] = 0x3fff; + s->dl_busy[5] = 0x3fff; +} + +void lock_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_lock(&s->m_dl[slot]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + exit(1); + } +} + +void unlock_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_unlock(&s->m_dl[slot]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_wait(&s->c_dl[slot], &s->m_dl[slot]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_dl_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_broadcast(&s->c_dl[slot]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} + +void lock_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_lock(&s->m_ul[slot]) != 0) { + printf("%s: fatal: lock fails\n", __FUNCTION__); + printf("%s: fatal: lock fails slot %d\n", __FUNCTION__, slot); + exit(1); + } +} + +void unlock_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_mutex_unlock(&s->m_ul[slot]) != 0) { + printf("%s: fatal: unlock fails\n", __FUNCTION__); + exit(1); + } +} + +void wait_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_wait(&s->c_ul[slot], &s->m_ul[slot]) != 0) { + printf("%s: fatal: cond_wait fails\n", __FUNCTION__); + exit(1); + } +} + +void signal_ul_buffer(shared_buffers *s, int slot) +{ + if (pthread_cond_broadcast(&s->c_ul[slot]) != 0) { + printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__); + exit(1); + } +} diff --git a/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h new file mode 100644 index 0000000000..ca7dbd9c8f --- /dev/null +++ b/targets/ARCH/ETHERNET/benetel/5g/shared_buffers.h @@ -0,0 +1,60 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _BENETEL_5G_SHARED_BUFFERS_H_ +#define _BENETEL_5G_SHARED_BUFFERS_H_ + +#include +#include + +typedef struct { + unsigned char dl[20][14*1272*4]; + unsigned char ul[20][14*1272*4]; + uint16_t dl_busy[20]; + uint16_t ul_busy[20]; + + pthread_mutex_t m_ul[20]; + pthread_cond_t c_ul[20]; + + pthread_mutex_t m_dl[20]; + pthread_cond_t c_dl[20]; + + unsigned char prach[20][849*4]; + unsigned char prach_busy[20]; + + /* statistics/error counting */ + int ul_overflow; + int dl_underflow; +} shared_buffers; + +void init_buffers(shared_buffers *s); + +void lock_dl_buffer(shared_buffers *s, int slot); +void unlock_dl_buffer(shared_buffers *s, int slot); +void wait_dl_buffer(shared_buffers *s, int slot); +void signal_dl_buffer(shared_buffers *s, int slot); + +void lock_ul_buffer(shared_buffers *s, int slot); +void unlock_ul_buffer(shared_buffers *s, int slot); +void wait_ul_buffer(shared_buffers *s, int slot); +void signal_ul_buffer(shared_buffers *s, int slot); + +#endif /* _BENETEL_5G_SHARED_BUFFERS_H_ */ diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 1377086e8f..0c89a68dd5 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -108,7 +108,8 @@ typedef struct { int64_t rx_count; int wait_for_first_pps; int use_gps; - int first_tx; + //int first_tx; + //int first_rx; //! timestamp of RX packet openair0_timestamp rx_timestamp; } usrp_state_t; @@ -282,31 +283,28 @@ static int trx_usrp_start(openair0_device *device) { // set pin 5 (Shutdown LNA) to 1 when the radio is transmitting and receiveing (ATR_XX) // (we use full duplex here, because our RX is on all the time - this might need to change later) s->usrp->set_gpio_attr("FP0", "ATR_XX", (1<<5), 0x7f); - // set the output pins to 0 + // set the output pins to 1 s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80); - // init recv and send streaming - uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); - LOG_I(HW,"Time in secs now: %llu \n", s->usrp->get_time_now().to_ticks(s->sample_rate)); - LOG_I(HW,"Time in secs last pps: %llu \n", s->usrp->get_time_last_pps().to_ticks(s->sample_rate)); - - if (s->use_gps == 1 || device->openair0_cfg[0].time_source == external) { - s->wait_for_first_pps = 1; - cmd.time_spec = s->usrp->get_time_last_pps() + uhd::time_spec_t(1.0); - } else { - s->wait_for_first_pps = 0; - cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.005); - } - - cmd.stream_now = false; // start at constant delay - s->rx_stream->issue_stream_cmd(cmd); - /*s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate); - s->tx_md.has_time_spec = true; - s->tx_md.start_of_burst = true; - s->tx_md.end_of_burst = false;*/ + s->wait_for_first_pps = 1; s->rx_count = 0; s->tx_count = 0; + //s->first_tx = 1; + //s->first_rx = 1; s->rx_timestamp = 0; + + s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); + // wait for the pps to change + uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps(); + while (time_last_pps == s->usrp->get_time_last_pps()) { + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); + cmd.time_spec = uhd::time_spec_t(1.0); + cmd.stream_now = false; // start at constant delay + s->rx_stream->issue_stream_cmd(cmd); + return 0; } /*! \brief Terminate operation of the USRP transceiver -- free all associated resources @@ -635,7 +633,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp int16x8_t buff_tmp[2][nsamps2]; #endif - if (device->type == USRP_B200_DEV) { if (cc>1) { // receive multiple channels (e.g. RF A and RF B) std::vector buff_ptrs; @@ -648,7 +645,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp samples_received=0; while (samples_received != nsamps) { - samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received, + samples_received += s->rx_stream->recv((void*)((int32_t*)buff_tmp[0]+samples_received), nsamps-samples_received, s->rx_md); if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)) @@ -658,7 +655,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp printf("sleep...\n"); //usleep(100); } } - if (samples_received == nsamps) s->wait_for_first_pps=0; } @@ -684,22 +680,10 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp #endif } } - } else if (device->type == USRP_X300_DEV) { - if (cc>1) { - // receive multiple channels (e.g. RF A and RF B) - std::vector buff_ptrs; - for (int i=0; irx_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,1.0); + if (samples_received < nsamps) { + LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps); } - } - - if (samples_received < nsamps) - LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps); if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str()); @@ -835,6 +819,17 @@ rx_gain_calib_table_t calib_table_x310[] = { {-1,0} }; +/*! \brief USRPB210 RX calibration table */ +rx_gain_calib_table_t calib_table_n310[] = { + {3500000000.0,0.0}, + {2660000000.0,0.0}, + {2300000000.0,0.0}, + {1880000000.0,0.0}, + {816000000.0, 0.0}, + {-1,0} +}; + + /*! \brief Set RX gain offset * \param openair0_cfg RF frontend parameters set by application * \param chain_index RF chain to apply settings to @@ -976,7 +971,6 @@ extern "C" { double usrp_master_clock; if (device_adds[0].get("type") == "b200") { - printf("Found USRP b200\n"); device->type = USRP_B200_DEV; usrp_master_clock = 30.72e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); @@ -985,7 +979,7 @@ extern "C" { if (device_adds[0].get("type") == "n3xx") { printf("Found USRP n300\n"); - device->type=USRP_X300_DEV; //treat it as X300 for now + device->type=USRP_N300_DEV; usrp_master_clock = 122.88e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); //args += ", send_buff_size=33554432"; @@ -1071,9 +1065,18 @@ extern "C" { if (device->type==USRP_X300_DEV) { openair0_cfg[0].rx_gain_calib_table = calib_table_x310; - std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info + std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; + } + + if (device->type==USRP_N300_DEV) { + openair0_cfg[0].rx_gain_calib_table = calib_table_n310; + std::cerr << "-- Using calibration table: calib_table_n310" << std::endl; + } + + + if (device->type==USRP_N300_DEV || device->type==USRP_X300_DEV) { LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate); - + switch ((int)openair0_cfg[0].sample_rate) { case 122880000: // from usrp_time_offset diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index b7b435f2d9..93c07a575f 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include "common_lib.h" #include @@ -78,11 +79,25 @@ extern RAN_CONTEXT_t RC; #define RFSIMULATOR_PARAMS_DESC {\ {"serveraddr", "\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ {"serverport", "\n", 0, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ - {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0},\ + {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\ {"IQfile", "\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ - {"modelname", "\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 }\ + {"modelname", "\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ + {"ploss", "\n", 0, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ + {"forgetfact", "\n", 0, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ + {"offset", "\n", 0, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\ }; + + +static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); +static telnetshell_cmddef_t rfsimu_cmdarray[] = { + {"setmodel","",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, + {"","",NULL}, +}; + +static telnetshell_vardef_t rfsimu_vardef[] = { + {"",0,NULL} +}; pthread_mutex_t Sockmutex; typedef struct complex16 sample_t; // 2*16 bits complex number @@ -114,6 +129,11 @@ typedef struct { double sample_rate; double tx_bw; int channelmod; + double chan_pathloss; + double chan_forgetfact; + int chan_offset; + void *telnetcmd_qid; + poll_telnetcmdq_func_t poll_telnetcmdq; } rfsimulator_state_t; @@ -148,22 +168,28 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { // Legacy changes directlty the variable channel_model->path_loss_dB place to place // while calling new_channel_desc_scm() with path losses = 0 static bool init_done=false; + if (!init_done) { - uint64_t rand; - FILE *h=fopen("/dev/random","r"); - fread(&rand,sizeof(rand),1,h); - fclose(h); + uint64_t rand; + FILE *h=fopen("/dev/random","r"); + if ( 1 != fread(&rand,sizeof(rand),1,h) ) + LOG_W(HW, "Simulator can't read /dev/random\n"); + fclose(h); randominit(rand); tableNor(rand); init_done=true; } + ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, bridge->channelmod, bridge->sample_rate, bridge->tx_bw, - 0.0, // forgetting_factor - 0, // maybe used for TA - 0); // path_loss in dB + 30e-9, // TDL delay-spread parameter + bridge->chan_forgetfact, // forgetting_factor + bridge->chan_offset, // maybe used for TA + bridge->chan_pathloss); // path_loss in dB + set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID); + random_channel(ptr->channel_model,false); } } @@ -290,6 +316,42 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { rfsimulator->typeStamp = UE_MAGICDL_FDD; } +static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) { + char *modelname=NULL; + int s = sscanf(buff,"%ms\n",&modelname); + if (s == 1) { + int channelmod=modelid_fromname(modelname); + if (channelmod<0) + prnt("ERROR: model %s unknown\n",modelname); + else { + rfsimulator_state_t *t = (rfsimulator_state_t *)arg; + for (int i=0; ibuf[i]; + if (b->conn_sock >= 0 ) { + channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels, + channelmod, + t->sample_rate, + t->tx_bw, + 30e-9, // TDL delay-spread parameter + t->chan_forgetfact, // forgetting_factor + t->chan_offset, // maybe used for TA + t->chan_pathloss); // path_loss in dB + set_channeldesc_owner(newmodel, RFSIMU_MODULEID); + random_channel(newmodel,false); + channel_desc_t *oldmodel=b->channel_model; + b->channel_model=newmodel; + free_channel_desc_scm(oldmodel); + prnt("New model %s applied to channel connected to sock %d\n",modelname,i); + } + } + } + } else { + prnt("ERROR: no model specified\n"); + } + free(modelname); + return CMDSTATUS_FOUND; +} + int server_start(openair0_device *device) { rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; t->typeStamp=ENB_MAGICDL_FDD; @@ -379,6 +441,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if (t->lastWroteTS > timestamp+nsamps) LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n", t->lastWroteTS, timestamp); + t->lastWroteTS=timestamp+nsamps; if (!alreadyLocked) @@ -396,7 +459,7 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initial) { // Process all incoming events on sockets // store the data in lists - struct epoll_event events[FD_SETSIZE]= {0}; + struct epoll_event events[FD_SETSIZE]= {{0}}; int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout); if ( nfds==-1 ) { @@ -480,6 +543,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi b->trashingPacket=true; } else if ( b->lastReceivedTS < b->th.timestamp) { int nbAnt= b->th.nbAnt; + if ( b->th.timestamp-b->lastReceivedTS < CirSize ) { for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { for (int a=0; a < nbAnt; a++) { @@ -490,8 +554,10 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi } else { memset(b->circularBuf, 0, sampleToByte(CirSize,1)); } + if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS > 50 ) LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS ); + b->lastReceivedTS=b->th.timestamp; } else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) { @@ -510,7 +576,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi LOG_E(HW,"UEsock: %d Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, t->lastWroteTS, b->lastReceivedTS); pthread_mutex_unlock(&Sockmutex); - b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; + b->transferPtr=(char *)&b->circularBuf[(b->lastReceivedTS*b->th.nbAnt)%CirSize]; b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); } @@ -640,8 +706,10 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo // it seems legacy behavior is: never in UL, each frame in DL if (reGenerateChannel) random_channel(ptr->channel_model,0); + if (t->poll_telnetcmdq) + t->poll_telnetcmdq(t->telnetcmd_qid,t); - for (int a=0; achannel_model != NULL ) // apply a channel model rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a], a, @@ -652,14 +720,16 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ); else { // no channel modeling sample_t *out=(sample_t *)samplesVoid[a]; - const int64_t base=t->nextTimestamp*nbAnt+a; - for ( int i=0; i < nsamps; i++ ) { - const int idx=(i*nbAnt+base)%CirSize; - out[i].r+=ptr->circularBuf[idx].r; - out[i].i+=ptr->circularBuf[idx].i; - } + int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas + //LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx); + for (int i=0; i < nsamps; i++) {//loop over nsamps + for (int a_tx=0; a_txcircularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].r; + out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].i; + } // end for a_tx + } // end for i (number of samps) } // end of no channel modeling - } // end for a... + } // end for a (number of rx antennas) } } @@ -734,5 +804,18 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->tx_bw=openair0_cfg->tx_bw; //randominit(0); set_taus_seed(0); + /* look for telnet server, if it is loaded, add the channel modeling commands to it */ + add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); + + if (addcmd != NULL) { + rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME); + addcmd("rfsimu",rfsimu_vardef,rfsimu_cmdarray); + for(int i=0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) { + if ( rfsimu_cmdarray[i].qptr != NULL) { + rfsimulator->telnetcmd_qid = rfsimu_cmdarray[i].qptr; + break; + } + } + } return 0; } diff --git a/targets/COMMON/threads_t.h b/targets/COMMON/threads_t.h index 0671f40988..5fb1645444 100644 --- a/targets/COMMON/threads_t.h +++ b/targets/COMMON/threads_t.h @@ -1,5 +1,5 @@ -#ifndef _THREADS_T_H_ -#define _THREADS_T_H_ +#ifndef _TARGETS_COMMON_THREADS_T_H_ +#define _TARGETS_COMMON_THREADS_T_H_ typedef struct threads_s { int main; @@ -18,4 +18,4 @@ typedef struct threads_s { //int dlsch_td1_three; } threads_t; -#endif /* _THREADS_T_H_ */ +#endif /* _TARGETS_COMMON_THREADS_T_H_ */ diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf new file mode 100644 index 0000000000..716bfd3b6b --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-4g.conf @@ -0,0 +1,281 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2655000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 90; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -10; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.61.195"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "no"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.160.46"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.160.46"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.1"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 150; + } +); + +RUs = ( + { + //local_if_name = "enp129s0f0"; + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 8 -n 2 -b 0000:3b:00.0 --proc-type auto --file-prefix ggg -- -p 0x1"; + #sdr_addrs = "softmodem -l 8 -n 2 -- -p 0x2"; + remote_address = "127.0.0.2"; + local_address = "127.0.0.1"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + local_rf = "no" + tr_preference = "raw_if4p5" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + eNB_instances = [0]; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + #parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf new file mode 100644 index 0000000000..27fc90e5e3 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/benetel-5g.conf @@ -0,0 +1,307 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is is the central frequency of SSB + absoluteFrequencySSB = 640000; //641272 + dl_frequencyBand = 78; + # the carrier frequency is assumed to be in the middle of the carrier, i.e. dl_absoluteFrequencyPointA_kHz + dl_carrierBandwidth*12*SCS_kHz/2 + dl_absoluteFrequencyPointA = 638728; //640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 4; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 74; + zeroCorrelationZoneConfig = 13; + #preambleReceivedTargetPower = -118; + preambleReceivedTargetPower = -104; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 2; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 1; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + #msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + #ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.61.195"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "127.0.0.1"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.160.146/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.160.146/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "127.0.0.2/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "no" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + //clock_src = "internal"; + clock_src = "external"; + + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 6 -n 3 -b 0000:3b:00.1 --proc-type auto --file-prefix hhh -- -p 0x1"; + remote_address = "127.0.0.2"; + local_address = "127.0.0.1"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + tr_preference = "raw_if4p5" + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + //parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf index d5bc492644..983404e459 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf @@ -235,7 +235,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; if_freq = 5300000000; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf index 93a6c7fbc9..2737357851 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf @@ -235,7 +235,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "type=n300"; } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf index 72a27cc1e7..e171b2faa9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf @@ -235,7 +235,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; if_freq = 5124520000L; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf index fdc4894da6..862f0e6303 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf @@ -21,183 +21,166 @@ gNBs = ////////// Physical parameters: - component_carriers = ( - { - node_function = "3GPP_gNODEB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "TDD"; - DL_prefix_type = "NORMAL"; - UL_prefix_type = "NORMAL"; - eutra_band = 78; - downlink_frequency = 3510000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 106; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - MIB_subCarrierSpacingCommon = 30; - MIB_ssb_SubcarrierOffset = 0; - MIB_dmrs_TypeA_Position = 2; - pdcch_ConfigSIB1 = 0; - SIB1_frequencyOffsetSSB = "khz5"; - SIB1_ssb_PeriodicityServingCell = 5; - SIB1_ss_PBCH_BlockPower = -60; - absoluteFrequencySSB = 0; - DL_FreqBandIndicatorNR = 15; - DL_absoluteFrequencyPointA = 15; - DL_offsetToCarrier = 15; - DL_SCS_SubcarrierSpacing = "kHz30"; - DL_SCS_SpecificCarrier_k0 = 0; - DL_carrierBandwidth = 15; - DL_locationAndBandwidth = 15; - DL_BWP_SubcarrierSpacing = "kHz30"; - DL_BWP_prefix_type = "NORMAL"; - UL_FreqBandIndicatorNR = 15; - UL_absoluteFrequencyPointA = 13; - UL_additionalSpectrumEmission = 3; - UL_p_Max = -1; - UL_frequencyShift7p5khz = "TRUE"; - UL_offsetToCarrier = 10; - UL_SCS_SubcarrierSpacing = "kHz30"; - UL_SCS_SpecificCarrier_k0 = 0; - UL_carrierBandwidth = 15; - UL_locationAndBandwidth = 15; - UL_BWP_SubcarrierSpacing = "kHz30"; - UL_BWP_prefix_type = "NORMAL"; - UL_timeAlignmentTimerCommon = "infinity"; - ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; - ServingCellConfigCommon_ssb_periodicityServingCell = 10; - ServingCellConfigCommon_dmrs_TypeA_Position = 2; - NIA_SubcarrierSpacing = "kHz15"; - ServingCellConfigCommon_ss_PBCH_BlockPower = -60; - referenceSubcarrierSpacing = "kHz15"; - dl_UL_TransmissionPeriodicity = "ms0p5"; - nrofDownlinkSlots = 10; - nrofDownlinkSymbols = 10; - nrofUplinkSlots = 10; - nrofUplinkSymbols = 10; - rach_totalNumberOfRA_Preambles = 63; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice = "oneEighth"; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf = 16; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one = 24; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two = 32; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen = 2; - rach_groupBconfigured = "ENABLE"; - rach_ra_Msg3SizeGroupA = 56; - rach_messagePowerOffsetGroupB = "dB0"; - rach_numberOfRA_PreamblesGroupA = 32; - rach_ra_ContentionResolutionTimer = 8; - rsrp_ThresholdSSB = 64; - rsrp_ThresholdSSB_SUL = 64; - prach_RootSequenceIndex_choice = "l839"; - prach_RootSequenceIndex_l839 = 0; - prach_RootSequenceIndex_l139 = 0; - prach_msg1_SubcarrierSpacing = "kHz30"; - restrictedSetConfig = "unrestrictedSet"; - msg3_transformPrecoding = "ENABLE"; - prach_ConfigurationIndex = 10; - prach_msg1_FDM = "one"; - prach_msg1_FrequencyStart = 10; - zeroCorrelationZoneConfig = 10; - preambleReceivedTargetPower = -150; - preambleTransMax = 6; - powerRampingStep = "dB0"; - ra_ResponseWindow = 8; - groupHoppingEnabledTransformPrecoding = "ENABLE"; - msg3_DeltaPreamble = 0; - p0_NominalWithGrant = 0; - PUSCH_TimeDomainResourceAllocation_k2 = 0; - PUSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PUSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - pucch_ResourceCommon = 0; - pucch_GroupHopping = "neither"; - hoppingId = 0; - p0_nominal = -30; - PDSCH_TimeDomainResourceAllocation_k0 = 2; - PDSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PDSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - rateMatchPatternId = 0; - RateMatchPattern_patternType = "bitmaps"; - symbolsInResourceBlock = "oneSlot"; - periodicityAndPattern = 2; - RateMatchPattern_controlResourceSet = 5; - RateMatchPattern_subcarrierSpacing = "kHz30"; - RateMatchPattern_mode = "dynamic"; - controlResourceSetZero = 0; - searchSpaceZero = 0; - searchSpaceSIB1 = 10; - searchSpaceOtherSystemInformation = 10; - pagingSearchSpace = 10; - ra_SearchSpace = 10; - PDCCH_common_controlResourceSetId = 5; - PDCCH_common_ControlResourceSet_duration = 2; - PDCCH_cce_REG_MappingType = "nonInterleaved"; - PDCCH_reg_BundleSize = 3; - PDCCH_interleaverSize = 3; - PDCCH_shiftIndex = 10; - PDCCH_precoderGranularity = "sameAsREG-bundle"; - PDCCH_TCI_StateId = 32; - tci_PresentInDCI = "ENABLE"; - PDCCH_DMRS_ScramblingID = 0; - SearchSpaceId = 10; - commonSearchSpaces_controlResourceSetId = 5; - SearchSpace_monitoringSlotPeriodicityAndOffset_choice = "sl1"; - SearchSpace_monitoringSlotPeriodicityAndOffset_value = 0; - SearchSpace_duration = 2; - SearchSpace_nrofCandidates_aggregationLevel1 = 0; - SearchSpace_nrofCandidates_aggregationLevel2 = 0; - SearchSpace_nrofCandidates_aggregationLevel4 = 0; - SearchSpace_nrofCandidates_aggregationLevel8 = 0; - SearchSpace_nrofCandidates_aggregationLevel16 = 0; - SearchSpace_searchSpaceType = "common"; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16 = 1; - Common_dci_Format2_3_monitoringPeriodicity = 1; - Common_dci_Format2_3_nrofPDCCH_Candidates = 1; - ue_Specific__dci_Formats = "formats0-0-And-1-0"; - RateMatchPatternLTE_CRS_carrierFreqDL = 6; - RateMatchPatternLTE_CRS_carrierBandwidthDL = 6; - RateMatchPatternLTE_CRS_nrofCRS_Ports = 1; - RateMatchPatternLTE_CRS_v_Shift = 0; - RateMatchPatternLTE_CRS_radioframeAllocationPeriod = 1; - RateMatchPatternLTE_CRS_radioframeAllocationOffset = 0; - RateMatchPatternLTE_CRS_subframeAllocation_choice = "oneFrame"; - } - ); - - - srb1_parameters : + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; + #spCellConfigCommon - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; + physCellId = 0; - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=2,L=3 + initialDLBWPstartSymbolAndLength_0 = 40; - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#0 = 839, 1 = 139 + prach_RootSequenceIndex_PR = 1; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } # ------- SCTP definitions SCTP : @@ -255,7 +238,7 @@ RUs = ( max_rxgain = 114; eNB_instances = [0]; sdr_addrs = "type=b200"; - + #clock_src = "external"; } ); @@ -264,20 +247,10 @@ THREAD_STRUCT = ( #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" - worker_config = "WORKER_DISABLE"; + worker_config = "WORKER_ENABLE"; } ); -NETWORK_CONTROLLER : -{ - FLEXRAN_ENABLED = "no"; - FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; - FLEXRAN_PORT = 2210; - FLEXRAN_CACHE = "/mnt/oai_agent_cache"; - FLEXRAN_AWAIT_RECONF = "no"; -}; - log_config : { global_log_level ="info"; 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 2c37e0d03f..aeb9e2be88 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 @@ -246,9 +246,11 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; } ); 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 ae17efc9bd..9420c488ec 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -254,7 +254,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2"; clock_src = "external"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf index 464ce6b9aa..0a6268f8a8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf @@ -240,7 +240,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 114; + max_rxgain = 75; eNB_instances = [0]; sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf index ea105d86b6..4c0d346360 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_enb.conf @@ -235,7 +235,7 @@ MACRLCs = ( THREAD_STRUCT = ( { - parallel_config = "PARALLEL_RU_L1_TRX_SPLITaaaaaa"; + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; worker_config = "ENABLE"; } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf index b63939add2..2eed408b53 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf @@ -23,7 +23,9 @@ gNBs = ssb_SubcarrierOffset = 31; //0; pdsch_AntennaPorts = 1; - + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + servingCellConfigCommon = ( { #spCellConfigCommon @@ -132,12 +134,12 @@ gNBs = # pusch-ConfigCommon (up to 16 elements) initialULBWPk2_0 = 2; initialULBWPmappingType_0 = 1 - # this is SS=0 L=11 + # this is SS=0 L=12 initialULBWPstartSymbolAndLength_0 = 55; initialULBWPk2_1 = 2; initialULBWPmappingType_1 = 1; - # this is SS=0 L=12 + # this is SS=0 L=11 initialULBWPstartSymbolAndLength_1 = 69; initialULBWPk2_2 = 7; @@ -266,8 +268,8 @@ RUs = ( THREAD_STRUCT = ( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" - //parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; - parallel_config = "PARALLEL_SINGLE_THREAD"; + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" worker_config = "WORKER_ENABLE"; } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf new file mode 100644 index 0000000000..f30c928448 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf @@ -0,0 +1,295 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -90; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = 0; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.196/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.196/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.196/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + time_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 4d89020077..e3b9797105 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -2675,6 +2675,15 @@ void set_function_spec_param(RU_t *ru) { exit(-1); } + if (ru->ifdevice.get_internal_parameter != NULL) { + void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); + if (t != NULL) + ru->fh_south_in = t; + t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); + if (t != NULL) + ru->fh_south_out = t; + } + malloc_IF4p5_buffer(ru); break; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4715a4e995..0d0dde4ac4 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -438,9 +438,6 @@ int restart_L1L2(module_id_t enb_id) { } RC.ru_mask |= (1 << ru->idx); - /* copy the changed frame parameters to the RU */ - /* TODO this should be done for all RUs associated to this eNB */ - memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS)); set_function_spec_param(RC.ru[enb_id]); /* reset the list of connected UEs in the MAC, since in this process with * loose all UEs (have to reconnect) */ @@ -556,6 +553,8 @@ int main ( int argc, char **argv ) MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); init_opt(); + // to make a graceful exit when ctrl-c is pressed + set_softmodem_sighandler(); check_clock(); #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" @@ -713,9 +712,12 @@ int main ( int argc, char **argv ) sync_var=0; pthread_cond_broadcast(&sync_cond); pthread_mutex_unlock(&sync_mutex); + create_tasks_mbms(1); config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); } - create_tasks_mbms(1); + else + create_tasks_mbms(1); + //create_tasks_mbms(1); // wait for end of program LOG_UI(ENB_APP,"TYPE TO TERMINATE\n"); @@ -725,7 +727,7 @@ int main ( int argc, char **argv ) // end of CI modifications //getchar(); if(IS_SOFTMODEM_DOFORMS) - load_softscope("enb"); + load_softscope("enb",NULL); itti_wait_tasks_end(); oai_exit=1; LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit); diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index a45ecd2298..54a9f4a669 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -759,7 +759,7 @@ int main( int argc, char **argv ) { } if(IS_SOFTMODEM_DOFORMS) - load_softscope("ue"); + load_softscope("ue",NULL); config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex); diff --git a/targets/RT/USER/rfsim.c b/targets/RT/USER/rfsim.c index a9a0912433..eb380b9518 100644 --- a/targets/RT/USER/rfsim.c +++ b/targets/RT/USER/rfsim.c @@ -337,6 +337,7 @@ void init_ue_devices(PHY_VARS_UE *UE) { void init_ocm(void) { module_id_t UE_id, ru_id; int CC_id; + double DS_TDL = .03; randominit(0); set_taus_seed(0); init_channelmod(); @@ -357,6 +358,7 @@ void init_ocm(void) { AWGN, N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_DL), N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_DL), + DS_TDL, 0.0, 0, 0); @@ -369,6 +371,7 @@ void init_ocm(void) { AWGN, N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_UL), N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_UL), + DS_TDL, 0.0, 0, 0); diff --git a/targets/RT/USER/stats.h b/targets/RT/USER/stats.h index 264c8f7af0..15ee4a8087 100644 --- a/targets/RT/USER/stats.h +++ b/targets/RT/USER/stats.h @@ -21,8 +21,8 @@ /* Header file generated by fdesign on Thu Aug 28 12:13:51 2014 */ -#ifndef FD_stats_form_h_ -#define FD_stats_form_h_ +#ifndef _TARGETS_RT_USER_STATS_H_ +#define _TARGETS_RT_USER_STATS_H_ #include @@ -43,4 +43,4 @@ typedef struct { extern FD_stats_form * create_form_stats_form( void ); -#endif /* FD_stats_form_h_ */ +#endif /* _TARGETS_RT_USER_STATS_H_ */