Merge branch 'integration_2026_w12' into 'develop'

Integration `2026.w12`

* !3985 Fix XNAP to avoid recompilation and unnecessary includes
* !3724 Better c style pss sss
* !3972 Resolve "Demote AssertFatal `PUCCH list is full` message to a warning"
* !3956 [FHI72] [xran F] Revert and simplify the code for Liteon FR2 interoperability
* !3970 Fix for NTN phy-test mode
* !3987 T: minor: remove target record_db from automatic building
* !3993 UE: Derive Serving Network Name from SIB1 PLMN
* !3997 vrtsim doc: clarify container requirements
* !3935 [FHI72] Fix long PRACH format
* !3998 Set rxgain to 0 in vrtsim
* !3964 CI: Add FHI7.2 phytest pipeline
* !4001 Remove unused ci-scripts/mysql4testresults/ dir and content
* !3999 bugfix: use proper pointer
* !3986 handle start symbol on non-zeroth downlink symbol for SIB1 for multiplexing pattern 3 configuration.
* !3957 replace static allocation of max antennas in a dynamic structure for gnb rach
* !3859 Delay compensation in SRS
* !3909 Adjust ssPBCH_BlockPower in FHI7.2 configs

Closes #1058

See merge request oai/openairinterface5g!3989
This commit is contained in:
Jaroslava Fiedlerova
2026-03-20 13:29:57 +00:00
88 changed files with 1198 additions and 1771 deletions
-4
View File
@@ -183,10 +183,6 @@ amarisoft_ue_2x2:
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_2x2/aw2s-multi-00102-2x2-v2.cfg & InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_2x2/aw2s-multi-00102-2x2-v2.cfg &
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
NetworkScript: ip netns exec ue1 ip a show dev pdn0 NetworkScript: ip netns exec ue1 ip a show dev pdn0
amarisoft_ue_fhi72:
Host: amariue
InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_fhi72_asue_2x2_benetel550/fhi72-multi-20897-2x2.cfg &
TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2
amarisoft_ue_1: amarisoft_ue_1:
Host: amariue Host: amariue
AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}' AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}'
+8 -2
View File
@@ -789,7 +789,7 @@ class Containerize():
logging.error('\u001B[1m Undeploying objects Failed\u001B[0m') logging.error('\u001B[1m Undeploying objects Failed\u001B[0m')
return success return success
def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds): def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None):
logging.info(f'Analyzing realtime stats from server: {node}') logging.info(f'Analyzing realtime stats from server: {node}')
yaml = self.yamlPath.strip('/') yaml = self.yamlPath.strip('/')
wd = f'{self.eNBSourceCodePath}/{yaml}' wd = f'{self.eNBSourceCodePath}/{yaml}'
@@ -797,7 +797,13 @@ class Containerize():
with cls_cmd.getConnection(node) as cmd: with cls_cmd.getConnection(node) as cmd:
services = GetDeployedServices(cmd, wd_yaml) services = GetDeployedServices(cmd, wd_yaml)
s, _ = services[0] # we simply assume something is deployed, if not Exception will report if not services:
raise RuntimeError("No deployed docker compose services found")
deployed_services = [s for s, _ in services]
s = service or deployed_services[0] # choose first service if not provided
if s not in deployed_services:
raise RuntimeError(f"Requested service {s} not found among services: {deployed_services}")
logging.info(f"Analyzing deployed service '{s}'")
# similar to BuildRunTests(), use docker cp to avoid problems with permissions # similar to BuildRunTests(), use docker cp to avoid problems with permissions
cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrL1_stats.log {wd}/') cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrL1_stats.log {wd}/')
l1_file = archiveArtifact(cmd, ctx, f"{wd}/nrL1_stats.log") l1_file = archiveArtifact(cmd, ctx, f"{wd}/nrL1_stats.log")
@@ -245,12 +245,12 @@ log_config :
}; };
fhi_72 = { fhi_72 = {
dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1"); dpdk_devices = ("0000:c3:11.0");
dpdk_iova_mode = "VA"; dpdk_iova_mode = "VA";
system_core = 0; system_core = 0;
io_core = 1; io_core = 1;
worker_cores = (2); worker_cores = (2);
ru_addr = ("98:ae:71:04:83:e3", "98:ae:71:04:83:e3"); ru_addr = ("98:ae:71:04:83:e3");
mtu = 9216; mtu = 9216;
fh_config = ({ fh_config = ({
T1a_cp_dl = (285, 470); T1a_cp_dl = (285, 470);
@@ -0,0 +1,28 @@
#this is a configuration file
#used to build real time processing statistics
#for 5G NR phy test (gNB terminate)
Title : Processing Time (us) from datalog_rt_stats.4x4.fhi72.yaml
ColNames :
- Metric
- Average; Max; Count
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
Ref :
tx_fhaul : 73.0
feptx_prec (per port, half_slot) : 46.0
L1 Tx processing : 371.7
DLSCH encoding : 196.9
L1 Rx processing : 578.0
UL segments decoding : 81.2
UL Indication : 0.4
Slot Indication : 14.3
PUSCH inner-receiver : 739.4
DeviationThreshold :
tx_fhaul : 0.25
feptx_prec (per port, half_slot) : 0.25
L1 Tx processing : 0.25
DLSCH encoding : 0.25
L1 Rx processing : 0.25
UL segments decoding : 0.25
UL Indication : 1.00
Slot Indication : 0.50
PUSCH inner-receiver : 0.25
+2 -1
View File
@@ -259,7 +259,8 @@ def ExecuteActionWithParam(action, ctx, node):
elif action == 'AnalyzeRTStats_Object': elif action == 'AnalyzeRTStats_Object':
yaml = test.findtext('stats_cfg') yaml = test.findtext('stats_cfg')
success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml) service = test.findtext('service')
success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml, service)
else: else:
logging.warning(f"unknown action {action}, skip step") logging.warning(f"unknown action {action}, skip step")
@@ -1,12 +0,0 @@
version: '2'
services:
mysql:
container_name: oaicicd_mysql
restart: always
image: mysql:latest
environment:
MYSQL_ROOT_PASSWORD: 'ucZBc2XRYdvEm59F'
ports:
- "3307:3306"
volumes:
- /home/oaicicd/mysql/data:/var/lib/mysql
@@ -1,33 +0,0 @@
import pymysql
import sys
from datetime import datetime
#This is the script used to write the test results to the mysql DB
#Called by Jenkins pipeline (jenkinsfile)
#Must be located in /home/oaicicid/mysql on the database host
#Usage from Jenkinsfile :
#python3 /home/oaicicd/mysql/sql_connect.py ${JOB_NAME} ${params.eNB_MR} ${params.eNB_Branch} ${env.BUILD_ID} ${env.BUILD_URL} ${StatusForDb} ''
class SQLConnect:
def __init__(self):
self.connection = pymysql.connect(
host='172.22.0.2',
user='root',
password = 'ucZBc2XRYdvEm59F',
db='oaicicd_tests',
port=3306
)
def put(self,TEST,MR,BRANCH,BUILD,BUILD_LINK,STATUS):
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
cur=self.connection.cursor()
cur.execute ('INSERT INTO test_results (TEST,MR,BRANCH,BUILD,BUILD_LINK,STATUS,DATE) VALUES (%s,%s,%s,%s,%s,%s,%s);' , (TEST, MR, BRANCH, BUILD, BUILD_LINK, STATUS, now))
self.connection.commit()
self.connection.close()
if __name__ == "__main__":
mydb=SQLConnect()
mydb.put(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5],sys.argv[6])
@@ -1,151 +0,0 @@
<!--
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
-->
<testCaseList>
<htmlTabRef>test-5g-fhi72-metanoia-2x2</htmlTabRef>
<htmlTabName>100 MHz TDD SA METANOIA</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<testCase>
<class>Custom_Script</class>
<desc>Setup sriov and network interfaces Metanoia</desc>
<node>cacofonix</node>
<script>yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_sriov_metanoia.sh</script>
</testCase>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace for server 0</desc>
<node>cacofonix</node>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Deploy gNB (TDD/Band78/100MHz/Metanoia) in a container</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb</yaml_path>
</testCase>
<testCase>
<class>Attach_UE</class>
<desc>Attach UE</desc>
<id>up2-fhi72</id>
</testCase>
<testCase>
<class>Ping</class>
<desc>Ping: 100 pings in 10 sec</desc>
<id>up2-fhi72</id>
<svr_id>oc-cn5g-20897</svr_id>
<ping_args>-c 100 -i 0.1</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_rttavg_threshold>15</ping_rttavg_threshold>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/570Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 570M -t 30 -R</iperf_args>
<id>up2-fhi72</id>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
<svr_id>oc-cn5g-20897</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/100Mbps/UDP)(30 sec)</desc>
<iperf_args>-u -b 100M -t 30</iperf_args>
<id>up2-fhi72</id>
<iperf_packetloss_threshold>20</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
<svr_id>oc-cn5g-20897</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (DL/TCP)(30 sec)</desc>
<iperf_args>-t 30 -R</iperf_args>
<id>up2-fhi72</id>
<iperf_tcp_rate_target>80</iperf_tcp_rate_target>
<svr_id>oc-cn5g-20897</svr_id>
</testCase>
<testCase>
<class>Iperf</class>
<desc>iperf (UL/TCP)(30 sec)</desc>
<iperf_args>-t 30</iperf_args>
<id>up2-fhi72</id>
<iperf_tcp_rate_target>80</iperf_tcp_rate_target>
<svr_id>oc-cn5g-20897</svr_id>
</testCase>
<testCase>
<class>Detach_UE</class>
<always_exec>true</always_exec>
<desc>Detach UE</desc>
<id>up2-fhi72</id>
</testCase>
<testCase>
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>5</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
<desc>Undeploy gNB</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>Custom_Script</class>
<always_exec>true</always_exec>
<desc>Set CPU to idle state, set kernel parameters to default values</desc>
<node>cacofonix</node>
<script>yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_cleanup.sh</script>
</testCase>
</testCaseList>
@@ -27,9 +27,9 @@
<testCase> <testCase>
<class>Custom_Script</class> <class>Custom_Script</class>
<desc>Setup sriov and network interfaces VVDN</desc> <desc>Configure system for low-latency RT performance</desc>
<node>cacofonix</node> <node>cacofonix</node>
<script>yaml_files/sa_fhi_7.2_vvdn_gnb/setup_sriov_vvdn.sh</script> <script>yaml_files/sa_fhi_7.2_vvdn_gnb/setup_config.sh</script>
</testCase> </testCase>
<testCase> <testCase>
@@ -25,13 +25,6 @@
<htmlTabName>Timing phytest 100 MHz 4x4 FHI7.2</htmlTabName> <htmlTabName>Timing phytest 100 MHz 4x4 FHI7.2</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon> <htmlTabIcon>tasks</htmlTabIcon>
<testCase>
<class>Custom_Script</class>
<desc>Setup sriov and network interfaces for dummy (no RU)</desc>
<node>bulbul</node>
<script>yaml_files/phytest_fhi72/setup_sriov_dummy.sh</script>
</testCase>
<testCase> <testCase>
<class>Pull_Local_Registry</class> <class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc> <desc>Pull Images from Local Registry</desc>
@@ -63,6 +56,7 @@
<class>AnalyzeRTStats_Object</class> <class>AnalyzeRTStats_Object</class>
<desc>Analyze Real-Time Stats</desc> <desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.100.4x4.fhi72.yaml</stats_cfg> <stats_cfg>datalog_rt_stats.100.4x4.fhi72.yaml</stats_cfg>
<service>oai-gnb</service>
<node>bulbul</node> <node>bulbul</node>
</testCase> </testCase>
@@ -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
-->
<testCaseList>
<htmlTabRef>gNB-PHY-Test-100-4x4-FHI72</htmlTabRef>
<htmlTabName>Timing phytest 100 MHz 4x4 FHI7.2</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<testCase>
<class>Custom_Script</class>
<desc>Configure system for low-latency RT performance</desc>
<node>cacofonix</node>
<script>yaml_files/phytest_fhi72_cacofonix/setup_config.sh</script>
</testCase>
<testCase>
<class>Pull_Local_Registry</class>
<desc>Pull Images from Local Registry</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace</desc>
<node>cacofonix</node>
</testCase>
<testCase>
<class>Deploy_Object</class>
<desc>Initialize gNB FHI7.2</desc>
<node>cacofonix</node>
<yaml_path>ci-scripts/yaml_files/phytest_fhi72_cacofonix</yaml_path>
<services>oai-gnb</services>
</testCase>
<testCase>
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase>
<class>AnalyzeRTStats_Object</class>
<desc>Analyze Real-Time Stats</desc>
<stats_cfg>datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml</stats_cfg>
<service>oai-gnb</service>
<node>cacofonix</node>
</testCase>
<testCase>
<class>Undeploy_Object</class>
<node>cacofonix</node>
<always_exec>true</always_exec>
<desc>Terminate gNB</desc>
<yaml_path>ci-scripts/yaml_files/phytest_fhi72_cacofonix</yaml_path>
<analysis>
<services>oai-gnb=EndsWithBye</services>
</analysis>
</testCase>
<testCase>
<class>Clean_Test_Server_Images</class>
<always_exec>true</always_exec>
<desc>Clean Test Images on Test Server</desc>
<node>cacofonix</node>
<images>oai-gnb-fhi72</images>
</testCase>
<testCase>
<class>Custom_Script</class>
<always_exec>true</always_exec>
<desc>Set CPU to idle state, set kernel parameters to default values</desc>
<node>cacofonix</node>
<script>yaml_files/phytest_fhi72_cacofonix/setup_cleanup.sh</script>
</testCase>
</testCaseList>
@@ -1,4 +1,16 @@
services: services:
dpdk-init:
image: docker.io/library/oai-dpdk-init:latest
network_mode: host
container_name: dpdk-init
entrypoint: "/tmp/setup_sriov.sh"
privileged: true
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ./setup_sriov_dummy.sh:/tmp/setup_sriov.sh
- /lib/modules:/lib/modules
- /usr/lib/modules:/usr/lib/modules
oai-gnb: oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-fhi72}:${TAG:-develop} image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-fhi72}:${TAG:-develop}
container_name: oai-gnb-phytest container_name: oai-gnb-phytest
@@ -12,11 +24,24 @@ services:
devices: devices:
- /dev/vfio:/dev/vfio/ - /dev/vfio:/dev/vfio/
volumes: volumes:
- ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4-4L-vvdn.conf:/opt/oai-gnb/etc/gnb.conf - ../../conf_files/gnb.band77.273prb.fhi72.4x4-vvdn-phytest.conf:/opt/oai-gnb/etc/gnb.conf
- /dev/hugepages:/dev/hugepages - /dev/hugepages:/dev/hugepages
cpuset: "8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23" cpuset: "8-23"
networks: ["public_net"]
depends_on:
dpdk-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: /bin/bash -c "pgrep nr-softmodem" test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
networks:
public_net:
driver: bridge
name: ci-physim
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "ci-physim"
@@ -19,19 +19,19 @@ IF_NAME=ens1f0np0
C_U_PLANE_MAC_ADD=22:11:55:33:99:55 C_U_PLANE_MAC_ADD=22:11:55:33:99:55
C_U_PLANE_VLAN=123 C_U_PLANE_VLAN=123
MTU=9000 MTU=9000
DPDK_DEVBIND_PREFIX=/home/oaicicd/test/dpdk-stable-22.11.7/bin DPDK_DEVBIND_PREFIX=/usr/local/bin
NUM_VFs=1 NUM_VFs=1
sudo ethtool -G $IF_NAME rx 8160 tx 8160 ethtool -G $IF_NAME rx 8160 tx 8160
sudo sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs" sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs"
sudo sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs" sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs"
C_U_PLANE_PCI=$(pci_addr $IF_NAME 0) C_U_PLANE_PCI=$(pci_addr $IF_NAME 0)
# this next 2 lines is for C/U planes # this next 2 lines is for C/U planes
sudo ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU
sleep 1 sleep 1
sudo modprobe iavf modprobe iavf
sudo ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI
sudo modprobe vfio-pci modprobe vfio-pci
sudo ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI
echo "Successfully configured C-PLANE and U-PLANE: echo "Successfully configured C-PLANE and U-PLANE:
- C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI" - C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI"
exit 0 exit 0
@@ -0,0 +1,47 @@
services:
dpdk-init:
image: docker.io/library/oai-dpdk-init:latest
network_mode: host
container_name: dpdk-init
entrypoint: "/tmp/setup_sriov.sh"
privileged: true
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ./setup_sriov_dummy.sh:/tmp/setup_sriov.sh
- /lib/modules:/lib/modules
- /usr/lib/modules:/usr/lib/modules
oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-fhi72}:${TAG:-develop}
container_name: oai-gnb-phytest
cap_add:
- IPC_LOCK
- SYS_NICE
cap_drop:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: --phy-test -q -M 273 -m 27 -l 2 -D 231 -T 273 -t 16 -L 2 -U 528 --log_config.global_log_options level,nocolor,time --thread-pool 7,8,9,10,11,12
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf:/opt/oai-gnb/etc/gnb.conf
- /dev/hugepages:/dev/hugepages
cpuset: "0-12"
networks: ["public_net"]
depends_on:
dpdk-init:
condition: service_completed_successfully
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
timeout: 5s
retries: 5
networks:
public_net:
driver: bridge
name: ci-physim
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "ci-physim"
@@ -0,0 +1,4 @@
set -e
sudo cpupower idle-set -D 0 > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=-1
sudo sysctl kernel.timer_migration=0
@@ -0,0 +1,38 @@
#!/bin/sh
set -eu
pci_addr()
{
PF_IF=$1
VF_INDEX=$2
SYSFS_PATH="/sys/class/net/${PF_IF}/device/virtfn${VF_INDEX}"
if [ ! -e "$SYSFS_PATH" ]; then
echo "VF $VF_INDEX not found for interface $PF_IF"
exit 1
fi
PCI_ADDR=$(basename "$(readlink "$SYSFS_PATH")")
echo "$PCI_ADDR"
}
IF_NAME=ens7f1
## O-DU C Plane MAC ADDR and VLAN
C_U_PLANE_MAC_ADD=22:11:55:33:99:55
C_U_PLANE_VLAN=123
MTU=9000
DPDK_DEVBIND_PREFIX=/usr/local/bin
NUM_VFs=1
ethtool -G $IF_NAME rx 8160 tx 8160
sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs"
sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs"
C_U_PLANE_PCI=$(pci_addr $IF_NAME 0)
# this next 2 lines is for C/U planes
ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU
sleep 1
modprobe iavf
${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI
modprobe vfio-pci
${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI
echo "Successfully configured C-PLANE and U-PLANE:
- C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI"
exit 0
@@ -1,15 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI O-RAN 7.2 Front-haul Docker Compose</font></b>
</td>
</tr>
</table>
For instructions on OAI gNB Docker deployment with FH 7.2 RU, please refer to the [README](../sa_fhi_7.2_vvdn_gnb/README.md).
@@ -1,42 +0,0 @@
services:
oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop}
cap_add:
- SYS_ADMIN
- IPC_LOCK
- SYS_NICE
cap_drop:
- ALL
container_name: oai-gnb
environment:
TZ: Europe/Paris
USE_ADDITIONAL_OPTIONS: --thread-pool 6,7,8,9
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ../../conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf:/opt/oai-gnb/etc/gnb.conf
- /dev/hugepages:/dev/hugepages
# Please change these values based on your system
cpuset: "0,1,2,3,4,5,6,7,8,9"
networks:
oai-net:
ipv4_address: 172.21.18.20
healthcheck:
test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh"
start_period: 15s
start_interval: 500ms
interval: 5s
timeout: 5s
retries: 10
networks:
oai-net:
driver: macvlan
name: oai-net
ipam:
config:
- subnet: "172.21.16.0/22"
ip_range: "172.21.18.20/32"
gateway: "172.21.19.254"
driver_opts:
com.docker.network.bridge.name: "oai-net"
parent: ens7f0
@@ -1,22 +0,0 @@
set -e
sudo cpupower idle-set -D 0 > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=-1
sudo sysctl kernel.timer_migration=0
sudo ethtool -G ens7f1 rx 8160
sudo ethtool -G ens7f1 tx 8160
sudo ifconfig ens7f1 mtu 9216
sudo sh -c 'echo 0 > /sys/class/net/ens7f1/device/sriov_numvfs'
sudo sh -c 'echo 2 > /sys/class/net/ens7f1/device/sriov_numvfs'
sudo modprobe -r iavf
sudo modprobe iavf
# this next 2 lines is for C/U planes
sudo ip link set ens7f1 vf 0 mac 00:11:22:33:44:66 vlan 3 qos 0 spoofchk off mtu 9216
sudo ip link set ens7f1 vf 1 mac 00:11:22:33:44:67 vlan 3 qos 0 spoofchk off mtu 9216
sleep 1
# These are the DPDK bindings for C/U-planes on vlan 3
sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.0
sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.1
sudo modprobe vfio-pci
sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.0
sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.1
exit 0
@@ -1,87 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI O-RAN 7.2 Front-haul Docker Compose</font></b>
</td>
</tr>
</table>
![Docker deploy 7.2](../../../doc/images/docker-deploy-oai-7-2.png)
This docker-compose is designed to use `OAI-gNB` with a 7.2 compatible Radio Unit. Before using this docker compose you have to configure
the host machine as per the [ORAN_FHI7.2_Tutorial](../../../doc/ORAN_FHI7.2_Tutorial.md). The container image used by the docker compose file is tested only on `Ubuntu 22.04` and `RHEL 9.4` docker host.
## Build Image (Optional)
Refer to [OAI Docker/Podman Build and Usage Procedures](../../../docker/README.md)
## Configure Networking
### SR-IOV Virtual Functions (VFs)
In docker-compose environment there is no automated method
to configure the VFs on the fly. The user will have to manually configure
C/U plane VFs before starting the container `OAI-gNB`.
You can follow the step
[configure-network-interfaces-and-dpdk-vfs](../../../doc/ORAN_FHI7.2_Tutorial.md#configure-network-interfaces-and-dpdk-vfs).
### Interface towards AMF (N2)
For `N2` interface we are using `macvlan` driver of docker.
You can use the `bridge` driver, in situation
- When the core network is running on the same machine
- or different machine but you have configured
needed `ip route` and forwarding to access the core network from RAN host.
To configure docker `macvlan` network
you need to choose `ipam.config` and `driver_opts.parent` are per your environment
```
oai-net:
driver: macvlan
name: oai-net
ipam:
config:
- subnet: "172.21.16.0/22"
ip_range: "172.21.18.20/32"
gateway: "172.21.19.254"
driver_opts:
com.docker.network.bridge.name: "oai-net"
parent: ens7f0
```
To configure `bridge` network you need to choose `ipam.config.subnet` as per your environment.
```
oai-net:
driver: bridge
name: oai-net
ipam:
config:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "oai-net"
```
## Deploy OAI-gNB Container
The [configuration file](../../conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf) used by docker compose is configured for Metanoia RU.
```bash
docker-compose up -d
```
To check the logs
```bash
docker logs oai-gnb -f
```
@@ -1,41 +0,0 @@
services:
oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop}
cap_add:
- IPC_LOCK
- SYS_NICE
cap_drop:
- ALL
container_name: oai-gnb
environment:
TZ: Europe/Paris
USE_ADDITIONAL_OPTIONS: --thread-pool 7,8,9,10,11,12
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf:/opt/oai-gnb/etc/gnb.conf
- /dev/hugepages:/dev/hugepages
# Please change these values based on your system
cpuset: "0,1,2,3,4,5,6,7,8,9,10,11,12"
networks:
oai-net:
ipv4_address: 172.21.18.20
healthcheck:
test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh"
start_period: 15s
start_interval: 500ms
interval: 5s
timeout: 5s
retries: 10
networks:
oai-net:
driver: macvlan
name: oai-net
ipam:
config:
- subnet: "172.21.16.0/22"
ip_range: "172.21.18.20/32"
gateway: "172.21.19.254"
driver_opts:
com.docker.network.bridge.name: "oai-net"
parent: ens7f0
@@ -1,5 +0,0 @@
set -e
sudo cpupower idle-set -E > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=950000
sudo sysctl kernel.timer_migration=1
exit 0
@@ -1,20 +0,0 @@
set -e
sudo cpupower idle-set -D 0 > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=-1
sudo sysctl kernel.timer_migration=0
sudo ethtool -G ens7f1 rx 8160 tx 8160
sudo sh -c 'echo 0 > /sys/class/net/ens7f1/device/sriov_numvfs'
sudo sh -c 'echo 3 > /sys/class/net/ens7f1/device/sriov_numvfs'
sudo modprobe -r iavf
sudo modprobe iavf
# this next 2 lines is for C/U planes
sudo ip link set ens7f1 vf 0 mac 00:11:22:33:44:55 vlan 3 spoofchk off mtu 9000
sudo ip link set ens7f1 vf 1 mac 00:11:22:33:44:54 vlan 3 spoofchk off mtu 9000
sleep 1
# These are the DPDK bindings for C/U-planes on vlan 1
sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.0
sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.1
sudo modprobe vfio-pci
sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.0
sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.1
exit 0
@@ -1,4 +1,16 @@
services: services:
dpdk-init:
image: docker.io/library/oai-dpdk-init:latest
network_mode: host
container_name: dpdk-init
entrypoint: "/tmp/setup_sriov.sh"
privileged: true
devices:
- /dev/vfio:/dev/vfio/
volumes:
- ./setup_sriov_vvdn.sh:/tmp/setup_sriov.sh
- /lib/modules:/lib/modules
- /usr/lib/modules:/usr/lib/modules
oai-gnb: oai-gnb:
image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop} image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop}
cap_add: cap_add:
@@ -16,10 +28,13 @@ services:
- ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf:/opt/oai-gnb/etc/gnb.conf - ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf:/opt/oai-gnb/etc/gnb.conf
- /dev/hugepages:/dev/hugepages - /dev/hugepages:/dev/hugepages
# Please change these values based on your system # Please change these values based on your system
cpuset: "0,1,2,3,4,5,6,7,8,9,10,11,12" cpuset: "0-12"
networks: networks:
oai-net: oai-net:
ipv4_address: 172.21.18.20 ipv4_address: 172.21.18.20
depends_on:
dpdk-init:
condition: service_completed_successfully
healthcheck: healthcheck:
test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh"
start_period: 15s start_period: 15s
View File
@@ -0,0 +1,4 @@
set -e
sudo cpupower idle-set -D 0 > /dev/null
sudo sysctl kernel.sched_rt_runtime_us=-1
sudo sysctl kernel.timer_migration=0
+34 -18
View File
@@ -1,21 +1,37 @@
set -e #!/bin/sh
sudo cpupower idle-set -D 0 > /dev/null set -eu
sudo sysctl kernel.sched_rt_runtime_us=-1
sudo sysctl kernel.timer_migration=0 pci_addr()
sudo ethtool -G ens7f1 rx 8160 {
sudo ethtool -G ens7f1 tx 8160 PF_IF=$1
sudo sh -c 'echo 0 > /sys/class/net/ens7f1/device/sriov_numvfs' VF_INDEX=$2
sudo sh -c 'echo 2 > /sys/class/net/ens7f1/device/sriov_numvfs' SYSFS_PATH="/sys/class/net/${PF_IF}/device/virtfn${VF_INDEX}"
sudo modprobe -r iavf
sudo modprobe iavf if [ ! -e "$SYSFS_PATH" ]; then
echo "VF $VF_INDEX not found for interface $PF_IF"
exit 1
fi
PCI_ADDR=$(basename "$(readlink "$SYSFS_PATH")")
echo "$PCI_ADDR"
}
IF_NAME=ens7f1
## O-DU C Plane MAC ADDR and VLAN
C_U_PLANE_MAC_ADD=76:76:64:6e:00:01
C_U_PLANE_VLAN=4
MTU=9000
DPDK_DEVBIND_PREFIX=/usr/local/bin
NUM_VFs=1
ethtool -G $IF_NAME rx 8160 tx 8160
sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs"
sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs"
C_U_PLANE_PCI=$(pci_addr $IF_NAME 0)
# this next 2 lines is for C/U planes # this next 2 lines is for C/U planes
sudo ip link set ens7f1 vf 0 mac 76:76:64:6e:00:01 vlan 4 spoofchk off mtu 9216 ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU
sudo ip link set ens7f1 vf 1 mac 76:76:64:6e:00:00 vlan 4 spoofchk off mtu 9216
sleep 1 sleep 1
# These are the DPDK bindings for C/U-planes on vlan 4 modprobe iavf
sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.0 ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI
sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.1 modprobe vfio-pci
sudo modprobe vfio-pci ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI
sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.0 echo "Successfully configured C-PLANE and U-PLANE:
sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.1 - C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI"
exit 0 exit 0
@@ -1,5 +1,5 @@
diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h
index ac5f471..b1acb26 100644 index ac5f471..fe27425 100644
--- a/fhi_lib/app/src/common.h --- a/fhi_lib/app/src/common.h
+++ b/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
@@ -7,7 +7,7 @@ index ac5f471..b1acb26 100644
#include <rte_mbuf.h> #include <rte_mbuf.h>
-#define VERSIONX "oran_f_release_v1.0" -#define VERSIONX "oran_f_release_v1.0"
+#define VERSIONX "oran_f_release_v1.8" +#define VERSIONX "oran_f_release_v1.9"
#define APP_O_DU 0 #define APP_O_DU 0
#define APP_O_RU 1 #define APP_O_RU 1
@@ -173,20 +173,18 @@ index eccc4ae..a97fdc6 100644
CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF) CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF)
CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF) CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF)
diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h
index bacf597..18597d6 100644 index bacf597..c37e132 100644
--- a/fhi_lib/lib/api/xran_fh_o_du.h --- a/fhi_lib/lib/api/xran_fh_o_du.h
+++ b/fhi_lib/lib/api/xran_fh_o_du.h +++ b/fhi_lib/lib/api/xran_fh_o_du.h
@@ -141,8 +141,8 @@ extern "C" { @@ -141,7 +141,7 @@ extern "C" {
#define XRAN_MAX_SECTIONS_PER_SYM (XRAN_MAX_SECTIONS_PER_SLOT) /**< Max number of different sections in single slot (section may be equal to RB allocation for UE) */ #define XRAN_MAX_SECTIONS_PER_SYM (XRAN_MAX_SECTIONS_PER_SLOT) /**< Max number of different sections in single slot (section may be equal to RB allocation for UE) */
#define XRAN_MIN_SECTIONS_PER_SYM (XRAN_MIN_SECTIONS_PER_SLOT) /**< Min number of different sections in single slot (section may be equal to RB allocation for UE) */ #define XRAN_MIN_SECTIONS_PER_SYM (XRAN_MIN_SECTIONS_PER_SLOT) /**< Min number of different sections in single slot (section may be equal to RB allocation for UE) */
-#define XRAN_MAX_FRAGMENT (4) /**< Max number of fragmentations in single symbol */ -#define XRAN_MAX_FRAGMENT (4) /**< Max number of fragmentations in single symbol */
-#define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */
+#define XRAN_MAX_FRAGMENT (7) /**< Max number of fragmentations in single symbol */ +#define XRAN_MAX_FRAGMENT (7) /**< Max number of fragmentations in single symbol */
+#define XRAN_MAX_SET_BFWS (1) //(64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ #define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */
#define XRAN_MAX_PKT_BURST (448+4) /**< 4x14x8 symbols per ms */ #define XRAN_MAX_PKT_BURST (448+4) /**< 4x14x8 symbols per ms */
#define XRAN_N_MAX_BUFFER_SEGMENT XRAN_MAX_PKT_BURST /**< Max number of segments per ms */
@@ -419,6 +419,7 @@ struct xran_io_cfg { @@ -419,6 +419,7 @@ struct xran_io_cfg {
uint16_t num_rxq; /**< number of RX queues per VF */ uint16_t num_rxq; /**< number of RX queues per VF */
char *dpdk_dev[XRAN_VF_MAX]; /**< VFs devices */ char *dpdk_dev[XRAN_VF_MAX]; /**< VFs devices */
@@ -195,15 +193,7 @@ index bacf597..18597d6 100644
int32_t bbdev_mode; /**< DPDK for BBDev */ int32_t bbdev_mode; /**< DPDK for BBDev */
uint32_t dpdkIoVaMode; /**< IOVA Mode */ uint32_t dpdkIoVaMode; /**< IOVA Mode */
uint32_t dpdkMemorySize; /**< DPDK max memory allocation */ uint32_t dpdkMemorySize; /**< DPDK max memory allocation */
@@ -713,6 +714,7 @@ struct xran_fh_config { @@ -1193,6 +1194,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb,
uint16_t max_sections_per_slot; /**< M-Plane settings for section */
uint16_t max_sections_per_symbol; /**< M-Plane settings for section */
int32_t RunSlotPrbMapBySymbolEnable; /**< enable prb mapping by symbol with multisection*/
+ uint8_t LiteOnIgnoreUPSectionIdEnable; /**< handle LiteOn issue where section id on UP packet is wrongly set to 13. */
uint8_t dssEnable; /**< enable DSS (extension-9) */
uint8_t dssPeriod; /**< DSS pattern period for LTE/NR */
@@ -1193,6 +1195,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb,
*/ */
int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond);
@@ -594,7 +584,7 @@ index 08660f3..b5de607 100644
time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT); time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT);
diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c
index dc40ad9..1b88013 100644 index dc40ad9..5968d01 100644
--- a/fhi_lib/lib/src/xran_common.c --- a/fhi_lib/lib/src/xran_common.c
+++ b/fhi_lib/lib/src/xran_common.c +++ b/fhi_lib/lib/src/xran_common.c
@@ -31,7 +31,10 @@ @@ -31,7 +31,10 @@
@@ -608,110 +598,7 @@ index dc40ad9..1b88013 100644
#include <rte_mbuf.h> #include <rte_mbuf.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
@@ -49,6 +52,8 @@ @@ -714,11 +717,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
#include "xran_printf.h"
#include "xran_mlog_lnx.h"
+#include "xran_frame_struct.h"
+
static struct timespec sleeptime = {.tv_nsec = 1E3 }; /* 1 us */
extern int32_t first_call;
@@ -529,13 +534,30 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru
if (pRbMap)
{
/** Get the prb_elem_id */
+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ if(0 == p_dev_ctx->LiteOnIgnoreUPSectionIdEnable) {
+ section_id_tmp = prb_elem_id_tmp = sect_id[i];
+ } else {
+ u_int8_t mixed_ul_sym_start = 0;
+ if (xran_fs_get_slot_type(xran_port, CC_ID[i], tti, XRAN_SLOT_TYPE_SP)) {
+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID[i], tti);
+ }
+ u_int8_t section_id_tmp = symb_id[i] - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ //Note for future reference when using MTU 1500
+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ }
+
total_sections=0;
if(pRbMap->prbMap[0].bf_weight.extType == 1)
{
for(idxElm=0 ; idxElm < pRbMap->nPrbElm ; idxElm++)
{
total_sections += pRbMap->prbMap[idxElm].bf_weight.numSetBFWs;
- if(total_sections >= (sect_id[i] + 1))
+ if(total_sections >= (/*sect_id[i]*/ prb_elem_id_tmp + 1))
{
prb_elem_id[i] = idxElm;
break;
@@ -544,12 +566,12 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru
}
else
{
- prb_elem_id[i] = sect_id[i];
+ prb_elem_id[i] = prb_elem_id_tmp; /*sect_id[i];*/
}
if (prb_elem_id[i] >= pRbMap->nPrbElm)
{
- print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", sect_id[i], prb_elem_id[i], pRbMap->nPrbElm);
+ print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", /*sect_id[i]*/ section_id_tmp, prb_elem_id[i], pRbMap->nPrbElm);
ret_data[i] = MBUF_FREE;
continue;
}
@@ -615,13 +637,30 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru
if (pRbMap)
{
/** Get the prb_elem_id */
+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ if(0 == p_dev_ctx->LiteOnIgnoreUPSectionIdEnable) {
+ section_id_tmp = prb_elem_id_tmp = sect_id[i];
+ } else {
+ u_int8_t mixed_ul_sym_start = 0;
+ if (xran_fs_get_slot_type(xran_port, CC_ID[i], tti, XRAN_SLOT_TYPE_SP)) {
+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID[i], tti);
+ }
+ u_int8_t section_id_tmp = symb_id[i] - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ //Note for future reference when using MTU 1500
+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ }
+
total_sections=0;
if(pRbMap->prbMap[0].bf_weight.extType == 1)
{
for(idxElm=0 ; idxElm < pRbMap->nPrbElm ; idxElm++)
{
total_sections += pRbMap->prbMap[idxElm].bf_weight.numSetBFWs;
- if(total_sections >= (sect_id[i] + 1))
+ if(total_sections >= (/*sect_id[i]*/ prb_elem_id_tmp + 1))
{
prb_elem_id[i] = idxElm;
break;
@@ -630,12 +669,12 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru
}
else
{
- prb_elem_id[i] = sect_id[i];
+ prb_elem_id[i] = prb_elem_id_tmp; /*sect_id[i];*/
}
if (prb_elem_id[i] >= pRbMap->nPrbElm)
{
- print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", sect_id[i], prb_elem_id[i], pRbMap->nPrbElm);
+ print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", /*sect_id[i]*/ section_id_tmp, prb_elem_id[i], pRbMap->nPrbElm);
ret_data[i] = MBUF_FREE;
continue;
}
@@ -714,11 +753,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
uint8_t compMeth = 0; uint8_t compMeth = 0;
uint8_t iqWidth = 0; uint8_t iqWidth = 0;
@@ -726,7 +613,7 @@ index dc40ad9..1b88013 100644
if(first_call == 0) if(first_call == 0)
return ret; return ret;
@@ -733,9 +775,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) @@ -733,9 +739,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
return MBUF_FREE; return MBUF_FREE;
num_bytes = xran_extract_iq_samples(pkt, &iq_samp_buf, num_bytes = xran_extract_iq_samples(pkt, &iq_samp_buf,
@@ -738,7 +625,7 @@ index dc40ad9..1b88013 100644
if (num_bytes <= 0) if (num_bytes <= 0)
{ {
print_err("num_bytes is wrong [%d]\n", num_bytes); print_err("num_bytes is wrong [%d]\n", num_bytes);
@@ -781,10 +823,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) @@ -781,10 +787,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
else else
{ {
@@ -752,7 +639,7 @@ index dc40ad9..1b88013 100644
#ifndef FCN_ADAPT #ifndef FCN_ADAPT
if(valid_res != 0) if(valid_res != 0)
{ {
@@ -807,8 +848,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) @@ -807,8 +812,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid)
PrachCfg = &(p_dev_ctx->PrachCPConfig); PrachCfg = &(p_dev_ctx->PrachCPConfig);
} }
@@ -762,7 +649,7 @@ index dc40ad9..1b88013 100644
/* PRACH packet has ruportid = num_eAxc + ant_id */ /* PRACH packet has ruportid = num_eAxc + ant_id */
Ant_ID -= PrachCfg->eAxC_offset; Ant_ID -= PrachCfg->eAxC_offset;
symbol_total_bytes[p_dev_ctx->xran_port_id][CC_ID][Ant_ID] += num_bytes; symbol_total_bytes[p_dev_ctx->xran_port_id][CC_ID][Ant_ID] += num_bytes;
@@ -1412,7 +1452,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc @@ -1412,7 +1416,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc
if(XRAN_FILTERINDEX_PRACH_ABC == pPrachCPConfig->filterIdx) if(XRAN_FILTERINDEX_PRACH_ABC == pPrachCPConfig->filterIdx)
{ {
timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu
@@ -771,7 +658,7 @@ index dc40ad9..1b88013 100644
timeOffset += 16; timeOffset += 16;
} }
else else
@@ -1547,8 +1587,7 @@ int32_t ring_processing_func(void* args) @@ -1547,8 +1551,7 @@ int32_t ring_processing_func(void* args)
for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i++){ for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i++){
for(qi = 0; qi < ctx->rxq_per_port[i]; qi++) { for(qi = 0; qi < ctx->rxq_per_port[i]; qi++) {
@@ -1081,18 +968,10 @@ index 4acade1..c939edc 100644
for(i = 0; i < xran_ports_num; i++){ for(i = 0; i < xran_ports_num; i++){
g_xran_dev_ctx[i] = pCtx; g_xran_dev_ctx[i] = pCtx;
diff --git a/fhi_lib/lib/src/xran_dev.h b/fhi_lib/lib/src/xran_dev.h diff --git a/fhi_lib/lib/src/xran_dev.h b/fhi_lib/lib/src/xran_dev.h
index 0371a53..778b38d 100644 index 0371a53..b417619 100644
--- a/fhi_lib/lib/src/xran_dev.h --- a/fhi_lib/lib/src/xran_dev.h
+++ b/fhi_lib/lib/src/xran_dev.h +++ b/fhi_lib/lib/src/xran_dev.h
@@ -201,6 +201,7 @@ struct __rte_cache_aligned xran_device_ctx @@ -254,6 +254,11 @@ struct __rte_cache_aligned xran_device_ctx
int32_t DynamicSectionEna;
int32_t RunSlotPrbMapBySymbolEnable;
+ uint8_t LiteOnIgnoreUPSectionIdEnable; /**< handle LiteOn issue where section id on UP packet is wrongly set to 13. */
int64_t offset_sec;
int64_t offset_nsec; //offset to GPS time calcuated based on alpha and beta
uint32_t interval_us_local;
@@ -254,6 +255,11 @@ struct __rte_cache_aligned xran_device_ctx
int32_t sym_up; /**< when we start sym 0 of up with respect to OTA time as measured in symbols */ int32_t sym_up; /**< when we start sym 0 of up with respect to OTA time as measured in symbols */
int32_t sym_up_ul; int32_t sym_up_ul;
@@ -1105,45 +984,17 @@ index 0371a53..778b38d 100644
void *TtiCbParam[XRAN_CB_MAX]; void *TtiCbParam[XRAN_CB_MAX];
uint32_t SkipTti[XRAN_CB_MAX]; uint32_t SkipTti[XRAN_CB_MAX];
diff --git a/fhi_lib/lib/src/xran_frame_struct.c b/fhi_lib/lib/src/xran_frame_struct.c diff --git a/fhi_lib/lib/src/xran_frame_struct.c b/fhi_lib/lib/src/xran_frame_struct.c
index fbb1298..44aaf92 100644 index fbb1298..385de76 100644
--- a/fhi_lib/lib/src/xran_frame_struct.c --- a/fhi_lib/lib/src/xran_frame_struct.c
+++ b/fhi_lib/lib/src/xran_frame_struct.c +++ b/fhi_lib/lib/src/xran_frame_struct.c
@@ -519,4 +519,20 @@ int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlot @@ -518,5 +518,3 @@ int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlot
return xran_fs_slot_symb_type[PortId][nCellIdx][nSfIdxMod][nSymbIdx]; return xran_fs_slot_symb_type[PortId][nCellIdx][nSfIdxMod][nSymbIdx];
} }
-
+uint32_t xran_fs_get_num_dl_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx) -
+{
+ int32_t nSfIdxMod;
+
+ nSfIdxMod = xran_fs_slot_limit(PortId, nSlotdx) % ((xran_fs_num_slot_tdd_loop[PortId][nCellIdx] > 0) ? xran_fs_num_slot_tdd_loop[PortId][nCellIdx]: 1);
+
+ return xran_fs_num_dl_sym_sp[PortId][nCellIdx][nSfIdxMod];
+}
+uint32_t xran_fs_get_num_ul_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx)
+{
+ int32_t nSfIdxMod;
+
+ nSfIdxMod = xran_fs_slot_limit(PortId, nSlotdx) % ((xran_fs_num_slot_tdd_loop[PortId][nCellIdx] > 0) ? xran_fs_num_slot_tdd_loop[PortId][nCellIdx]: 1);
+
+ return xran_fs_num_ul_sym_sp[PortId][nCellIdx][nSfIdxMod];
+}
diff --git a/fhi_lib/lib/src/xran_frame_struct.h b/fhi_lib/lib/src/xran_frame_struct.h
index 7ed0a3a..8e66945 100644
--- a/fhi_lib/lib/src/xran_frame_struct.h
+++ b/fhi_lib/lib/src/xran_frame_struct.h
@@ -75,6 +75,8 @@ uint32_t xran_fs_slot_limit_init(uint32_t PortId, int32_t tti_interval_us);
uint32_t xran_fs_get_max_slot(uint32_t PortId);
uint32_t xran_fs_get_max_slot_SFN(uint32_t PortId);
int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx, int32_t nSymbIdx);
+uint32_t xran_fs_get_num_dl_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx);
+uint32_t xran_fs_get_num_ul_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx);
#ifdef __cplusplus
}
diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c
index 7c472d7..db03d94 100644 index 7c472d7..758616d 100644
--- a/fhi_lib/lib/src/xran_main.c --- a/fhi_lib/lib/src/xran_main.c
+++ b/fhi_lib/lib/src/xran_main.c +++ b/fhi_lib/lib/src/xran_main.c
@@ -35,7 +35,11 @@ @@ -35,7 +35,11 @@
@@ -1847,15 +1698,7 @@ index 7c472d7..db03d94 100644
if(pThCtx == NULL){ if(pThCtx == NULL){
print_err("pThCtx allocation error\n"); print_err("pThCtx allocation error\n");
return XRAN_STATUS_FAIL; return XRAN_STATUS_FAIL;
@@ -3754,6 +3808,7 @@ xran_open(void *pHandle, struct xran_fh_config* pConf) @@ -4034,6 +4088,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx,
p_xran_dev_ctx->puschMaskSlot = pConf->puschMaskSlot;
p_xran_dev_ctx->DynamicSectionEna = pConf->DynamicSectionEna;
p_xran_dev_ctx->RunSlotPrbMapBySymbolEnable = pConf->RunSlotPrbMapBySymbolEnable;
+ p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable = pConf->LiteOnIgnoreUPSectionIdEnable;
p_xran_dev_ctx->dssEnable = pConf->dssEnable;
p_xran_dev_ctx->dssPeriod = pConf->dssPeriod;
for(i=0; i<pConf->dssPeriod; i++) {
@@ -4034,6 +4089,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx,
return tti; return tti;
} }
@@ -1880,7 +1723,7 @@ index 7c472d7..db03d94 100644
int32_t int32_t
xran_set_debug_stop(int32_t value, int32_t count) xran_set_debug_stop(int32_t value, int32_t count)
{ {
@@ -4208,7 +4281,7 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str @@ -4208,7 +4280,7 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str
int32_t i = 0, j = 0, nPrbElm = 0; int32_t i = 0, j = 0, nPrbElm = 0;
int16_t iqwidth = p_PrbMapIn->prbMap[0].iqWidth; int16_t iqwidth = p_PrbMapIn->prbMap[0].iqWidth;
struct xran_prb_elm *p_prb_elm_src, *p_prb_elm_dst; struct xran_prb_elm *p_prb_elm_src, *p_prb_elm_dst;
@@ -1889,7 +1732,7 @@ index 7c472d7..db03d94 100644
int32_t nRBStart_tmp, nRBremain, nStartSymb, nEndSymb, nRBStart, nRBEnd, nRBSize; int32_t nRBStart_tmp, nRBremain, nStartSymb, nEndSymb, nRBStart, nRBEnd, nRBSize;
// int32_t eth_xran_up_headers_sz = sizeof(struct eth_xran_up_pkt_hdr); // int32_t eth_xran_up_headers_sz = sizeof(struct eth_xran_up_pkt_hdr);
// int32_t nmaxRB = (mtu - eth_xran_up_headers_sz - RTE_PKTMBUF_HEADROOM)/XRAN_PAYLOAD_1_RB_SZ(iqwidth); // int32_t nmaxRB = (mtu - eth_xran_up_headers_sz - RTE_PKTMBUF_HEADROOM)/XRAN_PAYLOAD_1_RB_SZ(iqwidth);
@@ -4217,7 +4290,6 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str @@ -4217,7 +4289,6 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str
if (mtu==9600) if (mtu==9600)
nmaxRB--; //for some reason when mtu is 9600, only 195 RB can be sent, not 196 nmaxRB--; //for some reason when mtu is 9600, only 195 RB can be sent, not 196
@@ -1897,7 +1740,7 @@ index 7c472d7..db03d94 100644
memcpy(p_PrbMapOut, p_PrbMapIn, sizeof(struct xran_prb_map)); memcpy(p_PrbMapOut, p_PrbMapIn, sizeof(struct xran_prb_map));
for(i = 0; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) for(i = 0; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++)
{ {
@@ -4292,26 +4364,30 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str @@ -4292,27 +4363,23 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str
for(; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) for(; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++)
{ {
@@ -1906,8 +1749,7 @@ index 7c472d7..db03d94 100644
- prbMapTemp[nPrbElm].numSymb++; - prbMapTemp[nPrbElm].numSymb++;
- } - }
- else - else
+ if((prbMapTemp[i].nRBSize != 0)) - {
{
- nPrbElm++; - nPrbElm++;
- prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb; - prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb;
- prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart; - prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart;
@@ -1922,31 +1764,27 @@ index 7c472d7..db03d94 100644
- -
- nRBStart = prbMapTemp[i].nRBStart; - nRBStart = prbMapTemp[i].nRBStart;
- nRBSize = prbMapTemp[i].nRBSize; - nRBSize = prbMapTemp[i].nRBSize;
+ if (false) // Force it to generate multiple prbMapElm, one for each symbol even if they are of the same RBs - }
+ //if((nRBStart == prbMapTemp[i].nRBStart) && (nRBSize == prbMapTemp[i].nRBSize)) + /* force using a separate section for each symbol in one multisection CP (both DL and UL) message;
+ { + * when generating DL UP, symbol index should be within nStartSymb and (nStartSymb + numSymb);
+ prbMapTemp[nPrbElm].numSymb++; + * nPrbElm doesn't have any affect on UL UP */
+ } + nPrbElm++;
+ else + prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb;
+ { + prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart;
+ nPrbElm++; + prbMapTemp[nPrbElm].nRBSize = prbMapTemp[i].nRBSize;
+ prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb; + prbMapTemp[nPrbElm].nBeamIndex = prbMapTemp[i].nBeamIndex;
+ prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart; + prbMapTemp[nPrbElm].bf_weight_update = prbMapTemp[i].bf_weight_update;
+ prbMapTemp[nPrbElm].nRBSize = prbMapTemp[i].nRBSize; + prbMapTemp[nPrbElm].compMethod = prbMapTemp[i].compMethod;
+ prbMapTemp[nPrbElm].nBeamIndex = prbMapTemp[i].nBeamIndex; + prbMapTemp[nPrbElm].iqWidth = prbMapTemp[i].iqWidth;
+ prbMapTemp[nPrbElm].bf_weight_update = prbMapTemp[i].bf_weight_update; + prbMapTemp[nPrbElm].ScaleFactor = prbMapTemp[i].ScaleFactor;
+ prbMapTemp[nPrbElm].compMethod = prbMapTemp[i].compMethod; + prbMapTemp[nPrbElm].reMask = prbMapTemp[i].reMask;
+ prbMapTemp[nPrbElm].iqWidth = prbMapTemp[i].iqWidth; + prbMapTemp[nPrbElm].BeamFormingType = prbMapTemp[i].BeamFormingType;
+ prbMapTemp[nPrbElm].ScaleFactor = prbMapTemp[i].ScaleFactor;
+ prbMapTemp[nPrbElm].reMask = prbMapTemp[i].reMask;
+ prbMapTemp[nPrbElm].BeamFormingType = prbMapTemp[i].BeamFormingType;
+ +
+ nRBStart = prbMapTemp[i].nRBStart; + nRBStart = prbMapTemp[i].nRBStart;
+ nRBSize = prbMapTemp[i].nRBSize; + nRBSize = prbMapTemp[i].nRBSize;
+ }
}
} }
for(i = 0; i < nPrbElm; i++)
diff --git a/fhi_lib/lib/src/xran_mem_mgr.c b/fhi_lib/lib/src/xran_mem_mgr.c diff --git a/fhi_lib/lib/src/xran_mem_mgr.c b/fhi_lib/lib/src/xran_mem_mgr.c
index e1dcb6c..b3c3fae 100644 index e1dcb6c..b3c3fae 100644
--- a/fhi_lib/lib/src/xran_mem_mgr.c --- a/fhi_lib/lib/src/xran_mem_mgr.c
@@ -1980,7 +1818,7 @@ index 7d4a5d0..b9b44ac 100644
#endif #endif
} }
diff --git a/fhi_lib/lib/src/xran_rx_proc.c b/fhi_lib/lib/src/xran_rx_proc.c diff --git a/fhi_lib/lib/src/xran_rx_proc.c b/fhi_lib/lib/src/xran_rx_proc.c
index e7056f4..34b6d3b 100644 index e7056f4..4941360 100644
--- a/fhi_lib/lib/src/xran_rx_proc.c --- a/fhi_lib/lib/src/xran_rx_proc.c
+++ b/fhi_lib/lib/src/xran_rx_proc.c +++ b/fhi_lib/lib/src/xran_rx_proc.c
@@ -35,7 +35,11 @@ @@ -35,7 +35,11 @@
@@ -1995,127 +1833,16 @@ index e7056f4..34b6d3b 100644
#include <rte_common.h> #include <rte_common.h>
#include <rte_eal.h> #include <rte_eal.h>
@@ -339,13 +343,33 @@ int32_t xran_process_srs_sym(void *arg, @@ -537,6 +541,9 @@ int32_t xran_process_rx_sym(void *arg,
pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFHSrsRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData;
if(pRbMap)
{
- prbMapElm = &pRbMap->prbMap[sect_id];
- if(sect_id >= pRbMap->nPrbElm)
+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) {
+ section_id_tmp = prb_elem_id_tmp = sect_id;
+ } else {
+ /** Get the prb_elem_id */
+ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx);
+ u_int8_t mixed_ul_sym_start = 0;
+ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) {
+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti);
+ }
+
+ section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ //Note for future reference when using MTU 1500
+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ }
+
+ prbMapElm = &pRbMap->prbMap[prb_elem_id_tmp /*sect_id*/];
+ if(/*sect_id*/ prb_elem_id_tmp >= pRbMap->nPrbElm)
{
- print_err("sect_id %d !=pRbMap->nPrbElm %d\n", sect_id,pRbMap->nPrbElm);
- *mb_free = MBUF_FREE;
- return size;
- }
+ print_err("sect_id %d !=pRbMap->nPrbElm %d\n", sect_id,pRbMap->nPrbElm);
+ *mb_free = MBUF_FREE;
+ return size;
+ }
}
else
{
@@ -397,7 +421,25 @@ int32_t xran_process_srs_sym(void *arg,
else */
{
struct xran_section_desc *p_sec_desc = NULL;
- prbMapElm = &pRbMap->prbMap[sect_id];
+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) {
+ section_id_tmp = prb_elem_id_tmp = sect_id;
+ } else {
+ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx);
+ u_int8_t mixed_ul_sym_start = 0;
+ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) {
+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti);
+ }
+ u_int8_t section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ //Note for future reference when using MTU 1500
+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ }
+
+ prbMapElm = &pRbMap->prbMap[prb_elem_id_tmp /*sect_id*/];
// sec_desc_idx = 0;//prbMapElm->nSecDesc[symb_id];
sec_desc_idx = prbMapElm->nSecDesc[symb_id];
@@ -537,14 +579,33 @@ int32_t xran_process_rx_sym(void *arg,
pos = (char*) p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData; pos = (char*) p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData;
pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData; pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData;
if(pRbMap){ if(pRbMap){
- /** Get the prb_elem_id */ + if (p_xran_dev_ctx->RunSlotPrbMapBySymbolEnable) {
+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 + sect_id = (pRbMap->nPrbElm == XRAN_NUM_OF_SYMBOL_PER_SLOT) ? symb_id : symb_id - (XRAN_NUM_OF_SYMBOL_PER_SLOT - pRbMap->nPrbElm);
+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13
+ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) {
+ section_id_tmp = prb_elem_id_tmp = sect_id;
+ } else {
+ /** Get the prb_elem_id */
+ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx);
+ u_int8_t mixed_ul_sym_start = 0;
+ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) {
+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti);
+ }
+
+ section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000
+ //Note for future reference when using MTU 1500
+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500
+ } + }
+ /** Get the prb_elem_id */
total_sections=0; total_sections=0;
if(pRbMap->prbMap[0].bf_weight.extType == 1) if(pRbMap->prbMap[0].bf_weight.extType == 1)
{
for(i=0 ; i < pRbMap->nPrbElm ; i++)
{
total_sections += pRbMap->prbMap[i].bf_weight.numSetBFWs;
- if(total_sections >= (sect_id + 1))
+ if(total_sections >= (/*sect_id*/ section_id_tmp + 1))
{
prb_elem_id = i;
break;
@@ -553,7 +614,7 @@ int32_t xran_process_rx_sym(void *arg,
}
else
{
- prb_elem_id = sect_id;
+ prb_elem_id = prb_elem_id_tmp; /*sect_id*/;
}
prbMapElm = &pRbMap->prbMap[prb_elem_id];
@@ -597,7 +658,7 @@ int32_t xran_process_rx_sym(void *arg,
if(p_sec_desc){
mb = p_sec_desc->pCtrl;
if(mb){
- rte_pktmbuf_free(mb);
+ rte_pktmbuf_free(mb);
}
p_sec_desc->pData = iq_data_start;
p_sec_desc->pCtrl = mbuf;
diff --git a/fhi_lib/lib/src/xran_timer.c b/fhi_lib/lib/src/xran_timer.c diff --git a/fhi_lib/lib/src/xran_timer.c b/fhi_lib/lib/src/xran_timer.c
index 14a6a41..55182d8 100644 index 14a6a41..55182d8 100644
--- a/fhi_lib/lib/src/xran_timer.c --- a/fhi_lib/lib/src/xran_timer.c
+1 -1
View File
@@ -8,7 +8,7 @@ CXXFLAGS=-Wall -g -pthread -DT_TRACER -I. -I../incgen -std=c++11
LIBS=-lm LIBS=-lm
XLIBS=-lX11 -lpng -lXft XLIBS=-lX11 -lpng -lXft
all: record record_db replay extract_config textlog enb ue vcd macpdu2wireshark \ all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
extract_input_subframe extract_output_subframe to_vcd extract multi \ extract_input_subframe extract_output_subframe to_vcd extract multi \
gnb t_tracer_app_gnb t_tracer_app_ue gnb_mac csv gnb t_tracer_app_gnb t_tracer_app_ue gnb_mac csv
+1 -1
View File
@@ -195,7 +195,7 @@ static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, g
e->ul_freq_estimate_ue_xy_plot = w; e->ul_freq_estimate_ue_xy_plot = w;
widget_add_child(g, line, w, -1); widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, 0, 2048, -10, 80); xy_plot_set_range(g, w, 0, 2048, -10, 80);
l = new_framelog(h, database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", "subframe", "chest_t"); l = new_framelog(h, database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", "subframe", "chest_f");
framelog_set_update_only_at_sf9(l, 0); framelog_set_update_only_at_sf9(l, 0);
v = new_view_xy(2048, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE); v = new_view_xy(2048, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE);
logger_add_view(l, v); logger_add_view(l, v);
+4
View File
@@ -366,6 +366,10 @@ void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id,
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
#define BOUNDED_EVAL(a, b, c) (min(c, max(a, b))) #define BOUNDED_EVAL(a, b, c) (min(c, max(a, b)))
/* Macro used to perform a circular increment. This implementation is computationally more efficient than using the remainder of the
* integer division, and improves code readability when compared to repetitive if... else statements. */
#define CIRCULAR_INC(val, inc, size) (((val) + (inc) >= (size)) ? ((val) + (inc) - (size)) : ((val) + (inc)))
static const char *const duplex_mode_txt[] = {"FDD", "TDD"}; static const char *const duplex_mode_txt[] = {"FDD", "TDD"};
#ifdef __cplusplus #ifdef __cplusplus
+44 -9
View File
@@ -61,8 +61,8 @@ We tested the category A radio units listed below.
|-----------------|---------------------------------------------| |-----------------|---------------------------------------------|
|VVDN LPRU |03-v3.0.5 | |VVDN LPRU |03-v3.0.5 |
|LiteON RU |01.00.08/02.00.03/02.00.10 | |LiteON RU |01.00.08/02.00.03/02.00.10 |
|Benetel 650 |RAN650-1v1.0.4-dda1bf5|RAN650-1v1.2.2-2fa04bc| |Benetel 650 |RAN650-1v1.0.4-dda1bf5/RAN650-1v1.2.2-2fa04bc/RAN650-1v1.4.2-NM-c48047d|
|Benetel 550 |RAN550-1v1.0.4-605a25a|RAN550-1v1.2.2-2fa04bc| |Benetel 550 |RAN550-1v1.0.4-605a25a/RAN550-1v1.2.2-2fa04bc/RAN550-1v1.4.1-M-25fa970/RAN550-1v2.0.5-M-92a9d2c|
|Foxconn RPQN |v3.1.15q.551_rc10 | |Foxconn RPQN |v3.1.15q.551_rc10 |
Tested libxran releases: Tested libxran releases:
@@ -563,13 +563,16 @@ flexran_prach_workaround=disabled
dl_tuning_special_slot=0x13b6 dl_tuning_special_slot=0x13b6
``` ```
#### LITEON In addition, PRACH format 0 is also verified with FW v2.0.5. An example gNB config file can be found at [`gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf). On the RU side, the following parameters shall be modified:
```bash
mimo_mode=1_3
prach_format=long
prach_freq_offset_dynamic=false
lf_prach_compression_enable=true
lf_prach_slot_id=0
```
The OAI configuration file [`gnb.sa.band78.273prb.fhi72.4x4-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf) corresponds to: #### LITEON
- TDD pattern `DDDSU`, 2.5ms
- Bandwidth 100MHz
- MTU 1500
- MTU 9216: v02.00.10
##### RU configuration ##### RU configuration
@@ -593,7 +596,15 @@ Once the RU is PTP synced, and RF state and DPD are `Ready`, write `configure te
- DU MAC address - DU MAC address
... ...
The configuration mode example: ###### FR1
The OAI configuration file [`gnb.sa.band78.273prb.fhi72.4x4-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf) corresponds to:
- TDD pattern `DDDSU`, 2.5ms
- Bandwidth 100MHz
- MTU 1500
- MTU 9216: v02.00.10
The RU configuration mode example:
```bash ```bash
compression-bit 9 # set IQ bitwidth for PxSCH/PRACH compression-bit 9 # set IQ bitwidth for PxSCH/PRACH
eAXC_id 4 5 6 7 # set PRACH eAxC IDs eAXC_id 4 5 6 7 # set PRACH eAxC IDs
@@ -601,6 +612,21 @@ jumboframe 1 # enable jumbo frame
... ...
``` ```
###### FR2
The OAI configuration file [`gnb.sa.band257.66prb.fhi72.2x2-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.66prb.fhi72.2x2-liteon.conf) corresponds to:
- TDD pattern `DDDDDDDSUU`, 1.25ms
- Bandwidth 100MHz
- FW v02.00.07
- DL uses jumbo frame, UL uses standard MTU of 1500 bytes
The RU configuration mode example:
```bash
compression-bit 8 # set IQ bitwidth for PxSCH/PRACH
eAXC_id 0 1 # set PRACH eAxC IDs
...
```
#### VVDN LPRU #### VVDN LPRU
**Version 3.x** **Version 3.x**
@@ -970,6 +996,14 @@ Edit the sample OAI gNB configuration file and check following parameters:
* `GNB_IPV4_ADDRESS_FOR_NGU` shall match your gNB N3 interface IP address * `GNB_IPV4_ADDRESS_FOR_NGU` shall match your gNB N3 interface IP address
* `prach_ConfigurationIndex` * `prach_ConfigurationIndex`
* `prach_msg1_FrequencyStart` * `prach_msg1_FrequencyStart`
* `ssPBCH_BlockPower` is average EPRE of the resource elements carrying the secondary synchronization signals, expressed in dBm. It can be estimated using the following formula:
> ssPBCH_BlockPower = P_TX − 10 x log10(N_RE) + 10 x log10(N_antenna_SSB)
where:
* `P_TX` is the total transmit power of the RU in dBm (configured on the RU).
* `N_RE` is the number of resource elements used for the transmission.
* `N_antenna_SSB` is the number of antenna ports used for SSB transmission (currently, a single antenna port is used for SSB transmission).
* Adjust the frequency, bandwidth and SSB position * Adjust the frequency, bandwidth and SSB position
* `L1s` section * `L1s` section
@@ -1012,6 +1046,7 @@ Edit the sample OAI gNB configuration file and check following parameters:
[Memory in DPDK](https://www.dpdk.org/memory-in-dpdk-part-2-deep-dive-into-iova/) [Memory in DPDK](https://www.dpdk.org/memory-in-dpdk-part-2-deep-dive-into-iova/)
* `owdm_enable`: used for eCPRI One-Way Delay Measurements; it depends if the RU supports it; if not set to 1 (enabled), default value is 0 (disabled) * `owdm_enable`: used for eCPRI One-Way Delay Measurements; it depends if the RU supports it; if not set to 1 (enabled), default value is 0 (disabled)
* `fh_config` * `fh_config`
* `RunSlotPrbMapBySymbol`: enable CP multisection (one symbol per section); default value is 0
* DU delay profile (`T1a` and `Ta4`): pairs of numbers `(x, y)` specifying minimum and maximum delays * DU delay profile (`T1a` and `Ta4`): pairs of numbers `(x, y)` specifying minimum and maximum delays
* `ru_config`: RU-specific configuration: * `ru_config`: RU-specific configuration:
* `iq_width`: Width of DL/UL IQ samples: if 16, no compression, if <16, applies * `iq_width`: Width of DL/UL IQ samples: if 16, no compression, if <16, applies
+4 -1
View File
@@ -464,7 +464,10 @@ sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF
The OAI UE can also be used in front of a OAI gNB without the support of eNB or EPC and circumventing random access. In this case both gNB and eNB need to be run with the `--phy-test` flag. At the gNB this flag does the following The OAI UE can also be used in front of a OAI gNB without the support of eNB or EPC and circumventing random access. In this case both gNB and eNB need to be run with the `--phy-test` flag. At the gNB this flag does the following
- it reads the RRC configuration from the configuration file - it reads the RRC configuration from the configuration file
- it encodes the RRCConfiguration and the RBconfig message and stores them in the binary files `rbconfig.raw` and `reconfig.raw` in the current directory - it encodes the RRCConfiguration and the RBconfig message and stores them in the binary files `rbconfig.raw` and `reconfig.raw` in the current directory
- the MAC uses a pre-configured allocation of PDSCH and PUSCH with randomly generated payload instead of the standard scheduler. The options `-m`, `-l`, `-t`, `-M`, `-T`, `-D`, and `-U` can be used to configure this scheduler. See `./nr-softmodem -h` for more information. - the MAC uses a pre-configured allocation of PDSCH and PUSCH with randomly generated payload instead of the standard scheduler. The options `-m`, `-l`, `-t`, `-M`, `-T`, `-D`, and `-U` can be used to configure this scheduler.
- Options `-Dmod`, and `-Umod` were introduced to enable scheduling PDSCH/PUSCH on slots >= 64 in phy-test mode. (in case of >= 120Khz subcarrier spacing and FDD)
- For ex: `-Dmod 2' / '-Umod 2` allocates every 2nd slot for PDSCH or PUSCH respectively.
- See `./nr-softmodem -h` for more information.
At the UE, the `--phy-test` flag will read the binary files `rbconfig.raw` and `reconfig.raw` from the current directory and process them. If you wish to provide a different path for these files, please use the options `--reconfig-file` and `--rbconfig-file`. At the UE, the `--phy-test` flag will read the binary files `rbconfig.raw` and `reconfig.raw` from the current directory and process them. If you wish to provide a different path for these files, please use the options `--reconfig-file` and `--rbconfig-file`.
+3 -8
View File
@@ -998,9 +998,10 @@ void *ru_thread(void *param)
proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP); proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP);
// Do PRACH RU processing // Do PRACH RU processing
prach_item_t *p = find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, SEARCH_EXIST); prach_item_t *p =
find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, gNB->frame_parms.nb_antennas_rx, SEARCH_EXIST);
if (p) { if (p) {
// need to extract RACH data for lqter processing by rx_nr_prach() // need to extract RACH data for later processing by rx_nr_prach()
rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset);
} // end if (prach_id >= 0) } // end if (prach_id >= 0)
} // end if (ru->feprx) } // end if (ru->feprx)
@@ -1458,13 +1459,7 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
} /* strcmp(local_rf, "yes") != 0 */ } /* strcmp(local_rf, "yes") != 0 */
ru->nb_tx = *param[RU_NB_TX_IDX].uptr; ru->nb_tx = *param[RU_NB_TX_IDX].uptr;
AssertFatal(ru->nb_tx <= NB_ANTENNAS_TX,
"Config file has %d TX antennas set, but the compile time max value in NB_ANTENNAS_TX\n",
ru->nb_tx);
ru->nb_rx = *param[RU_NB_RX_IDX].uptr; ru->nb_rx = *param[RU_NB_RX_IDX].uptr;
AssertFatal(ru->nb_rx <= NB_ANTENNAS_RX,
"Config file has %d RX antennas set, but the compile time max value in NB_ANTENNAS_RX\n",
ru->nb_rx);
ru->att_tx = *param[RU_ATT_TX_IDX].uptr; ru->att_tx = *param[RU_ATT_TX_IDX].uptr;
ru->att_rx = *param[RU_ATT_RX_IDX].uptr; ru->att_rx = *param[RU_ATT_RX_IDX].uptr;
ru->if_frequency = *param[RU_IF_FREQUENCY].u64ptr; ru->if_frequency = *param[RU_IF_FREQUENCY].u64ptr;
+2
View File
@@ -55,5 +55,7 @@
#define CONFIG_HLP_ULBW_PHYTEST "Set the number of PRBs used for ULSCH in PHYTEST mode\n" #define CONFIG_HLP_ULBW_PHYTEST "Set the number of PRBs used for ULSCH in PHYTEST mode\n"
#define CONFIG_HLP_DLBM_PHYTEST "Bitmap for DLSCH slots in period (slot 0 starts at LSB)\n" #define CONFIG_HLP_DLBM_PHYTEST "Bitmap for DLSCH slots in period (slot 0 starts at LSB)\n"
#define CONFIG_HLP_ULBM_PHYTEST "Bitmap for ULSCH slots in period (slot 0 starts at LSB)\n" #define CONFIG_HLP_ULBM_PHYTEST "Bitmap for ULSCH slots in period (slot 0 starts at LSB)\n"
#define CONFIG_HLP_DLMOD_PHYTEST "For-DLSCH, if val is n, every nth slot in slots per frame will be scheduled. \n"
#define CONFIG_HLP_ULMOD_PHYTEST "For ULSCH, if val is n, every nth slot in slots per frame will be scheduled. \n"
void wait_gNBs(void); void wait_gNBs(void);
#endif #endif
+4
View File
@@ -25,6 +25,8 @@
{"T" , CONFIG_HLP_ULBW_PHYTEST, 0, .uptr=&target_ul_bw, .defintval=0, TYPE_UINT, 0}, \ {"T" , CONFIG_HLP_ULBW_PHYTEST, 0, .uptr=&target_ul_bw, .defintval=0, TYPE_UINT, 0}, \
{"D" , CONFIG_HLP_DLBM_PHYTEST, 0, .u64ptr=&dlsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \ {"D" , CONFIG_HLP_DLBM_PHYTEST, 0, .u64ptr=&dlsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \
{"U" , CONFIG_HLP_ULBM_PHYTEST, 0, .u64ptr=&ulsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \ {"U" , CONFIG_HLP_ULBM_PHYTEST, 0, .u64ptr=&ulsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \
{"Dmod" , CONFIG_HLP_DLMOD_PHYTEST, 0, .uptr=&dlsch_slot_modval, .defintval=0, TYPE_UINT, 0}, \
{"Umod" , CONFIG_HLP_ULMOD_PHYTEST, 0, .uptr=&ulsch_slot_modval, .defintval=0, TYPE_UINT, 0}, \
{"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, .iptr=&usrp_tx_thread, .defstrval=0, TYPE_INT, 0}, \ {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, .iptr=&usrp_tx_thread, .defstrval=0, TYPE_INT, 0}, \
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \ {"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
} }
@@ -39,6 +41,8 @@ extern uint32_t target_ul_bw;
extern uint64_t dlsch_slot_bitmap; extern uint64_t dlsch_slot_bitmap;
extern uint64_t ulsch_slot_bitmap; extern uint64_t ulsch_slot_bitmap;
extern char *uecap_file; extern char *uecap_file;
extern uint32_t dlsch_slot_modval;
extern uint32_t ulsch_slot_modval;
// In nr-gnb.c // In nr-gnb.c
extern void init_gNB(); extern void init_gNB();
-6
View File
@@ -211,12 +211,6 @@ void nrue_set_ru_params(configmodule_interface_t *cfg)
if (RUParamList.numelt <= 0) { if (RUParamList.numelt <= 0) {
nrue_ru_count = 1; nrue_ru_count = 1;
nrue_rus = calloc_or_fail(nrue_ru_count, sizeof(nrUE_RU_params_t)); nrue_rus = calloc_or_fail(nrue_ru_count, sizeof(nrUE_RU_params_t));
AssertFatal(get_nrUE_params()->nb_antennas_tx <= NB_ANTENNAS_TX,
"Config file has %d TX antennas set, but the compile time max value in NB_ANTENNAS_TX\n",
get_nrUE_params()->nb_antennas_tx);
AssertFatal(get_nrUE_params()->nb_antennas_rx <= NB_ANTENNAS_RX,
"Config file has %d RX antennas set, but the compile time max value in NB_ANTENNAS_RX\n",
get_nrUE_params()->nb_antennas_tx);
nrue_rus[0] = (nrUE_RU_params_t){.nb_tx = get_nrUE_params()->nb_antennas_tx, nrue_rus[0] = (nrUE_RU_params_t){.nb_tx = get_nrUE_params()->nb_antennas_tx,
.nb_rx = get_nrUE_params()->nb_antennas_rx, .nb_rx = get_nrUE_params()->nb_antennas_rx,
.att_tx = get_nrUE_params()->tx_gain, .att_tx = get_nrUE_params()->tx_gain,
-2
View File
@@ -177,8 +177,6 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id)
ue->dci_thres = 0; ue->dci_thres = 0;
ue->target_Nid_cell = -1; ue->target_Nid_cell = -1;
ue->nrUE_config.ntn_config.params_changed = false;
// initialize all signal buffers // initialize all signal buffers
init_nr_ue_signal(ue, nb_connected_gNB); init_nr_ue_signal(ue, nb_connected_gNB);
@@ -765,29 +765,23 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
} // Antenna loop } // Antenna loop
} }
int nr_srs_channel_estimation(int ant, int nr_srs_ls_channel_estimation(int ant,
int p_index, int p_index,
uint16_t ofdm_symbol_size, uint16_t ofdm_symbol_size,
uint16_t first_carrier_offset, uint16_t first_carrier_offset,
uint8_t N_symb_SRS, uint8_t N_symb_SRS,
const nfapi_nr_srs_pdu_t *srs_pdu, const nfapi_nr_srs_pdu_t *srs_pdu,
const nr_srs_info_t *nr_srs_info, const nr_srs_info_t *nr_srs_info,
const c16_t *srs_generated_signal, const c16_t *srs_generated_signal,
c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS],
c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], delay_t *delay)
c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
uint32_t *signal_power,
uint32_t *noise_power,
int16_t *noise_power_per_rb)
{ {
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__); LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__);
#endif #endif
const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB;
const uint64_t first_subcarrier = (first_carrier_offset - (ofdm_symbol_size >> 1)) + srs_pdu->bwp_start * NR_NB_SC_PER_RB;
const uint8_t N_ap = 1 << srs_pdu->num_ant_ports; const uint8_t N_ap = 1 << srs_pdu->num_ant_ports;
const uint8_t K_TC = 2 << srs_pdu->comb_size; const uint8_t K_TC = 2 << srs_pdu->comb_size;
@@ -797,40 +791,20 @@ int nr_srs_channel_estimation(int ant,
if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) { if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) {
fd_cdm = 2; fd_cdm = 2;
} }
uint16_t subcarrier;
c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS];
c16_t srs_estimated_channel_freq_avg[ofdm_symbol_size];
memset(srs_ls_estimated_channel, 0, ofdm_symbol_size * N_symb_SRS * sizeof(c16_t)); memset(srs_ls_estimated_channel, 0, ofdm_symbol_size * N_symb_SRS * sizeof(c16_t));
memset(srs_estimated_channel_freq_avg, 0, ofdm_symbol_size * sizeof(c16_t));
for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) { for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) {
uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size; uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size;
// Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel
// interpolation
c16_t srs_est[ofdm_symbol_size + 4] __attribute__((aligned(32)));
memset(srs_est, 0, (ofdm_symbol_size + 4) * sizeof(c16_t));
// Estimate 16 byte memory alignment offset for the first SRS subcarrier to use AVX2 instructions in channel interpolation
uint8_t mem_offset = (16 - (((intptr_t)&srs_est[first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]]) & 0xF))
>> 2; // >> 2 <=> /sizeof(int32_t)
c16_t ls_estimated = {0};
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant); LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant);
LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb); LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb);
#endif #endif
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size);
if (subcarrier >= ofdm_symbol_size) {
subcarrier -= ofdm_symbol_size;
}
uint16_t subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb];
c16_t *srs_estimated_channel16 = &srs_est[subcarrier_abs];
c16_t ls_estimated = {0};
for (int k = 0; k < M_sc_b_SRS; k++) { for (int k = 0; k < M_sc_b_SRS; k++) {
if (k % fd_cdm == 0) { if (k % fd_cdm == 0) {
ls_estimated = (c16_t){0, 0}; ls_estimated = (c16_t){0, 0};
@@ -845,14 +819,13 @@ int nr_srs_channel_estimation(int ant,
ls_estimated = c16maddConjShift(generated_srs, received_srs, ls_estimated, nr_srs_info->srs_generated_signal_bits); ls_estimated = c16maddConjShift(generated_srs, received_srs, ls_estimated, nr_srs_info->srs_generated_signal_bits);
// Subcarrier increment // Subcarrier increment
subcarrier_cdm += K_TC; subcarrier_cdm = CIRCULAR_INC(subcarrier_cdm, K_TC, ofdm_symbol_size);
if (subcarrier_cdm >= ofdm_symbol_size) {
subcarrier_cdm = subcarrier_cdm - ofdm_symbol_size;
}
} }
} }
srs_ls_estimated_channel[srs_symbol_offset + subcarrier] = ls_estimated; for (int ktc = 0; ktc < K_TC && srs_symbol_offset + subcarrier + ktc < ofdm_symbol_size * N_symb_SRS; ktc++) {
srs_ls_estimated_channel[srs_symbol_offset + subcarrier + ktc] = ls_estimated;
}
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
int subcarrier_log = subcarrier - subcarrier_offset; int subcarrier_log = subcarrier - subcarrier_offset;
@@ -874,6 +847,140 @@ int nr_srs_channel_estimation(int ant,
ls_estimated.i); ls_estimated.i);
#endif #endif
// Subcarrier increment
subcarrier = CIRCULAR_INC(subcarrier, K_TC, ofdm_symbol_size);
} // for (int k = 0; k < M_sc_b_SRS; k++)
// Delay estimation
if (srs_symb == 0) {
c16_t ch_estimates_time[ofdm_symbol_size] __attribute__((aligned(32)));
nr_est_delay(ofdm_symbol_size, srs_ls_estimated_channel, ch_estimates_time, delay);
}
} // for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++)
return 0;
}
void nr_srs_noise_power_estimation(uint16_t ofdm_symbol_size,
uint16_t first_carrier_offset,
uint8_t N_symb_SRS,
const nfapi_nr_srs_pdu_t *srs_pdu,
const nr_srs_info_t *nr_srs_info,
uint32_t signal_power,
const c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS],
uint32_t *noise_power,
int16_t *noise_power_per_rb)
{
const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB;
const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);
int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB;
uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[0][0], 0, ofdm_symbol_size);
if (subcarrier + tot_subcarriers < ofdm_symbol_size) {
*noise_power = signal_energy_nodc(&srs_received_noise[subcarrier], tot_subcarriers) / tot_subcarriers;
} else {
int size1 = ofdm_symbol_size - subcarrier;
int size2 = tot_subcarriers - size1;
uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1;
uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2;
*noise_power = (noise_power_p1 + noise_power_p2) / tot_subcarriers;
}
// Compute SNR per RB on symbol 0
subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[0][0], 0, ofdm_symbol_size);
for (int rb = 0; rb < m_SRS_b; rb++) {
if (subcarrier + NR_NB_SC_PER_RB < ofdm_symbol_size) {
noise_power_per_rb[rb] += signal_energy_nodc(&srs_received_noise[subcarrier], NR_NB_SC_PER_RB);
} else {
int size1 = ofdm_symbol_size - subcarrier;
int size2 = NR_NB_SC_PER_RB - size1;
uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1;
uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2;
noise_power_per_rb[rb] += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB;
}
noise_power_per_rb[rb] = max(noise_power_per_rb[rb], 1);
subcarrier = CIRCULAR_INC(subcarrier, NR_NB_SC_PER_RB, ofdm_symbol_size);
#ifdef SRS_DEBUG
LOG_I(NR_PHY,
"[RB %3i] noise_power_per_rb = %i, SNR_per_rb = %i dB\n",
rb,
noise_power_per_rb[rb],
dB_fixed(signal_power) - dB_fixed(noise_power_per_rb[rb]));
#endif
}
#ifdef SRS_DEBUG
int32_t signal_power_dB = dB_fixed(signal_power);
int32_t noise_power_dB = dB_fixed(*noise_power);
LOG_I(NR_PHY,
"signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n",
signal_power_dB,
noise_power_dB,
signal_power_dB - noise_power_dB);
#endif
}
int nr_srs_channel_interpolation(int ant,
int p_index,
uint16_t ofdm_symbol_size,
uint16_t first_carrier_offset,
uint8_t N_symb_SRS,
const nfapi_nr_srs_pdu_t *srs_pdu,
const nr_srs_info_t *nr_srs_info,
const c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS],
int est_delay,
c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
uint32_t *signal_power,
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE])
{
#ifdef SRS_DEBUG
LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__);
#endif
const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB;
const uint64_t first_subcarrier = (first_carrier_offset - (ofdm_symbol_size >> 1)) + srs_pdu->bwp_start * NR_NB_SC_PER_RB;
const uint8_t K_TC = 2 << srs_pdu->comb_size;
const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);
const uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB / K_TC;
c16_t srs_estimated_channel_freq_avg[ofdm_symbol_size];
memset(srs_estimated_channel_freq_avg, 0, ofdm_symbol_size * sizeof(c16_t));
for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) {
uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size;
#ifdef SRS_DEBUG
LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant);
LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb);
#endif
// Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel
// interpolation
c16_t srs_est[ofdm_symbol_size + 4] __attribute__((aligned(32)));
memset(srs_est, 0, (ofdm_symbol_size + 4) * sizeof(c16_t));
// Estimate 16 byte memory alignment offset for the first SRS subcarrier to use AVX2 instructions in channel interpolation
uint8_t mem_offset =
(16 - (((intptr_t)&srs_est[first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]]) & 0xF)) / sizeof(c16_t);
uint16_t subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb];
c16_t *srs_estimated_channel16 = &srs_est[subcarrier_abs];
uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size);
int delay_idx = get_delay_idx(est_delay, MAX_DELAY_COMP);
const c16_t *srs_delay_table = delay_table[delay_idx];
for (int k = 0; k < M_sc_b_SRS; k++) {
// Apply delay
c16_t ls_estimated = c16mulShift(srs_ls_estimated_channel[srs_symbol_offset + subcarrier], srs_delay_table[subcarrier], 8);
// Channel interpolation // Channel interpolation
if (srs_pdu->comb_size == 0) { if (srs_pdu->comb_size == 0) {
if (k == 0) { // First subcarrier case if (k == 0) { // First subcarrier case
@@ -905,15 +1012,23 @@ int nr_srs_channel_estimation(int ant,
} }
// Subcarrier increment // Subcarrier increment
subcarrier += K_TC; subcarrier = CIRCULAR_INC(subcarrier, K_TC, ofdm_symbol_size);
if (subcarrier >= ofdm_symbol_size) {
subcarrier -= ofdm_symbol_size;
}
subcarrier_abs += K_TC; subcarrier_abs += K_TC;
} // for (int k = 0; k < M_sc_b_SRS; k++) } // for (int k = 0; k < M_sc_b_SRS; k++)
// Revert delay
int inv_delay_idx = get_delay_idx(-est_delay, MAX_DELAY_COMP);
const c16_t *srs_inv_delay_table = delay_table[inv_delay_idx];
subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb];
subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][0], 0, ofdm_symbol_size);
for (int k = 0; k < K_TC * M_sc_b_SRS; k++) {
srs_est[subcarrier_abs] = c16mulShift(srs_est[subcarrier_abs], srs_inv_delay_table[subcarrier], 8);
// Subcarrier increment
subcarrier = CIRCULAR_INC(subcarrier, 1, ofdm_symbol_size);
subcarrier_abs++;
}
memcpy(&srs_estimated_channel_freq[srs_symbol_offset], &srs_est[mem_offset], ofdm_symbol_size * sizeof(c16_t)); memcpy(&srs_estimated_channel_freq[srs_symbol_offset], &srs_est[mem_offset], ofdm_symbol_size * sizeof(c16_t));
// Average srs channel estimates over multiple symbols // Average srs channel estimates over multiple symbols
@@ -924,11 +1039,7 @@ int nr_srs_channel_estimation(int ant,
ofdm_symbol_size); ofdm_symbol_size);
#ifdef SRS_DEBUG #ifdef SRS_DEBUG
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size);
if (subcarrier >= ofdm_symbol_size) {
subcarrier -= ofdm_symbol_size;
}
subcarrier_abs = first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; subcarrier_abs = first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb];
for (int k = 0; k < K_TC * M_sc_b_SRS; k++) { for (int k = 0; k < K_TC * M_sc_b_SRS; k++) {
@@ -956,10 +1067,7 @@ int nr_srs_channel_estimation(int ant,
srs_received_noise[srs_symbol_offset + subcarrier].i); srs_received_noise[srs_symbol_offset + subcarrier].i);
// Subcarrier increment // Subcarrier increment
subcarrier++; subcarrier = CIRCULAR_INC(subcarrier, 1, ofdm_symbol_size);
if (subcarrier >= ofdm_symbol_size) {
subcarrier -= ofdm_symbol_size;
}
subcarrier_abs++; subcarrier_abs++;
} }
#endif #endif
@@ -996,61 +1104,5 @@ int nr_srs_channel_estimation(int ant,
return -1; return -1;
} }
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier >= ofdm_symbol_size) {
subcarrier -= ofdm_symbol_size;
}
if (p_index == 0) {
if (subcarrier + tot_subcarriers < ofdm_symbol_size) {
*noise_power = signal_energy_nodc(&srs_received_noise[subcarrier], tot_subcarriers) / tot_subcarriers;
} else {
int size1 = ofdm_symbol_size - subcarrier;
int size2 = tot_subcarriers - size1;
uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1;
uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2;
*noise_power = (noise_power_p1 + noise_power_p2) / tot_subcarriers;
}
}
// Compute SNR per RB for port 0 and symbol 0
if (p_index == 0) {
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
for (int rb = 0; rb < m_SRS_b; rb++) {
if (subcarrier >= ofdm_symbol_size) {
subcarrier -= ofdm_symbol_size;
}
if (subcarrier + NR_NB_SC_PER_RB < ofdm_symbol_size) {
noise_power_per_rb[rb] += signal_energy_nodc(&srs_received_noise[subcarrier], NR_NB_SC_PER_RB);
} else {
int size1 = ofdm_symbol_size - subcarrier;
int size2 = NR_NB_SC_PER_RB - size1;
uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1;
uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2;
noise_power_per_rb[rb] += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB;
}
noise_power_per_rb[rb] = max(noise_power_per_rb[rb], 1);
subcarrier += NR_NB_SC_PER_RB;
#ifdef SRS_DEBUG
LOG_I(NR_PHY,
"[RB %3i] noise_power_per_rb = %i, SNR_per_rb = %i dB\n",
rb,
noise_power_per_rb[rb],
dB_fixed(*signal_power) - dB_fixed(noise_power_per_rb[rb]));
#endif
}
}
#ifdef SRS_DEBUG
int32_t signal_power_dB = dB_fixed(*signal_power);
int32_t noise_power_dB = dB_fixed(*noise_power);
LOG_I(NR_PHY,
"signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n",
signal_power_dB,
noise_power_dB,
signal_power_dB - noise_power_dB);
#endif
return 0; return 0;
} }
+37 -16
View File
@@ -75,22 +75,43 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
unsigned char symbol, unsigned char symbol,
uint32_t nb_re_pusch); uint32_t nb_re_pusch);
int nr_srs_channel_estimation(int ant, int nr_srs_ls_channel_estimation(int ant,
int p_index, int p_index,
uint16_t ofdm_symbol_size, uint16_t ofdm_symbol_size,
uint16_t first_carrier_offset, uint16_t first_carrier_offset,
uint8_t N_symb_SRS, uint8_t N_symb_SRS,
const nfapi_nr_srs_pdu_t *srs_pdu, const nfapi_nr_srs_pdu_t *srs_pdu,
const nr_srs_info_t *nr_srs_info, const nr_srs_info_t *nr_srs_info,
const c16_t *srs_generated_signal, const c16_t *srs_generated_signal,
c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS],
c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], delay_t *delay);
c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], int nr_srs_channel_interpolation(int ant,
uint32_t *signal_power, int p_index,
uint32_t *noise_power, uint16_t ofdm_symbol_size,
int16_t *noise_power_per_rb); uint16_t first_carrier_offset,
uint8_t N_symb_SRS,
const nfapi_nr_srs_pdu_t *srs_pdu,
const nr_srs_info_t *nr_srs_info,
const c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS],
int est_delay,
c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS],
c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
uint32_t *signal_power,
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]);
void nr_srs_noise_power_estimation(uint16_t ofdm_symbol_size,
uint16_t first_carrier_offset,
uint8_t N_symb_SRS,
const nfapi_nr_srs_pdu_t *srs_pdu,
const nr_srs_info_t *nr_srs_info,
uint32_t signal_power,
const c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS],
uint32_t *noise_power,
int16_t *noise_power_per_rb);
void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms,
c16_t *rxdataF_comp, c16_t *rxdataF_comp,
-29
View File
@@ -61,38 +61,9 @@
#define SSS_METRIC_FLOOR_NR (30000) #define SSS_METRIC_FLOOR_NR (30000)
/************** VARIABLES *****************************************/
#define PHASE_HYPOTHESIS_NUMBER (16)
#define INDEX_NO_PHASE_DIFFERENCE (3) /* this is for no phase shift case */
/************** FUNCTION ******************************************/
static const c16_t phase_nr[PHASE_HYPOTHESIS_NUMBER] = {
// {pi/3 ---- pi/3, -pi/3 ---- pi/3}
{16384, -28377},
{20173, -25821},
{23571, -22762},
{26509, -19260},
{28932, -15383},
{30791, -11207},
{32051, -6813},
{32687, -2286},
{32687, 2286},
{32051, 6813},
{30791, 11207},
{28932, 15383},
{26509, 19260},
{23571, 22762},
{20173, 25821},
{16384, 28377}};
void init_context_sss_nr(int amp); void init_context_sss_nr(int amp);
void free_context_sss_nr(void); void free_context_sss_nr(void);
void insert_sss_nr(int16_t *sss_time,
NR_DL_FRAME_PARMS *frame_parms);
bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
int nid2, int nid2,
int target_Nid_cell, int target_Nid_cell,
+27 -17
View File
@@ -39,8 +39,7 @@
void init_prach_list(prach_list_t *l) void init_prach_list(prach_list_t *l)
{ {
pthread_mutex_init(&l->prach_list_mutex, NULL); pthread_mutex_init(&l->prach_list_mutex, NULL);
for (prach_item_t *p = l->list; p < l->list + NUMBER_OF_NR_PRACH_MAX; p++) memset(l->list, 0, sizeof(l->list));
*p = (prach_item_t){.frame = -1, .slot = -1};
} }
void free_nr_prach_entry(prach_list_t *l, prach_item_t *p) void free_nr_prach_entry(prach_list_t *l, prach_item_t *p)
@@ -48,17 +47,18 @@ void free_nr_prach_entry(prach_list_t *l, prach_item_t *p)
pthread_mutex_lock(&l->prach_list_mutex); pthread_mutex_lock(&l->prach_list_mutex);
if (p->frame == -1) if (p->frame == -1)
LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n"); LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n");
*p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1}; *p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1, .nb_rx = p->nb_rx, .prach_buf = (void *)(p + 1)};
pthread_mutex_unlock(&l->prach_list_mutex); pthread_mutex_unlock(&l->prach_list_mutex);
} }
prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t type) prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, int nb_rx, find_type_t type)
{ {
pthread_mutex_lock(&l->prach_list_mutex); pthread_mutex_lock(&l->prach_list_mutex);
prach_item_t *p = l->list; AssertFatal(nb_rx, "Error! Number of antennas set to 0.\n");
prach_item_t *end = p + NUMBER_OF_NR_PRACH_MAX; prach_item_t **p = l->list;
prach_item_t **end = p + NUMBER_OF_NR_PRACH_MAX;
for (; p < end; p++) for (; p < end; p++)
if (p->frame == frame && (p->slot + p->num_slots - 1) == slot) if ((*p) && (*p)->frame == frame && ((*p)->slot + (*p)->num_slots - 1) == slot)
break; break;
if (p == end) { if (p == end) {
if (type == SEARCH_EXIST) { if (type == SEARCH_EXIST) {
@@ -66,7 +66,7 @@ prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t ty
return NULL; return NULL;
} }
for (p = l->list; p < end; p++) for (p = l->list; p < end; p++)
if (p->frame == -1 && p->slot == -1) if (!(*p) || ((*p)->frame == -1 && (*p)->slot == -1))
break; break;
} }
if (p == end) { if (p == end) {
@@ -74,14 +74,24 @@ prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t ty
return NULL; return NULL;
} }
// mark it used, it will be filled later // mark it used, it will be filled later
p->frame = frame; if (*p && (*p)->nb_rx != nb_rx) {
LOG_W(PHY, "rach procedure nb_rx ant changed from %d to %d\n", (*p)->nb_rx, nb_rx);
free(*p);
*p = NULL;
}
if (!(*p)) {
*p = calloc(1, sizeof(prach_item_t) + sizeof(c16_t) * nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L);
(*p)->prach_buf = (void *)((*p) + 1);
}
(*p)->nb_rx = nb_rx;
(*p)->frame = frame;
pthread_mutex_unlock(&l->prach_list_mutex); pthread_mutex_unlock(&l->prach_list_mutex);
return p; return (*p);
} }
prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
{ {
prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, SEARCH_EXIST_OR_FREE); prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, gNB->frame_parms.nb_antennas_rx, SEARCH_EXIST_OR_FREE);
if (!prach) { if (!prach) {
LOG_W(PHY, "no free space for a new detected rach, discarding\n"); LOG_W(PHY, "no free space for a new detected rach, discarding\n");
return NULL; return NULL;
@@ -380,7 +390,7 @@ static void rx_nr_prach_ru_internal(prach_item_t *p,
rxsigF_tmp[j] = c16add(rxsigF_tmp[j], tmp[k2]); rxsigF_tmp[j] = c16add(rxsigF_tmp[j], tmp[k2]);
} }
} }
memcpy(p->rxsigF[prachOccasion][aa], rxsigF_tmp, sizeof(rxsigF_tmp)); memcpy(p->prach_buf[aa][prachOccasion], rxsigF_tmp, sizeof(rxsigF_tmp));
} }
} }
@@ -444,7 +454,7 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion)
int32_t prach_ifft[dft_sz] __attribute__((aligned(32))); int32_t prach_ifft[dft_sz] __attribute__((aligned(32)));
for (int preamble_index = 0; preamble_index < 64; preamble_index++) { for (int preamble_index = 0; preamble_index < 64; preamble_index++) {
if (LOG_DEBUGFLAG(DEBUG_PRACH)) { if (LOG_DEBUGFLAG(DEBUG_PRACH)) {
int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], N_ZC == 839 ? 840 : 140)); int en = dB_fixed(signal_energy((int32_t *)in->prach_buf[0][occasion], N_ZC == 839 ? 840 : 140));
if (en > 60) if (en > 60)
LOG_D(PHY, "frame %d, slot %d : Trying preamble %d \n", in->frame, in->slot, preamble_index); LOG_D(PHY, "frame %d, slot %d : Trying preamble %d \n", in->frame, in->slot, preamble_index);
} }
@@ -520,7 +530,7 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion)
// Compute DFT of RX signal (conjugate in->rxsigF[occasion], results in conjugate output) for each new rootSequenceIndex // Compute DFT of RX signal (conjugate in->rxsigF[occasion], results in conjugate output) for each new rootSequenceIndex
if (LOG_DEBUGFLAG(DEBUG_PRACH)) { if (LOG_DEBUGFLAG(DEBUG_PRACH)) {
int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], 840)); int en = dB_fixed(signal_energy((int32_t *)in->prach_buf[0][occasion], 840));
if (en>60) if (en>60)
LOG_D(PHY, LOG_D(PHY,
"frame %d, slot %d : preamble index %d, NCS %d, N_ZC/NCS %d: offset %d, preamble shift %d , en %d)\n", "frame %d, slot %d : preamble index %d, NCS %d, N_ZC/NCS %d: offset %d, preamble shift %d , en %d)\n",
@@ -549,14 +559,14 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion)
memset(prach_ifft, 0, sizeof(prach_ifft)); memset(prach_ifft, 0, sizeof(prach_ifft));
if (LOG_DUMPFLAG(DEBUG_PRACH)) { if (LOG_DUMPFLAG(DEBUG_PRACH)) {
LOG_M("prach_rxF0.m", "prach_rxF0", in->rxsigF[occasion][0], N_ZC, 1, 1); LOG_M("prach_rxF0.m", "prach_rxF0", in->prach_buf[0][occasion], N_ZC, 1, 1);
LOG_M("prach_rxF1.m", "prach_rxF1", in->rxsigF[occasion][1], 6144, 1, 1); LOG_M("prach_rxF1.m", "prach_rxF1", in->prach_buf[1][occasion], 6144, 1, 1);
} }
c16_t prachF[dft_sz] __attribute__((aligned(32))); c16_t prachF[dft_sz] __attribute__((aligned(32)));
for (int aa = 0; aa < nb_rx; aa++) { for (int aa = 0; aa < nb_rx; aa++) {
// Do componentwise product with Xu* on each antenna // Do componentwise product with Xu* on each antenna
for (int offset = 0; offset < N_ZC; offset++) { for (int offset = 0; offset < N_ZC; offset++) {
prachF[offset] = c16MulConjShift(Xu[offset], in->rxsigF[occasion][aa][offset], 15); prachF[offset] = c16MulConjShift(Xu[offset], in->prach_buf[aa][occasion][offset], 15);
} }
memset(prachF + N_ZC, 0, sizeof(*prachF) * (dft_sz - N_ZC)); memset(prachF + N_ZC, 0, sizeof(*prachF) * (dft_sz - N_ZC));
// Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139)
+3 -10
View File
@@ -23,11 +23,7 @@
//#define NR_SSS_DEBUG //#define NR_SSS_DEBUG
int nr_generate_sss( c16_t *txdataF, int nr_generate_sss(c16_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, int Nid, NR_DL_FRAME_PARMS *frame_parms)
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t* config,
NR_DL_FRAME_PARMS *frame_parms)
{ {
int16_t x0[NR_SSS_LENGTH]; int16_t x0[NR_SSS_LENGTH];
int16_t x1[NR_SSS_LENGTH]; int16_t x1[NR_SSS_LENGTH];
@@ -35,7 +31,6 @@ int nr_generate_sss( c16_t *txdataF,
const int x1_initial[7] = { 1, 0, 0, 0, 0, 0, 0 }; const int x1_initial[7] = { 1, 0, 0, 0, 0, 0, 0 };
/// Sequence generation /// Sequence generation
int Nid = config->cell_config.phy_cell_id.value;
int Nid2 = Nid % 3; int Nid2 = Nid % 3;
int Nid1 = (Nid - Nid2)/3; int Nid1 = (Nid - Nid2)/3;
@@ -59,13 +54,11 @@ int nr_generate_sss( c16_t *txdataF,
/// Resource mapping /// Resource mapping
// SSS occupies a predefined position (subcarriers 56-182, symbol 2) within the SSB block starting from // SSS occupies a predefined position (subcarriers 56-182, symbol 2) within the SSB block starting from
int k = frame_parms->ssb_start_subcarrier + 56; c16_t *tx = txdataF + (ssb_start_symbol + 2) * frame_parms->ofdm_symbol_size + frame_parms->ssb_start_subcarrier + 56;
int l = ssb_start_symbol + 2;
for (int i = 0; i < NR_SSS_LENGTH; i++) { for (int i = 0; i < NR_SSS_LENGTH; i++) {
int16_t d_sss = (1 - 2*x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2*x1[(i + m1) % NR_SSS_LENGTH] ) * 23170; int16_t d_sss = (1 - 2*x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2*x1[(i + m1) % NR_SSS_LENGTH] ) * 23170;
((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_sss) >> 15; *tx++ = (c16_t){.r = (amp * d_sss) >> 15};
k++;
} }
#ifdef NR_SSS_DEBUG #ifdef NR_SSS_DEBUG
// write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); // write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1);
@@ -60,11 +60,7 @@ int nr_generate_pss(c16_t *txdataF,
@param @param
@returns 0 on success @returns 0 on success
*/ */
int nr_generate_sss(c16_t *txdataF, int nr_generate_sss(c16_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, int nid, NR_DL_FRAME_PARMS *frame_parms);
int16_t amp,
uint8_t ssb_start_symbol,
nfapi_nr_config_request_scf_t *config,
NR_DL_FRAME_PARMS *frame_parms);
/*! /*!
\fn void nr_generate_pbch_dmrs \fn void nr_generate_pbch_dmrs
@@ -206,7 +202,7 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion);
void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset); void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset);
prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, find_type_t type); prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, int nb_rx, find_type_t type);
void nr_fill_pucch(PHY_VARS_gNB *gNB, void nr_fill_pucch(PHY_VARS_gNB *gNB,
int frame, int frame,
int slot, int slot,
+2 -4
View File
@@ -58,7 +58,6 @@
void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu)
{ {
bool found = false;
for (int i = 0; i < gNB->max_nb_pucch; i++) { for (int i = 0; i < gNB->max_nb_pucch; i++) {
NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; NR_gNB_PUCCH_t *pucch = &gNB->pucch[i];
if (pucch->active == false) { if (pucch->active == false) {
@@ -86,11 +85,10 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t
pucch->pucch_pdu.bit_len_harq, pucch->pucch_pdu.bit_len_harq,
pucch->pucch_pdu.sr_flag, pucch->pucch_pdu.sr_flag,
pucch->pucch_pdu.bit_len_csi_part1); pucch->pucch_pdu.bit_len_csi_part1);
found = true; return;
break;
} }
} }
AssertFatal(found, "PUCCH list is full\n"); LOG_W(PHY, "PUCCH list is full\n");
} }
@@ -147,37 +147,25 @@ uint32_t nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp,
int symbol_offset, int symbol_offset,
int ssb_start_subcarrier) int ssb_start_subcarrier)
{ {
int k_start = 56; const int k_start = 56;
int k_end = 183; const int k_end = 183;
unsigned int ssb_offset = fp->first_carrier_offset + ssb_start_subcarrier; const unsigned int ssb_offset = fp->first_carrier_offset + ssb_start_subcarrier;
const uint8_t l_sss = (symbol_offset + 2) % fp->symbols_per_slot;
uint8_t l_sss = (symbol_offset + 2) % fp->symbols_per_slot;
uint32_t rsrp = 0; uint32_t rsrp = 0;
LOG_D(PHY, "In %s: l_sss %d ssb_offset %d\n", __FUNCTION__, l_sss, ssb_offset); LOG_D(PHY, "In %s: l_sss %d ssb_offset %d\n", __FUNCTION__, l_sss, ssb_offset);
int nb_re = 0; int nb_re = 0;
for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) {
int16_t *rxF_sss = (int16_t *)&rxdataF[aarx][l_sss * fp->ofdm_symbol_size]; const c16_t *rxF_sss = &rxdataF[aarx][l_sss * fp->ofdm_symbol_size];
for(int k = k_start; k < k_end; k++){ for(int k = k_start; k < k_end; k++){
int re = (ssb_offset + k) % fp->ofdm_symbol_size; int re = (ssb_offset + k) % fp->ofdm_symbol_size;
rsrp += squaredMod(rxF_sss[re]);
#ifdef DEBUG_MEAS_UE
LOG_I(PHY, "In %s rxF_sss[%d] %d %d\n", __FUNCTION__, re, rxF_sss[re * 2], rxF_sss[re * 2 + 1]);
#endif
rsrp += (((int32_t)rxF_sss[re*2]*rxF_sss[re*2]) + ((int32_t)rxF_sss[re*2 + 1]*rxF_sss[re*2 + 1]));
nb_re++; nb_re++;
} }
} }
rsrp /= nb_re; rsrp /= nb_re;
LOG_D(PHY, "In %s: RSRP/nb_re: %d nb_re :%d\n", __FUNCTION__, rsrp, nb_re); LOG_D(PHY, "In %s: RSRP/nb_re: %d nb_re :%d\n", __FUNCTION__, rsrp, nb_re);
return rsrp; return rsrp;
} }
@@ -161,7 +161,6 @@ static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *sl_fp = &ue->SL_UE_PHY_PARAMS.sl_frame_params; NR_DL_FRAME_PARMS *sl_fp = &ue->SL_UE_PHY_PARAMS.sl_frame_params;
int16_t *d; int16_t *d;
uint16_t Nid1 = 0; uint16_t Nid1 = 0;
uint8_t phase;
c16_t *rxF_ext; c16_t *rxF_ext;
for (int aarx = 0; aarx < sl_fp->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < sl_fp->nb_antennas_rx; aarx++) {
@@ -260,15 +259,16 @@ static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue,
c16_t *sss = &sss_ext[0][0][0]; c16_t *sss = &sss_ext[0][0][0];
for (uint16_t id1 = 0; id1 < SL_NR_NUM_IDs_IN_SSS; id1++) { // all possible SSS Nid1 values for (uint16_t id1 = 0; id1 < SL_NR_NUM_IDs_IN_SSS; id1++) { // all possible SSS Nid1 values
for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS for (int phase = -15; phase < 16; phase += 2) { // phase offset between PSS and SSS
int32_t metric = 0, metric_re = 0; int32_t metric = 0, metric_re = 0;
const c64_t rot = (c64_t){round(cos(M_PI / 3 / 15 * (phase)) * 32767), round(sin(M_PI / 3 / 15 * (phase)) * 32767)};
d = (int16_t *)&ue->SL_UE_PHY_PARAMS.init_params.sl_sss_for_sync[Nid2 * SL_NR_NUM_IDs_IN_SSS + id1]; d = (int16_t *)&ue->SL_UE_PHY_PARAMS.init_params.sl_sss_for_sync[Nid2 * SL_NR_NUM_IDs_IN_SSS + id1];
// This is the inner product using one particular value of each unknown parameter // This is the inner product using one particular value of each unknown parameter
for (int i = 0; i < SL_NR_SSS_SEQUENCE_LENGTH; i++) { for (int i = 0; i < SL_NR_SSS_SEQUENCE_LENGTH; i++) {
metric_re += d[i] * (((int64_t)phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i) >> 15); // metric is only real part because sss is a pure real signal (imaginary is 0)
metric_re += d[i] * ((rot.r * sss[i].r - rot.i * sss[i].i) >> 15);
} }
metric = metric_re; metric = metric_re;
+43 -139
View File
@@ -49,24 +49,12 @@
//#define DBG_PSS_NR //#define DBG_PSS_NR
static time_stats_t generic_time[TIME_LAST]; static time_stats_t generic_time[TIME_LAST];
int pss_search_time_nr(const c16_t **rxdata,
const NR_DL_FRAME_PARMS *frame_parms,
const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size],
bool fo_flag,
int is,
int target_Nid_cell,
int *nid2,
int *f_off,
int *pssPeak,
int *pssAvg,
int search_start,
int search_length);
static int16_t primary_synchro_nr2[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0}; static int16_t d_pss[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0};
static c16_t primary_synchro[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0}; static c16_t primary_synchro[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0};
int16_t *get_primary_synchro_nr2(const int nid2) int16_t *get_primary_synchro_nr2(const int nid2)
{ {
return primary_synchro_nr2[nid2]; return d_pss[nid2];
} }
/******************************************************************* /*******************************************************************
@@ -86,12 +74,9 @@ int16_t *get_primary_synchro_nr2(const int nid2)
void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
{ {
AssertFatal(fp->ofdm_symbol_size > 127,"Illegal ofdm_symbol_size %d\n",fp->ofdm_symbol_size); AssertFatal(fp->ofdm_symbol_size > 127,"Illegal ofdm_symbol_size %d\n",fp->ofdm_symbol_size);
AssertFatal(N_ID_2>=0 && N_ID_2 <=2,"Illegal N_ID_2 %d\n",N_ID_2); AssertFatal(N_ID_2 >= 0 && N_ID_2 <= 2, "Illegal N_ID_2 %d\n", N_ID_2);
int16_t d_pss[LENGTH_PSS_NR];
int16_t x[LENGTH_PSS_NR]; int16_t x[LENGTH_PSS_NR];
int16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2]; /* pss in complex with alternatively i then q */
#define INITIAL_PSS_NR (7) #define INITIAL_PSS_NR (7)
const int16_t x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1}; const int16_t x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1};
assert(N_ID_2 < NUMBER_PSS_SEQUENCE); assert(N_ID_2 < NUMBER_PSS_SEQUENCE);
@@ -99,16 +84,15 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++)
x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2); x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2);
int16_t *pss = d_pss[N_ID_2];
for (int n=0; n < LENGTH_PSS_NR; n++) { for (int n=0; n < LENGTH_PSS_NR; n++) {
const int m = (n + 43 * N_ID_2) % (LENGTH_PSS_NR); const int m = (n + 43 * N_ID_2) % (LENGTH_PSS_NR);
d_pss[n] = 1 - 2*x[m]; pss[n] = 1 - 2 * x[m];
} }
/* PSS is directly mapped to subcarrier without modulation 38.211 */ /* PSS is directly mapped to subcarrier without modulation 38.211 */
for (int i=0; i < LENGTH_PSS_NR; i++) { for (int i=0; i < LENGTH_PSS_NR; i++) {
primary_synchro[N_ID_2][i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */ primary_synchro[N_ID_2][i].r = (pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */
primary_synchro2[i] = d_pss[i];
} }
#ifdef DBG_PSS_NR #ifdef DBG_PSS_NR
@@ -150,12 +134,13 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2)
void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssbFirstSCS, c16_t pssTime[fp->ofdm_symbol_size]) void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssbFirstSCS, c16_t pssTime[fp->ofdm_symbol_size])
{ {
unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL; unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL;
unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start;
if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size;
c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32))); c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32)));
memset(synchroF_tmp, 0, sizeof(synchroF_tmp)); memset(synchroF_tmp, 0, sizeof(synchroF_tmp));
unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start;
for (int i=0; i < LENGTH_PSS_NR; i++) { for (int i=0; i < LENGTH_PSS_NR; i++) {
synchroF_tmp[k % fp->ofdm_symbol_size] = primary_synchro[N_ID_2][i]; if (k >= fp->ofdm_symbol_size)
k -= fp->ofdm_symbol_size;
synchroF_tmp[k] = primary_synchro[N_ID_2][i];
k++; k++;
} }
@@ -182,54 +167,6 @@ void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssb
} }
#endif #endif
#if 0
/* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */
if ((N_ID_2 == 0) && (length == 256)) {
LOG_M("pss_f00.m","pss_f00",synchro_tmp,length,1,1);
bzero(synchroF_tmp, size);
/* get pss in the time domain by applying an inverse FFT */
dft((int16_t)get_dft(length),
synchro_tmp, /* complex input */
synchroF_tmp, /* complex output */
1); /* scaling factor */
if ((N_ID_2 == 0) && (length == 256)) {
LOG_M("pss_f_0.m","pss_f_0",synchroF_tmp,length,1,1);
}
/* check Pss */
k = length - (LENGTH_PSS_NR/2);
#define LIMIT_ERROR_FFT (10)
for (int i=0; i < LENGTH_PSS_NR; i++) {
if (abs(synchroF_tmp[2*k] - primary_synchro[i].r) > LIMIT_ERROR_FFT) {
printf("Pss Error[%d] Compute %d Reference %d \n", k, synchroF_tmp[2*k], primary_synchro[i].r);
}
if (abs(synchroF_tmp[2*k+1] - primary_synchro[i].i) > LIMIT_ERROR_FFT) {
printf("Pss Error[%d] Compute %d Reference %d\n", (2*k+1), synchroF_tmp[2*k+1], primary_synchro[i].i);
}
k++;
if (k >= length) {
k-=length;
}
}
}
#endif
} }
/******************************************************************* /*******************************************************************
@@ -391,49 +328,31 @@ int pss_synchro_nr(const c16_t **rxdata,
int *pssAvg) int *pssAvg)
{ {
#ifdef DBG_PSS_NR #ifdef DBG_PSS_NR
LOG_M("rxdata0_rand.m", "rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], frame_parms->samples_per_frame, 1, 1);
LOG_M("rxdata0_rand.m","rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], frame_parms->samples_per_frame, 1, 1); LOG_M("rxdata0_des.m", "rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame, 1, 1);
#endif
#ifdef DBG_PSS_NR
LOG_M("rxdata0_des.m","rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame,1,1);
#endif #endif
start_meas(&generic_time[TIME_PSS]); start_meas(&generic_time[TIME_PSS]);
int synchro_position = int synchro_position =
pss_search_time_nr(rxdata, frame_parms, pssTime, fo_flag, is, target_Nid_cell, nid2, f_off, pssPeak, pssAvg, -1, -1); pss_search_time_nr(rxdata, frame_parms, pssTime, fo_flag, is, target_Nid_cell, nid2, f_off, pssPeak, pssAvg, -1, -1);
stop_meas(&generic_time[TIME_PSS]);
#if TEST_SYNCHRO_TIMING_PSS #if TEST_SYNCHRO_TIMING_PSS
stop_meas(&generic_time[TIME_PSS]); int duration_ms = generic_time[TIME_PSS].p_time / (cpuf * 1000.0);
#ifndef NR_UNIT_TEST
int duration_ms = generic_time[TIME_PSS].p_time/(cpuf*1000.0); LOG_D(PHY, "PSS execution duration %4d microseconds \n", duration_ms);
#endif
#ifndef NR_UNIT_TEST
LOG_D(PHY,"PSS execution duration %4d microseconds \n", duration_ms);
#endif
#endif #endif
#ifdef SYNCHRO_DECIMAT #ifdef SYNCHRO_DECIMAT
if (rate_change != 1) { if (rate_change != 1) {
if (rxdata[0] != NULL) { if (rxdata[0] != NULL) {
for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) { for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
free(rxdata[aa]); free(rxdata[aa]);
} }
free(rxdata); free(rxdata);
} }
restore_frame_context_pss_nr(frame_parms, rate_change); restore_frame_context_pss_nr(frame_parms, rate_change);
} }
#endif #endif
@@ -504,11 +423,6 @@ int pss_search_time_nr(const c16_t **rxdata,
int search_start, int search_start,
int search_length) int search_length)
{ {
unsigned int n, ar, peak_position, pss_source;
int64_t peak_value;
int64_t avg[NUMBER_PSS_SEQUENCE] = {0};
double ffo_est = 0;
// Determine search window // Determine search window
unsigned int start, length; unsigned int start, length;
if (search_start >= 0 && search_length > 0) { if (search_start >= 0 && search_length > 0) {
@@ -524,11 +438,7 @@ int pss_search_time_nr(const c16_t **rxdata,
length = frame_parms->samples_per_frame; length = frame_parms->samples_per_frame;
} }
AssertFatal(length>0,"illegal length %d\n",length); AssertFatal(length > 0, "illegal length %d\n", length);
peak_value = 0;
peak_position = 0;
pss_source = 0;
int maxval=0; int maxval=0;
int max_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; int max_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL;
for (int j = 0; j < max_size; j++) for (int j = 0; j < max_size; j++)
@@ -542,37 +452,37 @@ int pss_search_time_nr(const c16_t **rxdata,
/* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */ /* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */
/* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */ /* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */
uint16_t pss_index_start = 0; int pss_index_start;
uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; int pss_index_end;
if (target_Nid_cell != -1) { if (target_Nid_cell != -1) {
pss_index_start = GET_NID2(target_Nid_cell); pss_index_start = GET_NID2(target_Nid_cell);
pss_index_end = pss_index_start + 1; pss_index_end = pss_index_start + 1;
} else {
pss_index_start = 0;
pss_index_end = max_size;
} }
int64_t avg[NUMBER_PSS_SEQUENCE] = {0};
int64_t peak_value = 0;
unsigned int peak_position = 0;
unsigned int pss_source = 0;
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) { for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) {
for (n = start; n < start + length; n += 4) { // for (int n = start; n < start + length; n += 4) { //
int64_t pss_corr_ue = 0;
int64_t pss_corr_ue=0;
/* calculate dot product of primary_synchro_time_nr and rxdata[ar][n] /* calculate dot product of primary_synchro_time_nr and rxdata[ar][n]
* (ar=0..nb_ant_rx) and store the sum in temp[n]; */ * (ar=0..nb_ant_rx) and store the sum in temp[n]; */
for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) { for (int ar = 0; ar < frame_parms->nb_antennas_rx; ar++) {
/* perform correlation of rx data and pss sequence ie it is a dot product */ /* perform correlation of rx data and pss sequence ie it is a dot product */
const c32_t result = dot_product(pssTime[pss_index], const c32_t result = dot_product(pssTime[pss_index],
&(rxdata[ar][n + is * frame_parms->samples_per_frame]), &rxdata[ar][n + is * frame_parms->samples_per_frame],
frame_parms->ofdm_symbol_size, frame_parms->ofdm_symbol_size,
shift); shift);
const c64_t r64 = {.r = result.r, .i = result.i}; const c64_t r64 = {.r = result.r, .i = result.i};
pss_corr_ue += squaredMod(r64); pss_corr_ue += squaredMod(r64);
//((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */
//((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
//((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */
//((short*)&synchro_out)[1] += ((int*) &result)[1]; /* imaginary part */
} }
/* calculate the absolute value of sync_corr[n] */ /* calculate the absolute value of sync_corr[n] */
avg[pss_index]+=pss_corr_ue; avg[pss_index] += pss_corr_ue;
if (pss_corr_ue > peak_value) { if (pss_corr_ue > peak_value) {
peak_value = pss_corr_ue; peak_value = pss_corr_ue;
peak_position = n; peak_position = n;
@@ -583,12 +493,14 @@ int pss_search_time_nr(const c16_t **rxdata,
#endif #endif
} }
} }
avg[pss_index] /= (length / 4);
} }
if (fo_flag){ double ffo_est = 0;
if (fo_flag) {
// fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS // fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS
// Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th
// International Conference on Communications and Networking in China, 2012.
// Computing cross-correlation at peak on half the symbol size for first half of data // Computing cross-correlation at peak on half the symbol size for first half of data
c32_t r1 = dot_product(pssTime[pss_source], c32_t r1 = dot_product(pssTime[pss_source],
@@ -606,15 +518,11 @@ int pss_search_time_nr(const c16_t **rxdata,
ffo_est = atan2(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI; ffo_est = atan2(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI;
#ifdef DBG_PSS_NR #ifdef DBG_PSS_NR
printf("ffo %lf\n",ffo_est); printf("ffo %lf\n", ffo_est);
#endif #endif
} }
// computing absolute value of frequency offset // computing absolute value of frequency offset
*f_off = ffo_est*frame_parms->subcarrier_spacing; *f_off = ffo_est * frame_parms->subcarrier_spacing;
for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++)
avg[pss_index] /= (length / 4);
*nid2 = pss_source; *nid2 = pss_source;
*pssPeak = dB_fixed64(peak_value); *pssPeak = dB_fixed64(peak_value);
@@ -631,22 +539,18 @@ int pss_search_time_nr(const c16_t **rxdata,
ffo_est); ffo_est);
if ((search_start < 0 || search_length == 0) && peak_value < 5 * avg[pss_source]) if ((search_start < 0 || search_length == 0) && peak_value < 5 * avg[pss_source])
return(-1); return (-1);
#ifdef DBG_PSS_NR #ifdef DBG_PSS_NR
static int debug_cnt = 0; static int debug_cnt = 0;
if (debug_cnt == 0) { if (debug_cnt == 0) {
if (is) if (is)
LOG_M("rxdata1.m","rxd0",rxdata[frame_parms->samples_per_frame],length,1,1); LOG_M("rxdata1.m", "rxd0", rxdata[frame_parms->samples_per_frame], length, 1, 1);
else else
LOG_M("rxdata0.m","rxd0",rxdata[0],length,1,1); LOG_M("rxdata0.m", "rxd0", rxdata[0], length, 1, 1);
} else { } else {
debug_cnt++; debug_cnt++;
} }
#endif #endif
return peak_position; return peak_position;
+71 -275
View File
@@ -109,71 +109,8 @@ void init_context_sss_nr(int amp)
#endif #endif
} }
/******************************************************************* // #define DEBUG_SSS_NR
* // #define DEBUG_PLOT_SSS
* NAME : insert_sss_nr
*
* PARAMETERS : pointer to input buffer for which sss in inserted
* amp amplitude applied to input
* frame parameters for cell identity
*
* RETURN : none
*
* DESCRIPTION : Allow to generate a reference sss sequence according to cell identity
*
*********************************************************************/
//#define DEBUG_SSS_NR
//#define DEBUG_PLOT_SSS
void insert_sss_nr(int16_t *sss_time,
NR_DL_FRAME_PARMS *frame_parms)
{
const unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
int Nid2 = GET_NID2(frame_parms->Nid_cell);
int Nid1 = GET_NID1(frame_parms->Nid_cell);
/* call of IDFT should be done with ordered input as below
*
* n input samples
* <------------------------------------------------>
* 0 n
* are written into input buffer for IFFT in this order
* -------------------------------------------------
* |xxxxxxx N/2 xxxxxxxx|
* --------------------------------------------------
* ^ ^ ^ ^ ^
* | | | | |
* n/2 end of n=0 start of n/2-1
* sss sss
*
* Frequencies
* positives negatives
* 0 (+N/2)(-N/2)
* |-----------------------><-------------------------|
*
* sample 0 is for continuous frequency which is not used here
*/
unsigned int k = ofdm_symbol_size - ((LENGTH_SSS_NR/2)+1);
c16_t synchroF_tmp[2048] __attribute__((aligned(32)));
c16_t synchro_tmp[2048] __attribute__((aligned(32)));
bzero(synchroF_tmp, sizeof(synchroF_tmp));
/* SSS is directly mapped to subcarrier */
for (int i=0; i<LENGTH_SSS_NR; i++) {
synchroF_tmp[k % ofdm_symbol_size].r = d_sss[Nid2][Nid1][i];
k++;
}
/* get sss in the frequency domain by applying an inverse FFT */
idft(IDFT_2048,
(int16_t *)synchroF_tmp, /* complex input */
(int16_t *)synchro_tmp, /* complex output */
1); /* scaling factor */
/* then get final sss in time */
memcpy(sss_time, synchro_tmp, ofdm_symbol_size * sizeof(c16_t));
}
/******************************************************************* /*******************************************************************
* *
@@ -187,7 +124,7 @@ void insert_sss_nr(int16_t *sss_time,
* *
*********************************************************************/ *********************************************************************/
static int pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms, static void pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms,
int nid2, int nid2,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR], c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR]) c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR])
@@ -199,148 +136,60 @@ static int pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t *pss_ext2 = pss_ext[aarx]; c16_t *pss_ext2 = pss_ext[aarx];
for (int i = 0; i < LENGTH_PSS_NR; i++) { for (int i = 0; i < LENGTH_PSS_NR; i++) {
// This is H*(PSS) = R* \cdot PSS // This is H*(PSS) = R* \cdot PSS
const int tmp_re = pss_ext2[i].r * pss[i]; const c16_t tmp = (c16_t){pss_ext2[i].r * pss[i], -pss_ext2[i].i * pss[i]};
const int tmp_im = -pss_ext2[i].i * pss[i]; const int32_t amp = squaredMod(tmp);
const int32_t amp = tmp_re * tmp_re + tmp_im * tmp_im;
const int shift = log2_approx(amp) / 2; const int shift = log2_approx(amp) / 2;
// This is R(SSS) \cdot H*(PSS) // This is R(SSS) \cdot H*(PSS)
const c16_t tmp = {(tmp_re * sss_ext2[i].r - tmp_im * sss_ext2[i].i) >> shift, const c16_t new_sss = c16mulShift(tmp, sss_ext2[i], shift);
(tmp_re * sss_ext2[i].i + tmp_im * sss_ext2[i].r) >> shift}; if (aarx == 0)
// printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]); sss_ext2[i] = new_sss;
// printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2); else
// MRC on RX antennas sss_ext2[i] = c16add(sss_ext2[i], new_sss);
if (aarx == 0) {
sss_ext2[i].r = tmp.r;
sss_ext2[i].i = tmp.i;
} else {
sss_ext2[i].r += tmp.r;
sss_ext2[i].i += tmp.i;
}
} }
} }
#if 0 // sss_ext[0] now contains the compensated SSS
LOG_M("pssrx.m","pssrx",pss,LENGTH_PSS_NR,1,1);
LOG_M("pss_ext.m","pssext",pss_ext2,LENGTH_PSS_NR,1,1);
LOG_M("psschest.m","pssch",chest,LENGTH_PSS_NR,1,1);
#endif
#if 0
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf(" sss ext 3 [%d] %d %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]);
}
#endif
// sss_ext now contains the compensated SSS
return(0);
} }
/******************************************************************* /*******************************************************************
* *
* NAME : do_pss_sss_extract * NAME : pss_sss_extract_nr
* *
* PARAMETERS : none * PARAMETERS : none
* *
* RETURN : none * RETURN : none
* *
* DESCRIPTION : it allows extracting sss from samples buffer * DESCRIPTION : it allows extracting sss from samples buffer
* *
*********************************************************************/ *********************************************************************/
static int do_pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms, static void pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR], c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR], c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR],
uint8_t doPss,
uint8_t doSss,
int ssb_start_subcarrier, int ssb_start_subcarrier,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both
{ {
AssertFatal(frame_parms->nb_antennas_rx > 0, "UB as sss_ext is not set to any value\n"); AssertFatal(frame_parms->nb_antennas_rx > 0, "nb antennas as sss_ext is not set to any value\n");
const unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
const int pss_symbol = 0;
const int sss_symbol =
get_softmodem_params()->sl_mode == 0 ? (SSS_SYMBOL_NB - PSS_SYMBOL_NB) : (SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB);
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
int pss_symbol = 0;
int sss_symbol = get_softmodem_params()->sl_mode == 0 ?
(SSS_SYMBOL_NB - PSS_SYMBOL_NB) :
(SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB) ;
unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
c16_t *pss_rxF = rxdataF[aarx] + pss_symbol * ofdm_symbol_size; c16_t *pss_rxF = rxdataF[aarx] + pss_symbol * ofdm_symbol_size;
c16_t *sss_rxF = rxdataF[aarx] + sss_symbol * ofdm_symbol_size; c16_t *sss_rxF = rxdataF[aarx] + sss_symbol * ofdm_symbol_size;
c16_t *pss_rxF_ext = pss_ext[aarx]; c16_t *pss_rxF_ext = pss_ext[aarx];
c16_t *sss_rxF_ext = sss_ext[aarx]; c16_t *sss_rxF_ext = sss_ext[aarx];
unsigned int k = frame_parms->first_carrier_offset + ssb_start_subcarrier unsigned int k = frame_parms->first_carrier_offset + ssb_start_subcarrier
+ ((get_softmodem_params()->sl_mode == 0) ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL); + ((get_softmodem_params()->sl_mode == 0) ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL);
if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size;
for (int i=0; i < LENGTH_PSS_NR; i++) { for (int i=0; i < LENGTH_PSS_NR; i++) {
if (doPss) { if (k >= frame_parms->ofdm_symbol_size)
pss_rxF_ext[i] = pss_rxF[k]; k -= frame_parms->ofdm_symbol_size;
} pss_rxF_ext[i] = pss_rxF[k];
sss_rxF_ext[i] = sss_rxF[k];
if (doSss) {
sss_rxF_ext[i] = sss_rxF[k];
}
k++; k++;
if (k == frame_parms->ofdm_symbol_size) k = 0;
} }
} }
#if 0
int16_t *p = (int16_t *)sss_rxF_ext;
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" sss ext 2 [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
}
#endif
#if 0
int16_t *p2 = (int16_t *)pss_rxF_ext;
for (int i = 0; i < LENGTH_PSS_NR; i++) {
printf(" pss_rxF_ext [%d] %d %d at address %p\n", i, p2[2*i], p2[2*i+1], &p2[2*i]);
}
#endif
return(0);
}
/*******************************************************************
*
* NAME : pss_sss_extract_nr
*
* PARAMETERS : none
*
* RETURN : none
*
* DESCRIPTION :
*
*********************************************************************/
static int pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR],
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR],
int ssb_start_subcarrier,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP])
{
return do_pss_sss_extract_nr(frame_parms,
pss_ext,
sss_ext,
1 /* doPss */,
1 /* doSss */,
ssb_start_subcarrier,
rxdataF);
} }
/******************************************************************* /*******************************************************************
@@ -366,44 +215,22 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
int *freq_offset_sss, int *freq_offset_sss,
c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) c16_t rxdataF[][frame_parms->samples_per_slot_wCP])
{ {
uint8_t i;
c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR]; c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR];
c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR]; c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR];
uint8_t Nid2 = GET_NID2(nid2); const int Nid2 = GET_NID2(nid2);
uint16_t Nid1;
uint8_t phase;
int32_t metric, metric_re;
int16_t *d;
// pss sss extraction // pss sss extraction
pss_sss_extract_nr(frame_parms, pss_ext, sss_ext, ssb_start_subcarrier, rxdataF); /* subframe */ pss_sss_extract_nr(frame_parms, pss_ext, sss_ext, ssb_start_subcarrier, rxdataF); /* subframe */
#ifdef DEBUG_PLOT_SSS #ifdef DEBUG_PLOT_SSS
write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1); write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1);
write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1); write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1);
write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1);
write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1); write_output("pss_ext.m", "pss_ext", pss_ext, LENGTH_PSS_NR, 1, 1);
#endif
#if 0
int16_t *p = (int16_t *)sss_ext[0];
int16_t *p2 = (int16_t *)pss_ext[0];
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
printf("sss ext [%i] : %d %d \n", i, p[2*i], p[2*i+1]);
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
printf("pss ext [%i] : %d %d \n", i, p2[2*i], p2[2*i+1]);
}
#endif #endif
// get conjugated channel estimate from PSS, H* = R* \cdot PSS // get conjugated channel estimate from PSS, H* = R* \cdot PSS
// and do channel estimation and compensation based on PSS // and do channel estimation and compensation based on PSS
pss_ch_est_nr(frame_parms, nid2, pss_ext, sss_ext); pss_ch_est_nr(frame_parms, nid2, pss_ext, sss_ext);
// now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h // now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h
@@ -411,91 +238,56 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
c16_t *sss = sss_ext[0]; c16_t *sss = sss_ext[0];
#ifdef DEBUG_PLOT_SSS
write_output("sss_ext.m","sss_ext",sss_ext[0],LENGTH_SSS_NR,1,1);
write_output("sss_ref.m","sss_ref", d_sss,LENGTH_SSS_NR,1,1);
#endif
#if 0
/* simulate of a phase shift on the signal */
int phase_shift_index = 0;
phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]);
#endif
#if 0
int16_t *ps = (int16_t *)pss_ext;
for (int i = 0; i < LENGTH_SSS_NR; i++) {
printf("sss ref [%i] : %d \n", i, d_sss[0][0][i]);
printf("sss ext [%i] : %d %d \n", i, sss[i].r, sss[i].i);
printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]);
printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]);
}
#endif
/* for phase evaluation, one uses an array of possible phase shifts */ /* for phase evaluation, one uses an array of possible phase shifts */
/* then a correlation is done between received signal with a shift pĥase and the reference signal */ /* then a correlation is done between received signal with a shift pĥase and the reference signal */
/* Computation of signal with shift phase is based on below formula */ /* Computation of signal with shift phase is based on below formula */
/* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */ /* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
/* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */ /* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
uint16_t Nid1_start = 0; int Nid1_start = 0;
uint16_t Nid1_end = N_ID_1_NUMBER; int Nid1_end = N_ID_1_NUMBER;
if (target_Nid_cell != -1) { if (target_Nid_cell != -1) {
Nid1_start = GET_NID1(target_Nid_cell); Nid1_start = GET_NID1(target_Nid_cell);
Nid1_end = Nid1_start + 1; Nid1_end = Nid1_start + 1;
} }
for (Nid1 = Nid1_start; Nid1 < Nid1_end; Nid1++) { // all possible Nid1 values const int phase_to_try[] = {0, 2, -2, 4, -4, 6, -6, 8, -8, 10, -10, 12, -12, 14, -14};
for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS for (int idx = 0; idx < sizeofArray(phase_to_try); idx++) { // phase offset between PSS and SSS
const c64_t rot =
metric = 0; (c64_t){round(cos(M_PI / 3 / 15 * (phase_to_try[idx])) * 32767), round(sin(M_PI / 3 / 15 * (phase_to_try[idx])) * 32767)};
metric_re = 0; for (int n1 = Nid1_start; n1 < Nid1_end; n1++) { // all possible Nid1 values
int64_t metric = 0;
d = (int16_t *)&d_sss[Nid2][Nid1]; int16_t *d = d_sss[Nid2][n1];
for (int i = 0; i < LENGTH_SSS_NR; i++) {
// This is the inner product using one particular value of each unknown parameter // metric is only real part because sss is a pure real signal (imaginary is 0)
for (i=0; i < LENGTH_SSS_NR; i++) { metric += d[i] * (rot.r * sss[i].r - rot.i * sss[i].i);
metric_re += d[i] * ((phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i) >> SCALING_METRIC_SSS_NR);
} }
metric >>= SCALING_METRIC_SSS_NR;
metric = metric_re;
// if the current metric is better than the last save it // if the current metric is better than the last save it
if (metric > *tot_metric) { if (metric > *tot_metric) {
*tot_metric = metric; *tot_metric = metric;
*Nid_cell = Nid2 + (3 * Nid1); *Nid_cell = Nid2 + (3 * n1);
*phase_max = phase; *phase_max = idx;
#ifdef DEBUG_SSS_NR #ifdef DEBUG_SSS_NR
LOG_D(PHY,
LOG_D(PHY,"(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max); "(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",
phase,
n1,
metric,
*tot_metric,
*phase_max);
#endif #endif
} }
} }
// we try progressively rotation between pss and sss
// but pss and sss are in phase at emission
// rotation means doppler variation, or very noisy pss detection
if (*tot_metric >= SSS_METRIC_FLOOR_NR)
break;
} }
//#ifdef DEBUG_SSS_NR if (*tot_metric < SSS_METRIC_FLOOR_NR) {
#define SSS_METRIC_FLOOR_NR (30000)
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
Nid2 = GET_NID2(*Nid_cell);
Nid1 = GET_NID1(*Nid_cell);
LOG_D(PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
}
// #endif
int re = 0;
int im = 0;
if (Nid1 == Nid1_end) {
LOG_D(PHY, LOG_D(PHY,
"Failed to detect SSS after PSS, metric of SSS %d, threshold to consider SSS valid %d, detected PCI: %d\n", "Failed to detect SSS after PSS, metric of SSS %d, threshold to consider SSS valid %d, detected PCI: %d\n",
*tot_metric, *tot_metric,
@@ -503,15 +295,19 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms,
*Nid_cell); *Nid_cell);
return false; return false;
} }
d = (int16_t *)&d_sss[Nid2][Nid1];
for(i = 0; i<LENGTH_SSS_NR; i++) { int Nid1 = GET_NID1(*Nid_cell);
re += d[i] * sss[i].r; LOG_D(PHY, "Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
im += d[i] * sss[i].i; int16_t *d = d_sss[Nid2][Nid1];
c32_t sig_sum = {};
for (int i = 0; i < LENGTH_SSS_NR; i++) {
sig_sum.r += d[i] * sss[i].r;
sig_sum.i += d[i] * sss[i].i;
} }
double ffo_sss = atan2(im,re)/M_PI/4.3; double ffo_sss = atan2(sig_sum.i, sig_sum.r) / M_PI / 4.3;
*freq_offset_sss = (int)(ffo_sss*frame_parms->subcarrier_spacing); *freq_offset_sss = (int)(ffo_sss*frame_parms->subcarrier_spacing);
double ffo_pss = ((double)freq_offset_pss) / frame_parms->subcarrier_spacing; double ffo_pss = (double)freq_offset_pss / frame_parms->subcarrier_spacing;
LOG_D(NR_PHY, LOG_D(NR_PHY,
"SSS detected, PCI: %d, ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz), nid1: %d, nid2: %d\n", "SSS detected, PCI: %d, ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz), nid1: %d, nid2: %d\n",
*Nid_cell, *Nid_cell,
+2
View File
@@ -23,6 +23,8 @@ uint32_t target_dl_bw = 50;
uint32_t target_dl_Nl; uint32_t target_dl_Nl;
uint32_t target_ul_Nl; uint32_t target_ul_Nl;
char *uecap_file; char *uecap_file;
uint32_t dlsch_slot_modval;
uint32_t ulsch_slot_modval;
#include <executables/nr-softmodem.h> #include <executables/nr-softmodem.h>
int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) {return 0;} int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) {return 0;}
-1
View File
@@ -39,7 +39,6 @@
#endif #endif
#endif #endif
#include "common/cmake_defs.h"
#include "defs_nr_common.h" #include "defs_nr_common.h"
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "PHY/defs_nr_sl_UE.h" #include "PHY/defs_nr_sl_UE.h"
+2 -2
View File
@@ -141,14 +141,14 @@ typedef struct {
int restricted_set; int restricted_set;
int numerology_index; int numerology_index;
int nb_rx; int nb_rx;
c16_t rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L];
c16_t (*Xu)[839]; c16_t (*Xu)[839];
time_stats_t *rx_prach; time_stats_t *rx_prach;
c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L];
} prach_item_t; } prach_item_t;
typedef struct { typedef struct {
/// prach commands /// prach commands
prach_item_t list[NUMBER_OF_NR_PRACH_MAX]; prach_item_t *list[NUMBER_OF_NR_PRACH_MAX];
/// mutex for prach_list access /// mutex for prach_list access
pthread_mutex_t prach_list_mutex; pthread_mutex_t prach_list_mutex;
} prach_list_t; } prach_list_t;
+1 -1
View File
@@ -51,7 +51,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac
rach_ind->slot = slot; rach_ind->slot = slot;
rach_ind->number_of_pdus = 0; rach_ind->number_of_pdus = 0;
prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, SEARCH_EXIST); prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, gNB->frame_parms.nb_antennas_rx, SEARCH_EXIST);
if (!prach_id) { if (!prach_id) {
return; return;
} }
+60 -25
View File
@@ -156,7 +156,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n
bitmap); bitmap);
nr_generate_pss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp); nr_generate_pss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp); nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg->cell_config.phy_cell_id.value, fp);
uint16_t slots_per_hf = (fp->slots_per_frame) >> 1; uint16_t slots_per_hf = (fp->slots_per_frame) >> 1;
int n_hf = slot < slots_per_hf ? 0 : 1; int n_hf = slot < slots_per_hf ? 0 : 1;
@@ -880,32 +880,49 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
stop_meas(&gNB->get_srs_signal_stats); stop_meas(&gNB->get_srs_signal_stats);
uint32_t signal_power_avg = 0; uint32_t signal_power_avg = 0;
uint32_t noise_power_avg = 0; c16_t srs_ls_estimated_channel[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS];
int16_t noise_power_per_rb[srs_pdu->bwp_size];
memset(noise_power_per_rb, 0, srs_pdu->bwp_size * sizeof(int16_t));
if (*srs_est >= 0) { if (*srs_est >= 0) {
start_meas(&gNB->srs_channel_estimation_stats); start_meas(&gNB->srs_channel_estimation_stats);
delay_t delay = {0};
for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) {
for (int p_ind = 0; p_ind < N_ap; p_ind++) {
delay_t delay_aux = {0};
nr_srs_ls_channel_estimation(ant_rx_ind,
p_ind,
ofdm_symbol_size,
frame_parms->first_carrier_offset,
N_symb_SRS,
srs_pdu,
nr_srs_info,
nr_srs_info->srs_generated_signal[p_ind],
srs_received_signal[ant_rx_ind],
srs_ls_estimated_channel[ant_rx_ind][p_ind],
&delay_aux);
if (delay_aux.delay_max_val > delay.delay_max_val)
delay = delay_aux;
}
}
for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) { for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) {
uint32_t noise_power = 0;
for (int p_ind = 0; p_ind < N_ap; p_ind++) { for (int p_ind = 0; p_ind < N_ap; p_ind++) {
uint32_t signal_power = 0; uint32_t signal_power = 0;
nr_srs_channel_estimation(ant_rx_ind, nr_srs_channel_interpolation(ant_rx_ind,
p_ind, p_ind,
ofdm_symbol_size, ofdm_symbol_size,
frame_parms->first_carrier_offset, frame_parms->first_carrier_offset,
N_symb_SRS, N_symb_SRS,
srs_pdu, srs_pdu,
nr_srs_info, nr_srs_info,
nr_srs_info->srs_generated_signal[p_ind], srs_ls_estimated_channel[ant_rx_ind][p_ind],
srs_received_signal[ant_rx_ind], delay.est_delay,
srs_received_noise[ant_rx_ind], srs_received_noise[ant_rx_ind],
srs_estimated_channel_freq[ant_rx_ind][p_ind], srs_estimated_channel_freq[ant_rx_ind][p_ind],
srs_estimated_channel_time[ant_rx_ind][p_ind], srs_estimated_channel_time[ant_rx_ind][p_ind],
srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], srs_estimated_channel_time_shifted[ant_rx_ind][p_ind],
&signal_power, &signal_power,
&noise_power, frame_parms->delay_table);
noise_power_per_rb);
signal_power_avg += signal_power; signal_power_avg += signal_power;
@@ -913,7 +930,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
T_INT(gNB->Mod_id), T_INT(gNB->Mod_id),
T_INT(srs_pdu->rnti), T_INT(srs_pdu->rnti),
T_INT(frame_rx), T_INT(frame_rx),
T_INT(slot_rx), T_INT(0),
T_INT(ant_rx_ind), T_INT(ant_rx_ind),
T_INT(p_ind), T_INT(p_ind),
T_BUFFER(srs_estimated_channel_freq[ant_rx_ind][p_ind], N_symb_SRS * ofdm_symbol_size * sizeof(c16_t))); T_BUFFER(srs_estimated_channel_freq[ant_rx_ind][p_ind], N_symb_SRS * ofdm_symbol_size * sizeof(c16_t)));
@@ -922,17 +939,35 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
T_INT(gNB->Mod_id), T_INT(gNB->Mod_id),
T_INT(srs_pdu->rnti), T_INT(srs_pdu->rnti),
T_INT(frame_rx), T_INT(frame_rx),
T_INT(slot_rx), T_INT(0),
T_INT(ant_rx_ind), T_INT(ant_rx_ind),
T_INT(p_ind), T_INT(p_ind),
T_BUFFER(srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], T_BUFFER(srs_estimated_channel_time_shifted[ant_rx_ind][p_ind],
NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size * sizeof(c16_t))); NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size * sizeof(c16_t)));
} }
noise_power_avg += noise_power;
} }
signal_power_avg /= (nb_antennas_rx * N_ap); signal_power_avg /= (nb_antennas_rx * N_ap);
noise_power_avg /= nb_antennas_rx;
signal_power_avg = max(signal_power_avg, 1); signal_power_avg = max(signal_power_avg, 1);
uint32_t noise_power_avg = 0;
int16_t noise_power_per_rb[srs_pdu->bwp_size];
memset(noise_power_per_rb, 0, srs_pdu->bwp_size * sizeof(int16_t));
for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) {
uint32_t noise_power_per_ant = 0;
nr_srs_noise_power_estimation(ofdm_symbol_size,
frame_parms->first_carrier_offset,
N_symb_SRS,
srs_pdu,
nr_srs_info,
signal_power_avg,
srs_received_noise[ant_rx_ind],
&noise_power_per_ant,
noise_power_per_rb);
noise_power_avg += noise_power_per_ant;
}
noise_power_avg /= nb_antennas_rx;
gNB->srs->snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1)); gNB->srs->snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1));
const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);
+26 -19
View File
@@ -563,7 +563,10 @@ int main(int argc, char **argv){
phy_init_nr_gNB(gNB); phy_init_nr_gNB(gNB);
nr_phy_init_RU(ru); nr_phy_init_RU(ru);
nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_list.list[0].pdu;
prach_item_t *prach_data = calloc(1,sizeof(prach_item_t));
gNB->prach_list.list[0] = prach_data;
nfapi_nr_prach_pdu_t *prach_pdu = &prach_data->pdu;
prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig);
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs));
prach_pdu->prach_format = prach_format; prach_pdu->prach_format = prach_format;
@@ -765,26 +768,30 @@ int main(int argc, char **argv){
nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra];
prach_pdu->num_prach_ocas=1; prach_pdu->num_prach_ocas=1;
prach_item_t in = {.frame = frame, prach_item_t *in = malloc(sizeof(prach_item_t)
.slot = slot, + sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value
.pdu = *prach_pdu, * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L);
.rootSequenceIndex = occ->prach_root_sequence_index.value, *in = (prach_item_t){.frame = frame,
.numrootSequenceIndex = occ->num_root_sequences.value, .slot = slot,
.msg1_frequencystart = occ->k1.value, .pdu = *prach_pdu,
.mu = cfg->prach_sub_c_spacing.value, .rootSequenceIndex = occ->prach_root_sequence_index.value,
.prach_sequence_length = cfg->prach_sequence_length.value, .numrootSequenceIndex = occ->num_root_sequences.value,
.restricted_set = cfg->restricted_set_config.value, .msg1_frequencystart = occ->k1.value,
.numerology_index = gNB->frame_parms.numerology_index, .mu = cfg->prach_sub_c_spacing.value,
.nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value, .prach_sequence_length = cfg->prach_sequence_length.value,
.Xu = gNB->X_u, .restricted_set = cfg->restricted_set_config.value,
.rx_prach = &gNB->rx_prach}; .numerology_index = gNB->frame_parms.numerology_index,
rx_nr_prach_ru(&in, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); .nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value,
.Xu = gNB->X_u,
.rx_prach = &gNB->rx_prach,
.prach_buf = (void *)(in + 1)};
rx_nr_prach_ru(in, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset);
if (n_frames == 1) if (n_frames == 1)
LOG_I(PHY, LOG_I(PHY,
"ncs %d,num_seq %d\n", "ncs %d,num_seq %d\n",
prach_pdu->num_cs, prach_pdu->num_cs,
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value);
rx_prach_out_t out = rx_nr_prach(&in, prachOccasion); rx_prach_out_t out = rx_nr_prach(in, prachOccasion);
// printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", out.max_preamble_energy, out.max_preamble, // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", out.max_preamble_energy, out.max_preamble,
// preamble_tx); // preamble_tx);
@@ -807,13 +814,13 @@ int main(int argc, char **argv){
LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1); LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1);
LOG_M("ru_prach_rxsigF0.m", "rxsF0", in.rxsigF[0][0], N_ZC, 1, 1); LOG_M("ru_prach_rxsigF0.m", "rxsF0", in->prach_buf[0][0], N_ZC, 1, 1);
LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1); LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1);
LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1); LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1);
#endif #endif
} }
free(in);
} }
printf("SNR %f dB, UE Speed %f km/h: errors %u/%d (delay %f)\n", SNR, ue_speed, prach_errors, n_frames, delay_avg/(double)(n_frames-prach_errors)); printf("SNR %f dB, UE Speed %f km/h: errors %u/%d (delay %f)\n", SNR, ue_speed, prach_errors, n_frames, delay_avg/(double)(n_frames-prach_errors));
if (input_fd) if (input_fd)
break; break;
@@ -833,7 +840,7 @@ int main(int argc, char **argv){
nr_phy_free_RU(ru); nr_phy_free_RU(ru);
free(RC.ru[0]); free(RC.ru[0]);
free(RC.ru); free(RC.ru);
free(prach_data);
phy_free_nr_gNB(gNB); phy_free_nr_gNB(gNB);
// allocated in set_tdd_config_nr() // allocated in set_tdd_config_nr()
int nb_slots_to_set = (1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; int nb_slots_to_set = (1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
+10
View File
@@ -1255,6 +1255,11 @@ static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray)
if (GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0) if (GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0)
return NULL; return NULL;
if (!IS_SA_MODE(get_softmodem_params())) {
LOG_E(GNB_APP, "DU SIBs only supported in SA mode, we'll skip them!\n");
return NULL;
}
seq_arr_t *du_SIBs = malloc(sizeof(seq_arr_t)); seq_arr_t *du_SIBs = malloc(sizeof(seq_arr_t));
seq_arr_init(du_SIBs, sizeof(nr_SIBs_t)); seq_arr_init(du_SIBs, sizeof(nr_SIBs_t));
for (int i = 0; i < GNBparamarray[GNB_DU_SIBS_IDX].numelt; i++) { for (int i = 0; i < GNBparamarray[GNB_DU_SIBS_IDX].numelt; i++) {
@@ -1795,6 +1800,11 @@ static seq_arr_t *fill_cu_sibs(paramdef_t *GNBparamarray)
if (GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0) if (GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0)
return NULL; return NULL;
if (!IS_SA_MODE(get_softmodem_params())) {
LOG_E(GNB_APP, "CU SIBs only supported in SA mode, we'll skip them!\n");
return NULL;
}
seq_arr_t *SIBs = malloc(sizeof(seq_arr_t)); seq_arr_t *SIBs = malloc(sizeof(seq_arr_t));
seq_arr_init(SIBs, sizeof(nr_SIBs_t)); seq_arr_init(SIBs, sizeof(nr_SIBs_t));
for (int i = 0; i < GNBparamarray[GNB_CU_SIBS_IDX].numelt; i++) { for (int i = 0; i < GNBparamarray[GNB_CU_SIBS_IDX].numelt; i++) {
@@ -42,17 +42,24 @@
/* This function checks whether the given Dl/UL slot is set /* This function checks whether the given Dl/UL slot is set
in the input bitmap (per period), which is a mask indicating in which in the input bitmap (per period), which is a mask indicating in which
slot to transmit (among those available in the TDD configuration) */ slot to transmit (among those available in the TDD configuration)
static bool is_xlsch_in_slot(uint64_t bitmap, slot_t slot) This function also checks if Dmod/Umod option is set, then the slot will be
scheduled in case slot % val == 0.
Use Dmod/Umod in case of FDD FR2. */
static bool is_xlsch_in_slot(uint64_t bitmap, uint32_t modval, slot_t slot)
{ {
AssertFatal(slot < 64, "Unable to handle periods with length larger than 64 slots in phy-test mode\n"); AssertFatal(modval || slot < 64, "Slot >= 64 cannot be scheduled using options 'D/U', use 'Dmod/Umod' option\n");
return (bitmap >> slot) & 0x01;
bool val1 = (bitmap >> slot) & 0x01;
bool val2 = (modval && (slot % modval == 0));
return (val1 || val2);
} }
uint32_t target_dl_mcs = 9; uint32_t target_dl_mcs = 9;
uint32_t target_dl_Nl = 1; uint32_t target_dl_Nl = 1;
uint32_t target_dl_bw = 50; uint32_t target_dl_bw = 50;
uint64_t dlsch_slot_bitmap = (1<<1); uint64_t dlsch_slot_bitmap = (1<<1);
uint32_t dlsch_slot_modval = 0;
/* schedules whole bandwidth for first user, all the time */ /* schedules whole bandwidth for first user, all the time */
void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch)
@@ -62,7 +69,7 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch)
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
int slot_period = slot % mac->frame_structure.numb_slots_period; int slot_period = slot % mac->frame_structure.numb_slots_period;
if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period)) if (!is_xlsch_in_slot(dlsch_slot_bitmap, dlsch_slot_modval, slot_period))
return; return;
NR_UE_info_t *UE = mac->UE_info.connected_ue_list[0]; NR_UE_info_t *UE = mac->UE_info.connected_ue_list[0];
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
@@ -218,6 +225,7 @@ uint32_t target_ul_mcs = 9;
uint32_t target_ul_bw = 50; uint32_t target_ul_bw = 50;
uint32_t target_ul_Nl = 1; uint32_t target_ul_Nl = 1;
uint64_t ulsch_slot_bitmap = (1 << 8); uint64_t ulsch_slot_bitmap = (1 << 8);
uint32_t ulsch_slot_modval = 0;
void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch) void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch)
{ {
int frame = pp_pusch->frame; int frame = pp_pusch->frame;
@@ -267,7 +275,7 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p
* limitations). Note that if K2 or the TDD configuration is changed, below * limitations). Note that if K2 or the TDD configuration is changed, below
* conditions might exclude each other and never be true */ * conditions might exclude each other and never be true */
int slot_period = sched_slot % nr_mac->frame_structure.numb_slots_period; int slot_period = sched_slot % nr_mac->frame_structure.numb_slots_period;
if (!is_xlsch_in_slot(ulsch_slot_bitmap, slot_period)) if (!is_xlsch_in_slot(ulsch_slot_bitmap, ulsch_slot_modval, slot_period))
return; return;
// TODO implement beam procedures for phy-test mode // TODO implement beam procedures for phy-test mode
+24
View File
@@ -486,6 +486,30 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf
if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG)
xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) sib1); xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) sib1);
LOG_A(NR_RRC, "SIB1 decoded\n"); LOG_A(NR_RRC, "SIB1 decoded\n");
plmn_id_t *plmn_id = malloc_or_fail(sizeof(plmn_id_t));
/* selected_plmn_identity is one-indexed */
AssertFatal(rrc->selected_plmn_identity > 0, "No PLMN selected");
/* only one PLMN info block is currently supported*/
NR_PLMN_Identity_t *plmn = sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[0]
->plmn_IdentityList.list.array[rrc->selected_plmn_identity - 1];
/* Convert MCC */
plmn_id->mcc = (*plmn->mcc->list.array[0]) * 100 + (*plmn->mcc->list.array[1]) * 10 + (*plmn->mcc->list.array[2]);
plmn_id->mnc_digit_length = plmn->mnc.list.count;
/* Convert MNC (2 or 3 digits) */
if (plmn->mnc.list.count == 3) {
plmn_id->mnc = (*plmn->mnc.list.array[0]) * 100 + (*plmn->mnc.list.array[1]) * 10 + (*plmn->mnc.list.array[2]);
} else {
plmn_id->mnc = (*plmn->mnc.list.array[0]) * 10 + (*plmn->mnc.list.array[1]);
}
nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
nas->sn_id = plmn_id;
nr_timer_start(&SI_info->sib1_timer); nr_timer_start(&SI_info->sib1_timer);
SI_info->sib1_validity = true; SI_info->sib1_validity = true;
if (rrc->nrRrcState == RRC_STATE_IDLE_NR) { if (rrc->nrRrcState == RRC_STATE_IDLE_NR) {
+11 -24
View File
@@ -101,26 +101,13 @@ static fgmm_msg_header_t set_mm_header(fgs_nas_msg_t type, Security_header_t sec
return mm_header; return mm_header;
} }
static void servingNetworkName(uint8_t *msg, char *imsiStr, int mnc_size) static void servingNetworkName(uint8_t *msg, plmn_id_t *plmn_id)
{ {
// SNN-network-identifier in TS 24.501 // SNN-network-identifier in TS 24.501
// TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning. // TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning.
// MNC
char mnc[4];
if (mnc_size == 2) {
snprintf(mnc, sizeof(mnc), "0%c%c", imsiStr[3], imsiStr[4]);
} else {
snprintf(mnc, sizeof(mnc), "%c%c%c", imsiStr[3], imsiStr[4], imsiStr[5]);
}
// MCC
char mcc[4];
snprintf(mcc, sizeof(mcc), "%c%c%c", imsiStr[0], imsiStr[1], imsiStr[2]);
int size = 64; int size = 64;
snprintf((char *)msg, size, "5G:mnc%3s.mcc%3s.3gppnetwork.org", mnc, mcc); snprintf((char *)msg, size, "5G:mnc%03d.mcc%03d.3gppnetwork.org", plmn_id->mnc, plmn_id->mcc);
} }
static const char *print_info(uint8_t id, const text_info_t *array, uint8_t array_size) static const char *print_info(uint8_t id, const text_info_t *array, uint8_t array_size)
@@ -505,11 +492,11 @@ static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc)
return 19; return 19;
} }
void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, uicc_t *uicc) void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, plmn_id_t *plmn_id)
{ {
uint8_t S[100] = {0}; uint8_t S[100] = {0};
S[0] = 0x6B; S[0] = 0x6B;
servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); servingNetworkName(S + 1, plmn_id);
int netNamesize = strlen((char *)S + 1); int netNamesize = strlen((char *)S + 1);
S[1 + netNamesize] = (netNamesize & 0xff00) >> 8; S[1 + netNamesize] = (netNamesize & 0xff00) >> 8;
S[2 + netNamesize] = (netNamesize & 0x00ff); S[2 + netNamesize] = (netNamesize & 0x00ff);
@@ -548,7 +535,7 @@ void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16
memcpy(output, out + 16, 16); memcpy(output, out + 16, 16);
} }
void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], uicc_t *uicc) void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], plmn_id_t *plmn_id)
{ {
uint8_t S[100] = {0}; uint8_t S[100] = {0};
uint8_t key[32] = {0}; uint8_t key[32] = {0};
@@ -556,7 +543,7 @@ void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[
memcpy(&key[0], ck, 16); memcpy(&key[0], ck, 16);
memcpy(&key[16], ik, 16); // KEY memcpy(&key[16], ik, 16); // KEY
S[0] = 0x6A; S[0] = 0x6A;
servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); servingNetworkName(S + 1, plmn_id);
int netNamesize = strlen((char *)S + 1); int netNamesize = strlen((char *)S + 1);
S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8);
S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff);
@@ -570,11 +557,11 @@ void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[
kdf(key, data, 32, kausf); kdf(key, data, 32, kausf);
} }
void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], uicc_t *uicc) void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], plmn_id_t *plmn_id)
{ {
uint8_t S[100] = {0}; uint8_t S[100] = {0};
S[0] = 0x6C; // FC S[0] = 0x6C; // FC
servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); servingNetworkName(S + 1, plmn_id);
int netNamesize = strlen((char *)S + 1); int netNamesize = strlen((char *)S + 1);
S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8);
S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff);
@@ -641,14 +628,14 @@ static void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas)
uint8_t ck[16], ik[16]; uint8_t ck[16], ik[16];
f2345(nas->uicc->key, rand, resTemp, ck, ik, ak, nas->uicc->opc); f2345(nas->uicc->key, rand, resTemp, ck, ik, ak, nas->uicc->opc);
transferRES(ck, ik, resTemp, rand, output, nas->uicc); transferRES(ck, ik, resTemp, rand, output, nas->sn_id);
for (int index = 0; index < 6; index++) { for (int index = 0; index < 6; index++) {
sqn[index] = buf[26 + index]; sqn[index] = buf[26 + index];
} }
derive_kausf(ck, ik, sqn, kausf, nas->uicc); derive_kausf(ck, ik, sqn, kausf, nas->sn_id);
derive_kseaf(kausf, kseaf, nas->uicc); derive_kseaf(kausf, kseaf, nas->sn_id);
derive_kamf(kseaf, kamf, 0x0000, nas->uicc); derive_kamf(kseaf, kamf, 0x0000, nas->uicc);
derive_kgnb(kamf, nas->security.nas_count_ul, kgnb); derive_kgnb(kamf, nas->security.nas_count_ul, kgnb);
+1
View File
@@ -102,6 +102,7 @@ typedef struct {
int t3446; int t3446;
/* NAS Key Set Identifier associated to the security context */ /* NAS Key Set Identifier associated to the security context */
uint8_t *ksi; uint8_t *ksi;
plmn_id_t *sn_id;
} nr_ue_nas_t; } nr_ue_nas_t;
nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); nr_ue_nas_t *get_ue_nas_info(module_id_t module_id);
+2 -2
View File
@@ -16,10 +16,10 @@ add_library(oran_fhlib_5g MODULE
oran-init.c oran-init.c
) )
set(F_VERSION 6.1.8) set(F_VERSION 6.1.9)
find_package(xran REQUIRED) find_package(xran REQUIRED)
if(xran_VERSION MATCHES "5.*") if(xran_VERSION VERSION_GREATER_EQUAL 5 AND xran_VERSION VERSION_LESS 6)
message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to F version ${F_VERSION}") message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to F version ${F_VERSION}")
elseif(xran_VERSION VERSION_EQUAL F_VERSION) elseif(xran_VERSION VERSION_EQUAL F_VERSION)
target_compile_definitions(oran_fhlib_5g PRIVATE F_RELEASE) target_compile_definitions(oran_fhlib_5g PRIVATE F_RELEASE)
+29 -48
View File
@@ -178,55 +178,55 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot)
struct xran_fh_config *fh_cfg = get_xran_fh_config(0); struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
nr_prach_info_t prach_info = get_prach_info(0); nr_prach_info_t prach_info = get_prach_info(0);
uint16_t N_ZC, num_prbu;
if ((prach_info.format & 0xff) < 4) {
N_ZC = 839;
num_prbu = 70;
prach_info.N_dur = 1;
} else {
N_ZC = 139;
num_prbu = 12;
}
int prach_start_sym = prach_info.start_symbol; int prach_start_sym = prach_info.start_symbol;
int prach_end_sym = prach_info.N_dur + prach_start_sym; int prach_end_sym = prach_info.N_dur + prach_start_sym;
struct xran_ru_config *ru_conf = &fh_cfg->ru_conf; struct xran_ru_config *ru_conf = &fh_cfg->ru_conf;
int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology;
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology;
int tti = slots_per_frame * (frame) + (slot); int tti = slots_per_frame * (frame) + (slot);
uint32_t subframe = slot / slots_per_subframe;
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
uint32_t is_prach_frame = (frame % prach_info.x == prach_info.y);
uint32_t is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (slot % slots_per_subframe));
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
/* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */ /* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */
if (is_prach_slot) { if (ru->prach_buf) {
if (!ru->prach_buf) {
LOG_W(HW, "we get rach data from ru, but it is not scheduled %d.%d\n", frame, slot);
return -1;
}
for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) { for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) {
for (int aa = 0; aa < ru->nb_rx; aa++) { for (int aa = 0; aa < ru->nb_rx; aa++) {
int16_t *dst, *src; int16_t *dst, *src;
int idx = 0; int idx = 0;
oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru); oran_buf_list_t *bufs = get_xran_buffers(aa / nb_rx_per_ru);
// hardcoded to use only first prach occasion // hardcoded to use only first prach occasion
dst = (int16_t *)ru->prach_buf[0][aa]; dst = (int16_t *)ru->prach_buf[aa][0];
src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData; src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData;
/* convert Network order to host order */ /* convert Network order to host order */
if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) {
if (sym_idx == prach_start_sym) { if (sym_idx == prach_start_sym) {
for (idx = 0; idx < 139 * 2; idx++) { for (idx = 0; idx < N_ZC * 2; idx++) {
dst[idx] = ((int16_t)ntohs(src[idx + g_kbar])); dst[idx] = ((int16_t)ntohs(src[idx + g_kbar]));
} }
} else { } else {
for (idx = 0; idx < 139 * 2; idx++) { for (idx = 0; idx < N_ZC * 2; idx++) {
dst[idx] += ((int16_t)ntohs(src[idx + g_kbar])); dst[idx] += ((int16_t)ntohs(src[idx + g_kbar]));
} }
} }
} else if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_BLKFLOAT) { } else if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_BLKFLOAT) {
int16_t local_dst[12 * 2 * N_SC_PER_PRB] __attribute__((aligned(64))); int16_t local_dst[num_prbu * 2 * N_SC_PER_PRB] __attribute__((aligned(64)));
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
struct xranlib_decompress_request bfp_decom_req = {}; struct xranlib_decompress_request bfp_decom_req = {};
struct xranlib_decompress_response bfp_decom_rsp = {}; struct xranlib_decompress_response bfp_decom_rsp = {};
int payload_len = (3 * ru_conf->iqWidth_PRACH + 1) * 12; // 12 = closest number of PRBs to 139 REs int payload_len = (3 * ru_conf->iqWidth_PRACH + 1) * num_prbu;
bfp_decom_req.data_in = (int8_t *)src; bfp_decom_req.data_in = (int8_t *)src;
bfp_decom_req.numRBs = 12; // closest number of PRBs to 139 REs bfp_decom_req.numRBs = num_prbu;
bfp_decom_req.len = payload_len; bfp_decom_req.len = payload_len;
bfp_decom_req.compMethod = XRAN_COMPMETHOD_BLKFLOAT; bfp_decom_req.compMethod = XRAN_COMPMETHOD_BLKFLOAT;
bfp_decom_req.iqWidth = ru_conf->iqWidth_PRACH; bfp_decom_req.iqWidth = ru_conf->iqWidth_PRACH;
@@ -235,21 +235,20 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot)
bfp_decom_rsp.len = 0; bfp_decom_rsp.len = 0;
xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp); xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp);
#elif defined(__arm__) || defined(__aarch64__) #elif defined(__arm__) || defined(__aarch64__)
armral_bfp_decompression(ru_conf->iqWidth_PRACH, 12, (int8_t *)src, (int16_t *)local_dst); armral_bfp_decompression(ru_conf->iqWidth_PRACH, num_prbu, (int8_t *)src, (int16_t *)local_dst);
#else #else
AssertFatal(1 == 0, "BFP decompression not supported on this architecture"); AssertFatal(1 == 0, "BFP decompression not supported on this architecture");
#endif #endif
// note: this is hardwired for 139 point PRACH sequence, kbar=2
if (sym_idx == prach_start_sym) if (sym_idx == prach_start_sym)
for (idx = 0; idx < (139 * 2); idx++) for (idx = 0; idx < (N_ZC * 2); idx++)
dst[idx] = local_dst[idx + g_kbar]; dst[idx] = local_dst[idx + g_kbar];
else else
for (idx = 0; idx < (139 * 2); idx++) for (idx = 0; idx < (N_ZC * 2); idx++)
dst[idx] += (local_dst[idx + g_kbar]); dst[idx] += (local_dst[idx + g_kbar]);
} // COMPMETHOD_BLKFLOAT } // COMPMETHOD_BLKFLOAT
} // aa } // aa
} // symb_indx } // symb_indx
} // is_prach_slot } // ru->prach_buf
return (0); return (0);
} }
@@ -543,7 +542,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
// Need to use --continuous-tx so that this routine will be triggered in RX slot. // Need to use --continuous-tx so that this routine will be triggered in RX slot.
for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet.
for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) {
int first = 1; // The first UL symbol
const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf;
// skip processing this slot is TX (no RX in this slot) // skip processing this slot is TX (no RX in this slot)
if (!is_tdd_ul_guard_slot(frame_conf, slot)) { if (!is_tdd_ul_guard_slot(frame_conf, slot)) {
@@ -581,17 +579,10 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
pRbElm->nBeamIndex = 0; pRbElm->nBeamIndex = 0;
} }
} else { } else {
if (first) { // ant_id / no of antenna per beam gives the beam_nb
// ant_id / no of antenna per beam gives the beam_nb int16_t beam_id = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx];
pRbElm->nBeamIndex = if (beam_id != -1)
ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; pRbElm->nBeamIndex = beam_id;
// In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly.
if (pRbElm->nBeamIndex == -1) {
pRbElm->nBeamIndex = 0;
} else {
first = 0;
}
}
} }
} }
} }
@@ -663,13 +654,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
for (uint32_t idxElm = 0; idxElm < pPrbMap->nPrbElm; idxElm++) { for (uint32_t idxElm = 0; idxElm < pPrbMap->nPrbElm; idxElm++) {
struct xran_section_desc *p_sec_desc = NULL; struct xran_section_desc *p_sec_desc = NULL;
struct xran_prb_elm *p_prbMapElm = &pPrbMap->prbMap[idxElm]; struct xran_prb_elm *p_prbMapElm = &pPrbMap->prbMap[idxElm];
if (sym_idx == 0) {
// ant_id / no of antenna per beam gives the beam_nb
p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT];
// In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly.
if (p_prbMapElm->nBeamIndex == -1)
p_prbMapElm->nBeamIndex = 0;
}
// radio-transport fragmentation is not supported in xran F release; // radio-transport fragmentation is not supported in xran F release;
// E-bit = 1 => each ethernet frame is considered as the last fragment; // E-bit = 1 => each ethernet frame is considered as the last fragment;
@@ -700,13 +684,10 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
if (p_prbMapElm->nBeamIndex == -1) if (p_prbMapElm->nBeamIndex == -1)
p_prbMapElm->nBeamIndex = 0; p_prbMapElm->nBeamIndex = 0;
} else { } else {
if (sym_idx == 0) { // ant_id / no of antenna per beam gives the beam_nb
// ant_id / no of antenna per beam gives the beam_nb int16_t beam_id = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx];
p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT]; if ( beam_id != -1)
// In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. p_prbMapElm->nBeamIndex = beam_id;
if (p_prbMapElm->nBeamIndex == -1)
p_prbMapElm->nBeamIndex = 0;
}
} }
dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod);
+6 -14
View File
@@ -432,12 +432,10 @@ void print_fh_config(const struct xran_fh_config *fh_config)
#if defined F_RELEASE #if defined F_RELEASE
printf("\ printf("\
RunSlotPrbMapBySymbolEnable %d\n\ RunSlotPrbMapBySymbolEnable %d\n\
LiteOnIgnoreUPSectionIdEnable %d\n\
dssEnable %d\n\ dssEnable %d\n\
dssPeriod %d\n\ dssPeriod %d\n\
technology[XRAN_MAX_DSS_PERIODICITY] (not filled as DSS disabled)\n", technology[XRAN_MAX_DSS_PERIODICITY] (not filled as DSS disabled)\n",
fh_config->RunSlotPrbMapBySymbolEnable, fh_config->RunSlotPrbMapBySymbolEnable,
fh_config->LiteOnIgnoreUPSectionIdEnable,
fh_config->dssEnable, fh_config->dssEnable,
fh_config->dssPeriod); fh_config->dssPeriod);
#endif #endif
@@ -777,8 +775,7 @@ static bool set_fh_prach_config(void *mplane_api,
const uint32_t max_num_ant, const uint32_t max_num_ant,
const paramdef_t *prachp, const paramdef_t *prachp,
int nprach, int nprach,
struct xran_prach_config *prach_config, struct xran_prach_config *prach_config)
bool liteon_prach_eAxC_offset)
{ {
const split7_config_t *s7cfg = &oai0->split7; const split7_config_t *s7cfg = &oai0->split7;
@@ -814,11 +811,8 @@ static bool set_fh_prach_config(void *mplane_api,
xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api; xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api;
prach_config->eAxC_offset = xran_mplane->prach_offset; prach_config->eAxC_offset = xran_mplane->prach_offset;
#else #else
uint8_t offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr; const paramdef_t *pd = gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET);
if (liteon_prach_eAxC_offset) prach_config->eAxC_offset = pd->paramflags & PARAMFLAG_PARAMSET ? *pd->u8ptr : max_num_ant;
prach_config->eAxC_offset = offset;
else
prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant;
#endif #endif
g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr; g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr;
@@ -964,13 +958,9 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->prachEnable = 1; // enable PRACH fh_config->prachEnable = 1; // enable PRACH
fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B
// For LiteOn E release, no need to take care of prach eAxC_offset. xran lib is hacked to handle it. // For LiteOn E release, no need to take care of prach eAxC_offset. xran lib is hacked to handle it.
bool liteon_prach_eAxC_offset = false;
#if defined F_RELEASE #if defined F_RELEASE
fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B
fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B
fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_RunSlotPrbMapBySymbol)->uptr; // enable RunSlotPrbMapBySymbol
fh_config->LiteOnIgnoreUPSectionIdEnable = *gpd(fhp, nfh, ORAN_CONFIG_LiteOnIgnoreUPSectionId)->uptr; // enable LiteOnIgnoreUPSectionId
liteon_prach_eAxC_offset = fh_config->LiteOnIgnoreUPSectionIdEnable;
#endif #endif
fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU
fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU
@@ -982,7 +972,7 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha
fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100 fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100
if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf, liteon_prach_eAxC_offset)) if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf))
return false; return false;
/* SRS only used if XRAN_CATEGORY_B /* SRS only used if XRAN_CATEGORY_B
Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */ Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */
@@ -1014,6 +1004,8 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->max_sections_per_symbol = 0; // not used in xran fh_config->max_sections_per_symbol = 0; // not used in xran
#if defined F_RELEASE #if defined F_RELEASE
fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_CP_MULTISECTION)->uptr; // enable PRB mapping by symbol with multisection
fh_config->dssEnable = 0; // enable DSS (extension-9) fh_config->dssEnable = 0; // enable DSS (extension-9)
fh_config->dssPeriod = 0; // DSS pattern period for LTE/NR fh_config->dssPeriod = 0; // DSS pattern period for LTE/NR
// fh_config->technology[XRAN_MAX_DSS_PERIODICITY] // technology array represents slot is LTE(0)/NR(1); used only if DSS enabled // fh_config->technology[XRAN_MAX_DSS_PERIODICITY] // technology array represents slot is LTE(0)/NR(1); used only if DSS enabled
+2 -10
View File
@@ -315,16 +315,8 @@ static void oran_allocate_buffers(void *handle,
}; };
#if defined F_RELEASE #if defined F_RELEASE
uint32_t size_of_prb_map; uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu);
if (fh_config->RunSlotPrbMapBySymbolEnable) { uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm);
// For Liteon FR2 with RunSlotPrbMapBySymbolEnable, xran_prb_map will have xran_prb_elm prbMap[14]
size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (XRAN_NUM_OF_SYMBOL_PER_SLOT);
}
else {
// For non-Liteon w/o RunSlotPrbMapBySymbolEnable, xran_prb_map will have xran_prb_elm prbMap[1]
uint32_t numPrbElm = xran_get_num_prb_elm(&dlPm, mtu);
size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm);
}
#endif #endif
// PDSCH // PDSCH
+3 -5
View File
@@ -106,8 +106,7 @@
#define CONFIG_STRING_ORAN_FH "fh_config" #define CONFIG_STRING_ORAN_FH "fh_config"
#define ORAN_CONFIG_RunSlotPrbMapBySymbol "RunSlotPrbMapBySymbol" #define ORAN_CONFIG_CP_MULTISECTION "RunSlotPrbMapBySymbol"
#define ORAN_CONFIG_LiteOnIgnoreUPSectionId "LiteOnIgnoreUPSectionId"
#define ORAN_FH_CONFIG_T1A_CP_DL "T1a_cp_dl" #define ORAN_FH_CONFIG_T1A_CP_DL "T1a_cp_dl"
#define ORAN_FH_CONFIG_T1A_CP_UL "T1a_cp_ul" #define ORAN_FH_CONFIG_T1A_CP_UL "T1a_cp_ul"
#define ORAN_FH_CONFIG_T1A_UP "T1a_up" #define ORAN_FH_CONFIG_T1A_UP "T1a_up"
@@ -117,8 +116,7 @@
// clang-format off // clang-format off
#define ORAN_FH_DESC { \ #define ORAN_FH_DESC { \
{ORAN_CONFIG_RunSlotPrbMapBySymbol, "RunSlotPrbMapBySymbol\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ {ORAN_CONFIG_CP_MULTISECTION, "RunSlotPrbMapBySymbol\n", PARAMFLAG_BOOL, .iptr=NULL, .defintval=0, TYPE_INT32, 0}, \
{ORAN_CONFIG_LiteOnIgnoreUPSectionId, "Liteon Ignore Section Id\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
{ORAN_FH_CONFIG_T1A_CP_DL, "T1a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_CP_DL, "T1a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \
{ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \
{ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \
@@ -145,7 +143,7 @@
// clang-format off // clang-format off
#define ORAN_PRACH_DESC {\ #define ORAN_PRACH_DESC {\
{ORAN_PRACH_CONFIG_EAXC_OFFSET, "RU's eAxC offset for PRACH\n", PARAMFLAG_MANDATORY, .u8ptr=NULL, .defuintval=0, TYPE_UINT8, 0}, \ {ORAN_PRACH_CONFIG_EAXC_OFFSET, "RU's eAxC offset for PRACH\n", 0, .u8ptr=NULL, .defuintval=0, TYPE_UINT8, 0}, \
{ORAN_PRACH_CONFIG_KBAR, "PRACH guard interval\n", 0, .uptr=NULL, .defuintval=4, TYPE_UINT, 0}, \ {ORAN_PRACH_CONFIG_KBAR, "PRACH guard interval\n", 0, .uptr=NULL, .defuintval=4, TYPE_UINT, 0}, \
} }
// clang-format on // clang-format on
+17 -2
View File
@@ -213,16 +213,31 @@ int trx_oran_ctlrecv(openair0_device_t *device, void *msg, ssize_t msg_len)
void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
{ {
prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, SEARCH_EXIST);
ru_info_t ru_info = { ru_info_t ru_info = {
.nb_rx = ru->nb_rx * ru->num_beams_period, .nb_rx = ru->nb_rx * ru->num_beams_period,
.nb_tx = ru->nb_tx * ru->num_beams_period, .nb_tx = ru->nb_tx * ru->num_beams_period,
.rxdataF = ru->common.rxdataF, .rxdataF = ru->common.rxdataF,
.beam_id = ru->common.beam_id, .beam_id = ru->common.beam_id,
.num_beams_period = ru->num_beams_period, .num_beams_period = ru->num_beams_period,
.prach_buf = prach_id ? prach_id->rxsigF : NULL, .prach_buf = NULL,
}; };
prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, ru->nr_frame_parms->nb_antennas_rx, SEARCH_EXIST);
if (prach_id) {
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology;
uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
nr_prach_info_t prach_info = get_prach_info(0);
bool is_prach_frame = (*frame % prach_info.x == prach_info.y);
bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (prach_id->slot % slots_per_subframe)); // `prach_id->slot` = slot in which PRACH is scheduled
if (is_prach_slot) {
ru_info.prach_buf = prach_id->prach_buf;
} else {
LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, prach_id->slot);
}
}
RU_proc_t *proc = &ru->proc; RU_proc_t *proc = &ru->proc;
int f, sl; int f, sl;
LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]); LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]);
+2 -2
View File
@@ -27,10 +27,10 @@
#include <pthread.h> #include <pthread.h>
#include <stdint.h> #include <stdint.h>
#include "common/cmake_defs.h"
#include "xran_fh_o_du.h" #include "xran_fh_o_du.h"
#include "openair1/PHY/impl_defs_nr.h" #include "openair1/PHY/impl_defs_nr.h"
#include "openair1/PHY/TOOLS/tools_defs.h" #include "openair1/PHY/TOOLS/tools_defs.h"
#include "openair1/PHY/defs_common.h"
/* /*
* Structure added to bear the information needed from OAI RU * Structure added to bear the information needed from OAI RU
*/ */
@@ -52,7 +52,7 @@ typedef struct ru_info_s {
int num_beams_period; int num_beams_period;
// Needed for Prach // Needed for Prach
c16_t (*prach_buf)[NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L]; c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L];
} ru_info_t; } ru_info_t;
/** @brief Reads RX data (PRACH/PUSCH) of next slot. /** @brief Reads RX data (PRACH/PUSCH) of next slot.
+1 -1
View File
@@ -1019,7 +1019,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t,
signal_energy(static_cast<int32_t *>(samplesVoid[0][0]), nsamps)); signal_energy(static_cast<int32_t *>(samplesVoid[0][0]), nsamps));
/* trace only first antenna */ /* trace only first antenna */
T(T_USRP_TX_ANT0, T_INT(timestamp), T_BUFFER(samplesVoid[0], (int)sampleToByte(nsamps, 1))); T(T_USRP_TX_ANT0, T_INT(timestamp), T_BUFFER(samplesVoid[0][0], (int)sampleToByte(nsamps, 1)));
return nsamps; return nsamps;
} }
+9 -1
View File
@@ -8,7 +8,8 @@ interface.
The `vrtsim` architecture follows a server-client model: The `vrtsim` architecture follows a server-client model:
- **Server (gNB)**: On startup, the server writes a file, default location is - **Server (gNB)**: On startup, the server writes connection information to a
file as provided in `--vrtsim.descriptor`, default location is
`/tmp/vrtsim_connection`. This file contains information required by the client `/tmp/vrtsim_connection`. This file contains information required by the client
to establish communication. to establish communication.
- **Client (UE)**: The client reads this file from, verifies its contents, and uses - **Client (UE)**: The client reads this file from, verifies its contents, and uses
@@ -31,6 +32,13 @@ Additionally on gNB use `vrtsim.role server` and optionally
`vrtsim.timescale <timescale>` to set the timescale. Timescale 1.0 `vrtsim.timescale <timescale>` to set the timescale. Timescale 1.0
is the default and means realtime. is the default and means realtime.
To use `vrtsim` in containers, you have to enable inter-process communication,
and mount the directory of the connection information in a shared volume
between server and clients. For instance, in docker and default
`vrtsim.connection_descriptor`, set `ipc: host` and share the server's and
client's `/tmp` directory through a volume. For an example, refer to
[this docker-compose file](../../ci-scripts/yaml_files/5g_vrtsim_cirdb/docker-compose.yaml).
Channel modelling can be enabled by adding `vrtsim.chanmod 1` to the Channel modelling can be enabled by adding `vrtsim.chanmod 1` to the
command line and should work the same as channel modelling in rfsimulator, command line and should work the same as channel modelling in rfsimulator,
see rfsimulator [documentation](../rfsimulator/README.md) with a slight difference: see rfsimulator [documentation](../rfsimulator/README.md) with a slight difference:
+1
View File
@@ -1133,5 +1133,6 @@ __attribute__((__visibility__("default"))) int device_init(openair0_device_t *de
LOG_A(HW, "VRTSIM: Noise power %d sample value\n", noise_power); LOG_A(HW, "VRTSIM: Noise power %d sample value\n", noise_power);
init_noise_device(noise_power); init_noise_device(noise_power);
} }
openair0_cfg->rx_gain[0] = 0;
return 0; return 0;
} }
@@ -146,7 +146,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 5; ssPBCH_BlockPower = 0;
} }
); );
@@ -146,7 +146,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 10; ssPBCH_BlockPower = 0;
} }
); );
@@ -146,7 +146,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 10; ssPBCH_BlockPower = 0;
} }
); );
@@ -146,7 +146,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 10; ssPBCH_BlockPower = 0;
} }
); );
@@ -1,87 +1,94 @@
Active_gNBs = ( "oai-du"); Active_gNBs = ( "inria-gnb");
# Asn1_verbosity, choice in: none, info, annoying # Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none"; Asn1_verbosity = "none";
gNBs = gNBs =
( (
{ {
////////// Identification parameters: ////////// Identification parameters:
gNB_ID = 0xe00; gNB_ID = 0xe99;
gNB_name = "oai-du"; cell_type = "CELL_MACRO_GNB";
gNB_name = "inria-gnb";
// Tracking area code, 0x0000 and 0xfffe are reserved values // Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1; tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ( { sst = 1; }); }); plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ( { sst = 1; }); });
nr_cellid = 1; nr_cellid = 1;
////////// Physical parameters: ////////// Physical parameters:
pdsch_AntennaPorts_XP = 2; pdsch_AntennaPorts_XP = 2;
pusch_AntennaPorts = 4; pusch_AntennaPorts = 2;
pdsch_AntennaPorts_N1 = 2;
maxMIMO_layers = 2; maxMIMO_layers = 2;
do_CSIRS = 1; do_CSIRS = 1;
do_SRS = 0; do_SRS = 0;
force_UL256qam_off = 1; min_rxtxtime = 4;
servingCellConfigCommon = ( servingCellConfigCommon = (
{ {
#spCellConfigCommon #spCellConfigCommon
physCellId = 0; physCellId = 0;
# downlinkConfigCommon # downlinkConfigCommon
#frequencyInfoDL #frequencyInfoDL
# this is 3300.24 + 134*12*30e3 = 3348.48 MHz (5G NR GSCN: 7741) # center frequency = 28701.12 MHz
absoluteFrequencySSB = 649920; #JF maybe we should adjust a bit # selected SSB frequency = 28691.04 MHz
dl_frequencyBand = 78; absoluteFrequencySSB = 2090683;
# this is 3300.24 MHz dl_frequencyBand = 257;
dl_absoluteFrequencyPointA = 646724; # frequency point A = 28653.6 MHz
dl_absoluteFrequencyPointA = 2090059;
#scs-SpecificCarrierList #scs-SpecificCarrierList
dl_offstToCarrier = 0; dl_offstToCarrier = 0;
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1; dl_subcarrierSpacing = 3;
dl_carrierBandwidth = 273; dl_carrierBandwidth = 66;
#initialDownlinkBWP #initialDownlinkBWP
#genericParameters #genericParameters
# this is RBstart=0,L=162 (275*(275-L+1))+(274-RBstart)) initialDLBWPlocationAndBandwidth = 17875;
initialDLBWPlocationAndBandwidth = 1099;
#
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1; initialDLBWPsubcarrierSpacing = 3;
#pdcch-ConfigCommon #pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 12; initialDLBWPcontrolResourceSetZero = 2;
initialDLBWPsearchSpaceZero = 0; initialDLBWPsearchSpaceZero = 0;
#uplinkConfigCommon #uplinkConfigCommon
#frequencyInfoUL #frequencyInfoUL
ul_frequencyBand = 78; ul_frequencyBand = 257;
#scs-SpecificCarrierList #scs-SpecificCarrierList
ul_offstToCarrier = 0; ul_offstToCarrier = 0;
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 1; ul_subcarrierSpacing = 3;
ul_carrierBandwidth = 273; ul_carrierBandwidth = 66;
pMax = 20; pMax = 20;
#initialUplinkBWP #initialUplinkBWP
#genericParameters #genericParameters
initialULBWPlocationAndBandwidth = 1099; initialULBWPlocationAndBandwidth = 17875;
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1; initialULBWPsubcarrierSpacing = 3;
#rach-ConfigCommon #rach-ConfigCommon
#rach-ConfigGeneric #rach-ConfigGeneric
prach_ConfigurationIndex = 148; # JF check this and other PRACH related params prach_ConfigurationIndex = 135;
#prach_msg1_FDM #prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight #0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0; prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0; prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 12; zeroCorrelationZoneConfig = 15;
preambleReceivedTargetPower = -96; preambleReceivedTargetPower = -118;
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) #preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
preambleTransMax = 6; preambleTransMax = 8;
#powerRampingStep #powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6 # 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 1; powerRampingStep = 2;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
#one (0..15) 4,8,12,16,...60,64 #one (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
#ra_ContentionResolutionTimer #ra_ContentionResolutionTimer
@@ -94,12 +101,15 @@ gNBs =
prach_RootSequenceIndex = 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 # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
# #
msg1_SubcarrierSpacing = 1, msg1_SubcarrierSpacing = 3,
# restrictedSetConfig # restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B # 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0, restrictedSetConfig = 0,
msg3_DeltaPreamble = 1;
# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB
msg3_DeltaPreamble = 0;
p0_NominalWithGrant = -90; p0_NominalWithGrant = -90;
# pucch-ConfigCommon setup : # pucch-ConfigCommon setup :
# pucchGroupHopping # pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping # 0 = neither, 1= group hopping, 2=sequence hopping
@@ -108,30 +118,38 @@ gNBs =
p0_nominal = -90; p0_nominal = -90;
ssb_PositionsInBurst_Bitmap = 1; ssb_PositionsInBurst_Bitmap = 1;
# ssb_periodicityServingCell # ssb_periodicityServingCell
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
ssb_periodicityServingCell = 2; ssb_periodicityServingCell = 1;
# dmrs_TypeA_position # dmrs_TypeA_position
# 0 = pos2, 1 = pos3 # 0 = pos2, 1 = pos3
dmrs_TypeA_Position = 0; dmrs_TypeA_Position = 0;
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
subcarrierSpacing = 1; subcarrierSpacing = 3;
#tdd-UL-DL-ConfigurationCommon #tdd-UL-DL-ConfigurationCommon
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
referenceSubcarrierSpacing = 1; referenceSubcarrierSpacing = 3;
# pattern1 # pattern1
# dl_UL_TransmissionPeriodicity # dl_UL_TransmissionPeriodicity
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
dl_UL_TransmissionPeriodicity = 5; #6; dl_UL_TransmissionPeriodicity = 3;
nrofDownlinkSlots = 3; #7; nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6; nrofDownlinkSymbols = 6;
nrofUplinkSlots = 1; #2; nrofUplinkSlots = 2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -10;
ssPBCH_BlockPower = 0;
} }
); );
# ------- SCTP definitions # ------- SCTP definitions
SCTP : SCTP :
{ {
@@ -140,60 +158,71 @@ gNBs =
SCTP_OUTSTREAMS = 2; SCTP_OUTSTREAMS = 2;
}; };
////////// AMF parameters:
amf_ip_address = ({ ipv4 = "172.21.6.103"; }); ////////// AMF parameters:
amf_ip_address = ({ ipv4 = "172.21.6.4"; });
NETWORK_INTERFACES : NETWORK_INTERFACES :
{ {
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.18.20"; GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.18.20"; GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51";
GNB_PORT_FOR_S1U = 2152; # Spec 2152 GNB_PORT_FOR_S1U = 2152; # Spec 2152
}; };
} }
); );
MACRLCs = ( MACRLCs = (
{ {
num_cc = 1; num_cc = 1;
tr_s_preference = "local_L1"; tr_s_preference = "local_L1";
tr_n_preference = "local_RRC"; tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 220; pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 220; pucch_TargetSNRx10 = 200;
ul_bler_target_upper=.35; pusch_FailureThres = 1000;
ul_bler_target_lower=.15; #ul_bler_target_upper =.02;
pusch_FailureThres = 100; #ul_bler_target_lower =.01;
ul_max_mcs = 28; #dl_bler_target_upper =.15;
#dl_bler_target_lower =.05
set_analog_beamforming = "lophy";
beam_duration = 1;
beams_per_period = 1;
beam_weights = [1];
} }
); );
L1s = ( L1s = (
{ {
num_cc = 1; num_cc = 1;
tr_n_preference = "local_mac"; tr_n_preference = "local_mac";
prach_dtx_threshold = 130; prach_dtx_threshold = 250;
pucch0_dtx_threshold = 80; pucch0_dtx_threshold = 100;
pusch_dtx_threshold = 10; pusch_dtx_threshold = -200;
max_ldpc_iterations = 10; max_ldpc_iterations = 10;
tx_amp_backoff_dB = 12; #9; needs to match O-RU configuration # JF important to check tx_amp_backoff_dB = 18;
L1_rx_thread_core = 3; L1_rx_thread_core = 10;
L1_tx_thread_core = 4; # relevant after merge of l1_tx_thread L1_tx_thread_core = 11;
phase_compensation = 0; # needs to match O-RU configuration # JF to be tested phase_compensation = 1;
} }
); );
RUs = ( RUs = (
{ {
local_rf = "no"; local_rf = "no";
nb_tx = 4; nb_tx = 2;
nb_rx = 4; nb_rx = 2;
att_tx = 0 att_tx = 0
att_rx = 0; att_rx = 0;
bands = [78]; bands = [257];
max_pdschReferenceSignalPower = -27; nr_scs_for_raster = 3;
max_rxgain = 75; max_pdschReferenceSignalPower = -40;
sf_extension = 0; max_rxgain = 60;
#sf_extension = 0;
eNB_instances = [0]; eNB_instances = [0];
ru_thread_core = 6; ru_thread_core = 9;
sl_ahead = 10; #5; sl_ahead = 10;
tr_preference = "raw_if4p5"; # important: activate FHI7.2 tr_preference = "raw_if4p5";
do_precoding = 0; # needs to match O-RU configuration do_precoding = 0;
} }
); );
@@ -216,34 +245,37 @@ security = {
log_config : log_config :
{ {
global_log_level ="info"; global_log_level = "info";
hw_log_level ="info"; hw_log_level = "info";
phy_log_level ="info"; phy_log_level = "info";
mac_log_level ="info"; mac_log_level = "info";
rlc_log_level ="info"; rlc_log_level = "info";
pdcp_log_level ="info"; pdcp_log_level = "info";
rrc_log_level ="info"; rrc_log_level = "info";
ngap_log_level ="info"; ngap_log_level = "info";
f1ap_log_level ="info"; f1ap_log_level = "info";
}; };
fhi_72 = { fhi_72 = {
dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1"); dpdk_devices = ("0000:c1:11.0", "0000:c1:11.1"); # one VF can be used as well
dpdk_iova_mode = "VA"; system_core = 6;
system_core = 0; io_core = 7;
io_core = 1; worker_cores = (8);
worker_cores = (2); ru_addr = ("E8:C7:4F:1E:C7:5B", "E8:C7:4F:1E:C7:5B");
ru_addr = ("00:E0:0C:00:AE:06", "00:E0:0C:00:AE:06"); mtu = 9216;
mtu = 9000;
fh_config = ({ fh_config = ({
T1a_cp_dl = (285, 470); RunSlotPrbMapBySymbol = 1;
T1a_cp_ul = (285, 429); T1a_cp_dl = (110, 111);
T1a_up = (125, 350); T1a_cp_ul = (69, 70);
Ta4 = (110, 180); T1a_up = (30, 64);
Ta4 = (30, 64);
ru_config = { ru_config = {
iq_width = 9; iq_width = 8;
iq_width_prach = 9; iq_width_prach = 8;
};
prach_config = {
eAxC_offset = 0;
kbar = 0;
}; };
}); });
}; };
@@ -144,7 +144,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -7;
} }
); );
@@ -11,7 +11,7 @@ gNBs =
// Tracking area code, 0x0000 and 0xfffe are reserved values // Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1; tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ( { sst = 1; }); }); plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ( { sst = 1; }); });
nr_cellid = 1; nr_cellid = 1;
@@ -20,10 +20,9 @@ gNBs =
pdsch_AntennaPorts_XP = 2; pdsch_AntennaPorts_XP = 2;
pdsch_AntennaPorts_N1 = 1; pdsch_AntennaPorts_N1 = 1;
maxMIMO_layers = 2; maxMIMO_layers = 2;
pusch_AntennaPorts = 4; pusch_AntennaPorts = 2;
do_CSIRS = 1; do_CSIRS = 1;
do_SRS = 0; do_SRS = 0;
# force_UL256qam_off = 1;
servingCellConfigCommon = ( servingCellConfigCommon = (
{ {
@@ -33,12 +32,12 @@ gNBs =
# n_TimingAdvanceOffset = 0; # n_TimingAdvanceOffset = 0;
# downlinkConfigCommon # downlinkConfigCommon
#frequencyInfoDL #frequencyInfoDL
# center frequency = 3350.01 MHz # center frequency = 3950.4 MHz
# selected SSB frequency = 3349.92 MHz # selected SSB frequency = 3950.4 MHz
absoluteFrequencySSB = 623328; absoluteFrequencySSB = 663360;
dl_frequencyBand = 78; dl_frequencyBand = 77;
# frequency point A = 3300.87 MHz # frequency point A = 3901.26 MHz
dl_absoluteFrequencyPointA = 620052; dl_absoluteFrequencyPointA = 660084;
#scs-SpecificCarrierList #scs-SpecificCarrierList
dl_offstToCarrier = 0; dl_offstToCarrier = 0;
# subcarrierSpacing # subcarrierSpacing
@@ -58,7 +57,7 @@ gNBs =
#uplinkConfigCommon #uplinkConfigCommon
#frequencyInfoUL #frequencyInfoUL
ul_frequencyBand = 78; ul_frequencyBand = 77;
#scs-SpecificCarrierList #scs-SpecificCarrierList
ul_offstToCarrier = 0; ul_offstToCarrier = 0;
# subcarrierSpacing # subcarrierSpacing
@@ -74,7 +73,7 @@ gNBs =
initialULBWPsubcarrierSpacing = 1; initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon #rach-ConfigCommon
#rach-ConfigGeneric #rach-ConfigGeneric
prach_ConfigurationIndex = 152; prach_ConfigurationIndex = 7;
#prach_msg1_FDM #prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight #0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0; prach_msg1_FDM = 0;
@@ -85,10 +84,10 @@ gNBs =
preambleTransMax = 8; preambleTransMax = 8;
#powerRampingStep #powerRampingStep
# 0=dB0,1=dB2,2=dB4,3=dB6 # 0=dB0,1=dB2,2=dB4,3=dB6
powerRampingStep = 1; powerRampingStep = 3;
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
#one (0..15) 4,8,12,16,...60,64 #one (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
#ra_ContentionResolutionTimer #ra_ContentionResolutionTimer
@@ -97,11 +96,11 @@ gNBs =
rsrp_ThresholdSSB = 19; rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR #prach-RootSequenceIndex_PR
#1 = 839, 2 = 139 #1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2; prach_RootSequenceIndex_PR = 1;
prach_RootSequenceIndex = 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 # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
# #
msg1_SubcarrierSpacing = 1, # msg1_SubcarrierSpacing = 1,
# restrictedSetConfig # restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B # 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0, restrictedSetConfig = 0,
@@ -145,9 +144,8 @@ gNBs =
nrofUplinkSlots = 2; nrofUplinkSlots = 2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -15; ssPBCH_BlockPower = -11;
} }
); );
@@ -161,12 +159,12 @@ gNBs =
////////// AMF parameters: ////////// AMF parameters:
amf_ip_address = ({ ipv4 = "172.21.6.103"; }); amf_ip_address = ({ ipv4 = "172.21.6.5";});
NETWORK_INTERFACES : NETWORK_INTERFACES :
{ {
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.18.20"; GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.130";
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.18.20"; GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.130";
GNB_PORT_FOR_S1U = 2152; # Spec 2152 GNB_PORT_FOR_S1U = 2152; # Spec 2152
}; };
} }
@@ -177,13 +175,13 @@ MACRLCs = (
num_cc = 1; num_cc = 1;
tr_s_preference = "local_L1"; tr_s_preference = "local_L1";
tr_n_preference = "local_RRC"; tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 100; pusch_TargetSNRx10 = 180;
pucch_TargetSNRx10 = 200; pucch_TargetSNRx10 = 180;
dl_bler_target_upper = .35; # dl_bler_target_upper = .35;
dl_bler_target_lower = .15; # dl_bler_target_lower = .15;
ul_bler_target_upper = .35; # ul_bler_target_upper = .35;
ul_bler_target_lower = .15; # ul_bler_target_lower = .15;
pusch_FailureThres = 1000; pusch_FailureThres = 100;
ul_max_mcs = 28; ul_max_mcs = 28;
} }
); );
@@ -192,13 +190,13 @@ L1s = (
{ {
num_cc = 1; num_cc = 1;
tr_n_preference = "local_mac"; tr_n_preference = "local_mac";
prach_dtx_threshold = 90; prach_dtx_threshold = 100;
pucch0_dtx_threshold = 80; pucch0_dtx_threshold = 10;
pusch_dtx_threshold = 10; pusch_dtx_threshold = 10;
max_ldpc_iterations = 15; max_ldpc_iterations = 15;
tx_amp_backoff_dB = 12; # needs to match O-RU configuration tx_amp_backoff_dB = 12; # needs to match O-RU configuration
L1_rx_thread_core = 3; L1_rx_thread_core = 6;
L1_tx_thread_core = 4; L1_tx_thread_core = 7;
phase_compensation = 0; # needs to match O-RU configuration phase_compensation = 0; # needs to match O-RU configuration
} }
); );
@@ -206,17 +204,17 @@ L1s = (
RUs = ( RUs = (
{ {
local_rf = "no"; local_rf = "no";
nb_tx = 4; nb_tx = 2;
nb_rx = 4; nb_rx = 2;
att_tx = 0; att_tx = 0;
att_rx = 0; att_rx = 0;
bands = [78]; bands = [77];
max_pdschReferenceSignalPower = -27; max_pdschReferenceSignalPower = -27;
max_rxgain = 75; max_rxgain = 75;
sf_extension = 0; sf_extension = 0;
eNB_instances = [0]; eNB_instances = [0];
ru_thread_core = 5; ru_thread_core = 8;
sl_ahead = 10; sl_ahead = 5;
tr_preference = "raw_if4p5"; # important: activate FHI7.2 tr_preference = "raw_if4p5"; # important: activate FHI7.2
do_precoding = 0; # needs to match O-RU configuration do_precoding = 0; # needs to match O-RU configuration
} }
@@ -253,20 +251,23 @@ log_config :
}; };
fhi_72 = { fhi_72 = {
dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1"); dpdk_devices = ("0000:6f:01.0");
system_core = 0; system_core = 9;
io_core = 1; io_core = 10;
worker_cores = (2); worker_cores = (11);
ru_addr = ("70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81"); ru_addr = ("8c:1f:64:d1:11:1e");
mtu = 9216; mtu = 9216;
fh_config = ({ fh_config = ({
T1a_cp_dl = (419, 470); T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336); T1a_cp_ul = (285, 336);
T1a_up = (294, 345); T1a_up = (294, 345);
Ta4 = (0, 200); Ta4 = (0, 831);
ru_config = { ru_config = {
iq_width = 9; iq_width = 9;
iq_width_prach = 9; iq_width_prach = 9;
}; };
prach_config = {
eAxC_offset = 8;
};
}); });
}; };
@@ -142,7 +142,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -144,7 +144,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -145,7 +145,7 @@ gNBs =
nrofUplinkSlots = 2; nrofUplinkSlots = 2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -143,7 +143,7 @@ gNBs =
nrofUplinkSlots = 2; nrofUplinkSlots = 2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -145,7 +145,7 @@ gNBs =
nrofUplinkSlots = 2; nrofUplinkSlots = 2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -145,7 +145,7 @@ gNBs =
nrofUplinkSlots = 2; nrofUplinkSlots = 2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -144,7 +144,7 @@ gNBs =
nrofUplinkSlots = 1; #2; nrofUplinkSlots = 1; #2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -144,7 +144,7 @@ gNBs =
nrofUplinkSlots = 1; nrofUplinkSlots = 1;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0; ssPBCH_BlockPower = -11;
} }
); );
@@ -130,7 +130,7 @@ gNBs =
nrofDownlinkSymbols = 6; nrofDownlinkSymbols = 6;
nrofUplinkSlots = 1; #2; nrofUplinkSlots = 1; #2;
nrofUplinkSymbols = 4; nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -10; ssPBCH_BlockPower = -11;
} }
); );
# ------- SCTP definitions # ------- SCTP definitions