Merge branch 'integration_2025_w15' into 'develop'
Integration: `2025.w15` Closes #901, #943, #944, #942, and #939 See merge request oai/openairinterface5g!3374 * !3358 RedCap InitialBWP * !3364 NR UE: fix PRACH generation with frequency resource id not 0 when msg1-FDM > 1 in SIB1 * !3365 nr pdcp: 'count' is 32 bits, use explicit type instead of generic 'int' * !3366 Fix typo in gNB_scheduler_uci.c * !3370 Doc: add information on how to avoid a common asan bug * !3275 NAS service reject * !3312 NR UE: enable concurrent UL slot processing * !3368 Encapsulate cmake asn1c call, suppress useless output * !3336 Fix logging in nr_dlsim * !3281 Add support for 'dl_min_mcs' and 'ul_min_mcs' configuration parameters * !3355 NR UE: add support for continuous frequency offset compensation (in particular NTN LEO Doppler) * !3375 CI CoreNetwork fixes * !3184 NR SIB2 * !3348 CI: Replacing Devkit server with a Grace Hopper in Aerial pipeline
This commit is contained in:
@@ -823,6 +823,7 @@ set(PHY_SRC_COMMON
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/sqrt.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/lut.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/simde_operations.c
|
||||
${OPENAIR1_DIR}/PHY/TOOLS/get_sin_cos.c
|
||||
)
|
||||
|
||||
set(PHY_SRC
|
||||
|
||||
@@ -77,8 +77,8 @@ oc-cn5g-20897:
|
||||
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72"
|
||||
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-fhi72 %%log_dir%%"
|
||||
|
||||
oc-cn5g-20897-aerial2:
|
||||
Host: aerial2
|
||||
oc-cn5g-20897-aerial:
|
||||
Host: gracehopper1-oai
|
||||
NetworkScript: echo "inet 172.21.6.105"
|
||||
RunIperf3Server: False
|
||||
Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-nvidia-aerial"
|
||||
|
||||
@@ -49,7 +49,7 @@ class CoreNetwork:
|
||||
self._host = c.get('Host').strip()
|
||||
if self._host == "%%current_host%%":
|
||||
if node is None:
|
||||
raise Exception(f"core network {self} requires node, but none provided (cannot replace %%current_host%%)")
|
||||
raise Exception(f"core network {cn_name} requires node, but none provided (cannot replace %%current_host%%)")
|
||||
self._host = node
|
||||
if d is not None:
|
||||
raise Exception("directory handling not implemented")
|
||||
@@ -66,7 +66,7 @@ class CoreNetwork:
|
||||
logging.info(f'initialized core {self} from {filename}')
|
||||
|
||||
def __str__(self):
|
||||
return f"{self._cn_name}@{self._host} [IP: {self.getIP()}]"
|
||||
return f"{self._cn_name}@{self._host}"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
@@ -162,6 +162,9 @@ class CoreNetwork:
|
||||
def getCmdPrefix(self):
|
||||
return self._cmd_prefix or ""
|
||||
|
||||
def getName(self):
|
||||
return self._cn_name
|
||||
|
||||
def getHost(self):
|
||||
return self._host
|
||||
|
||||
|
||||
@@ -464,7 +464,7 @@ class OaiCiTest():
|
||||
return (False, f"UE {ue.getName()} has no IP address")
|
||||
svrIP = cn.getIP()
|
||||
if not svrIP:
|
||||
return (False, f"Iperf server {ue.getName()} has no IP address")
|
||||
return (False, f"Iperf server {cn.getName()} has no IP address")
|
||||
|
||||
iperf_opt = self.iperf_args
|
||||
jsonReport = "--json"
|
||||
@@ -862,7 +862,7 @@ class OaiCiTest():
|
||||
success, output = cn.deploy()
|
||||
logging.info(f"deployment core network {core_name} success {success}, output:\n{output}")
|
||||
if success:
|
||||
msg = f"Started {cn}"
|
||||
msg = f"Started {cn} [{cn.getIP()}]"
|
||||
HTML.CreateHtmlTestRowQueue(core_name, 'OK', [msg])
|
||||
else:
|
||||
msg = f"deployment of core network {core_name} FAILED"
|
||||
|
||||
@@ -186,8 +186,8 @@ gNBs =
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.131";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.131";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.202";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.202";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ gNBs =
|
||||
min_rxtxtime = 6;
|
||||
num_dlharq = 32;
|
||||
num_ulharq = 32;
|
||||
cu_sibs = [2];
|
||||
du_sibs = [19];
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -235,15 +237,6 @@ RUs = (
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_DISABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
@@ -296,6 +289,4 @@ log_config :
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="debug";
|
||||
f1ap_log_level ="debug";
|
||||
};
|
||||
|
||||
@@ -19,6 +19,8 @@ gNBs =
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
disable_harq = 1;
|
||||
cu_sibs = [2];
|
||||
du_sibs = [19];
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -48,7 +50,7 @@ gNBs =
|
||||
initialDLBWPsubcarrierSpacing = 0;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 2;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
initialDLBWPsearchSpaceZero = 2;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
uicc0 = {
|
||||
imsi = "208990100001100";
|
||||
key = "fec86ba6eb707ed08905757b1bb44b8f";
|
||||
opc= "C42449363BBAD02B66D16BC975D77CC1";
|
||||
dnn= "oai";
|
||||
nssai_sst=1;
|
||||
}
|
||||
|
||||
position0 = {
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 6377900.0;
|
||||
}
|
||||
|
||||
thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
|
||||
#/* configuration for channel modelisation */
|
||||
#/* To be included in main config file when */
|
||||
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */
|
||||
channelmod = {
|
||||
max_chan = 10;
|
||||
modellist = "modellist_rfsimu_1";
|
||||
modellist_rfsimu_1 = (
|
||||
{ # DL, modify on UE side
|
||||
model_name = "rfsimu_channel_enB0"
|
||||
type = "SAT_LEO_TRANS";
|
||||
noise_power_dB = -100;
|
||||
},
|
||||
{ # UL, modify on gNB side
|
||||
model_name = "rfsimu_channel_ue0"
|
||||
type = "SAT_LEO_TRANS";
|
||||
noise_power_dB = -100;
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>rfsim-5gnr-ntn-Leo</htmlTabRef>
|
||||
<htmlTabName>Monolithic SA NTN LEO gNB</htmlTabName>
|
||||
<htmlTabIcon>wrench</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
111111
|
||||
100001
|
||||
800813
|
||||
000001
|
||||
000002
|
||||
000003
|
||||
020001
|
||||
020002
|
||||
100001
|
||||
222222
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="111111">
|
||||
<class>Pull_Local_Registry</class>
|
||||
<desc>Pull Images from Local Registry</desc>
|
||||
<svr_id>0</svr_id>
|
||||
<images>oai-gnb-asan oai-nr-ue-asan</images>
|
||||
</testCase>
|
||||
|
||||
<testCase id="800813">
|
||||
<class>Create_Workspace</class>
|
||||
<desc>Create new Workspace</desc>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
<testCase id="000001">
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy OAI 5G CoreNetwork</desc>
|
||||
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_ntn_leo</yaml_path>
|
||||
<services>mysql oai-amf oai-smf oai-upf oai-ext-dn</services>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000002">
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy OAI 5G gNB+nrUE RF sim SA</desc>
|
||||
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_ntn_leo</yaml_path>
|
||||
<services>oai-gnb oai-nr-ue</services>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000003">
|
||||
<class>Attach_UE</class>
|
||||
<desc>Attach OAI UE (Wait for IP)</desc>
|
||||
<id>rfsim5g_ue</id>
|
||||
<nodes>cacofonix</nodes>
|
||||
</testCase>
|
||||
|
||||
<testCase id="020001">
|
||||
<class>Ping</class>
|
||||
<desc>Ping ext-dn from NR-UE</desc>
|
||||
<id>rfsim5g_ue</id>
|
||||
<nodes>cacofonix</nodes>
|
||||
<svr_id>rfsim5g_ext_dn</svr_id>
|
||||
<svr_node>cacofonix</svr_node>
|
||||
<ping_args>-c 20 -i 0.25</ping_args>
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="020002">
|
||||
<class>Ping</class>
|
||||
<desc>Ping NR-UE from ext-dn</desc>
|
||||
<id>rfsim5g_ext_dn</id>
|
||||
<nodes>cacofonix</nodes>
|
||||
<svr_id>rfsim5g_ue</svr_id>
|
||||
<svr_node>cacofonix</svr_node>
|
||||
<ping_args>-c 20 -i 0.25</ping_args>
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="100001">
|
||||
<class>Undeploy_Object</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Undeploy all OAI 5G stack</desc>
|
||||
<yaml_path>ci-scripts/yaml_files/5g_rfsimulator_ntn_leo</yaml_path>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
</testCase>
|
||||
|
||||
<testCase id="222222">
|
||||
<class>Clean_Test_Server_Images</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Clean Test Images on Test Server</desc>
|
||||
<svr_id>0</svr_id>
|
||||
<images>oai-gnb-asan oai-nr-ue-asan</images>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -44,7 +44,7 @@
|
||||
<testCase id="555000">
|
||||
<class>DeployCoreNetwork</class>
|
||||
<desc>Initialize 5G Core</desc>
|
||||
<cn_id>oc-cn5g-20897-aerial2</cn_id>
|
||||
<cn_id>oc-cn5g-20897-aerial</cn_id>
|
||||
</testCase>
|
||||
|
||||
<testCase id="111111">
|
||||
@@ -52,6 +52,7 @@
|
||||
<desc>Pull Images from Local Registry</desc>
|
||||
<svr_id>0</svr_id>
|
||||
<images>oai-gnb-aerial</images>
|
||||
<tag_prefix>arm_</tag_prefix>
|
||||
</testCase>
|
||||
|
||||
<testCase id="800813">
|
||||
@@ -89,16 +90,16 @@
|
||||
<class>Ping</class>
|
||||
<desc>Ping: 100pings in 20sec</desc>
|
||||
<id>up2-aerial</id>
|
||||
<svr_id>oc-cn5g-20897-aerial2</svr_id>
|
||||
<svr_id>oc-cn5g-20897-aerial</svr_id>
|
||||
<ping_args>-c 100 -i 0.2</ping_args>
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000022">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (DL/UDP/600M)(30 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-u -b 600M -t 30 -R</iperf_args>
|
||||
<svr_id>oc-cn5g-20897-aerial2</svr_id>
|
||||
<desc>iperf (DL/UDP/500M)(30 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-u -b 500M -t 30 -R</iperf_args>
|
||||
<svr_id>oc-cn5g-20897-aerial</svr_id>
|
||||
<id>up2-aerial</id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
@@ -106,9 +107,9 @@
|
||||
|
||||
<testCase id="000033">
|
||||
<class>Iperf</class>
|
||||
<desc>iperf (UL/UDP/50M)(30 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-u -b 50M -t 30</iperf_args>
|
||||
<svr_id>oc-cn5g-20897-aerial2</svr_id>
|
||||
<desc>iperf (UL/UDP/40M)(30 sec)(single-ue profile)</desc>
|
||||
<iperf_args>-u -b 40M -t 30</iperf_args>
|
||||
<svr_id>oc-cn5g-20897-aerial</svr_id>
|
||||
<id>up2-aerial</id>
|
||||
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
|
||||
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
|
||||
@@ -144,7 +145,7 @@
|
||||
<class>UndeployCoreNetwork</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Terminate 5G Core</desc>
|
||||
<cn_id>oc-cn5g-20897-aerial2</cn_id>
|
||||
<cn_id>oc-cn5g-20897-aerial</cn_id>
|
||||
</testCase>
|
||||
</testCaseList>
|
||||
|
||||
|
||||
@@ -1,49 +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-GH-AERIAL-SA</htmlTabRef>
|
||||
<htmlTabName>Gracehopper AERIAL 100 MHz TDD SA</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
111111
|
||||
333333
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
|
||||
<testCase id="111111">
|
||||
<class>Pull_Local_Registry</class>
|
||||
<desc>Pull Images from Local Registry</desc>
|
||||
<svr_id>0</svr_id>
|
||||
<images>oai-gnb-aerial</images>
|
||||
<tag_prefix>arm_</tag_prefix>
|
||||
</testCase>
|
||||
|
||||
<testCase id="333333">
|
||||
<class>Clean_Test_Server_Images</class>
|
||||
<always_exec>true</always_exec>
|
||||
<desc>Clean Test Images on Test Server</desc>
|
||||
<svr_id>0</svr_id>
|
||||
<images>oai-gnb-aerial</images>
|
||||
</testCase>
|
||||
</testCaseList>
|
||||
|
||||
@@ -110,7 +110,7 @@ services:
|
||||
- NET_ADMIN # for interface bringup
|
||||
- NET_RAW # for ping
|
||||
environment:
|
||||
USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time
|
||||
USE_ADDITIONAL_OPTIONS: --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 238.74 --rfsimulator.serveraddr 192.168.71.140 --num-ul-actors 1 --log_config.global_log_options level,nocolor,time
|
||||
depends_on:
|
||||
- oai-gnb
|
||||
networks:
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
services:
|
||||
mysql:
|
||||
container_name: "rfsim5g-mysql"
|
||||
image: mysql:8.0
|
||||
volumes:
|
||||
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
|
||||
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- MYSQL_DATABASE=oai_db
|
||||
- MYSQL_USER=test
|
||||
- MYSQL_PASSWORD=test
|
||||
- MYSQL_ROOT_PASSWORD=linux
|
||||
healthcheck:
|
||||
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.131
|
||||
oai-amf:
|
||||
container_name: "rfsim5g-oai-amf"
|
||||
image: oaisoftwarealliance/oai-amf:v2.0.0
|
||||
environment:
|
||||
- TZ=Europe/paris
|
||||
volumes:
|
||||
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml
|
||||
depends_on:
|
||||
- mysql
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.132
|
||||
oai-smf:
|
||||
container_name: "rfsim5g-oai-smf"
|
||||
image: oaisoftwarealliance/oai-smf:v2.0.0
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
|
||||
depends_on:
|
||||
- oai-amf
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.133
|
||||
oai-upf:
|
||||
container_name: "rfsim5g-oai-upf"
|
||||
image: oaisoftwarealliance/oai-upf:v2.0.0
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
- ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml
|
||||
depends_on:
|
||||
- oai-smf
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_ADMIN
|
||||
cap_drop:
|
||||
- ALL
|
||||
privileged: true
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.134
|
||||
traffic_net:
|
||||
ipv4_address: 192.168.72.134
|
||||
oai-ext-dn:
|
||||
privileged: true
|
||||
container_name: rfsim5g-oai-ext-dn
|
||||
image: oaisoftwarealliance/trf-gen-cn5g:focal
|
||||
entrypoint: /bin/bash -c \
|
||||
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
|
||||
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
|
||||
depends_on:
|
||||
- oai-upf
|
||||
networks:
|
||||
traffic_net:
|
||||
ipv4_address: 192.168.72.135
|
||||
healthcheck:
|
||||
test: /bin/bash -c "ping -c 2 192.168.72.134"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
oai-gnb:
|
||||
image: ${REGISTRY:-oaisoftwarealliance}/${GNB_IMG:-oai-gnb}:${TAG:-develop}
|
||||
container_name: rfsim5g-oai-gnb
|
||||
cap_drop:
|
||||
- ALL
|
||||
environment:
|
||||
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
|
||||
ASAN_OPTIONS: detect_leaks=0
|
||||
depends_on:
|
||||
- oai-ext-dn
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.140
|
||||
volumes:
|
||||
- ../../conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn-leo.conf:/opt/oai-gnb/etc/gnb.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-softmodem"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
oai-nr-ue:
|
||||
image: ${REGISTRY:-oaisoftwarealliance}/${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
|
||||
container_name: rfsim5g-oai-nr-ue
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- NET_ADMIN # for interface bringup
|
||||
- NET_RAW # for ping
|
||||
environment:
|
||||
USE_ADDITIONAL_OPTIONS:
|
||||
--band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60
|
||||
--rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod
|
||||
--rfsimulator.serveraddr 192.168.71.140
|
||||
--time-sync-I 0.1 --ntn-initial-time-drift -46
|
||||
--autonomous-ta --initial-fo 57340 --cont-fo-comp 2
|
||||
--log_config.global_log_options level,nocolor,time
|
||||
depends_on:
|
||||
- oai-gnb
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.71.150
|
||||
devices:
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
volumes:
|
||||
- ../../conf_files/nrue.uicc.ntn-leo.conf:/opt/oai-nr-ue/etc/nr-ue.conf
|
||||
healthcheck:
|
||||
test: /bin/bash -c "pgrep nr-uesoftmodem"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
networks:
|
||||
public_net:
|
||||
driver: bridge
|
||||
name: rfsim5g-oai-public-net
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 192.168.71.128/26
|
||||
driver_opts:
|
||||
com.docker.network.bridge.name: "rfsim5g-public"
|
||||
traffic_net:
|
||||
driver: bridge
|
||||
name: rfsim5g-oai-traffic-net
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 192.168.72.128/26
|
||||
driver_opts:
|
||||
com.docker.network.bridge.name: "rfsim5g-traffic"
|
||||
@@ -24,7 +24,7 @@ sudo -E echo start_server -uid 0 | sudo -E nvidia-cuda-mps-control
|
||||
# Check if an argument is provided
|
||||
if [ $# -eq 0 ]; then
|
||||
# No argument provided, use default value
|
||||
argument="P5G_FXN"
|
||||
argument="P5G_FXN_GH"
|
||||
else
|
||||
# Argument provided, use it
|
||||
argument="$1"
|
||||
|
||||
@@ -23,7 +23,7 @@ services:
|
||||
- ../../../cmake_targets/share:/opt/cuBB/share
|
||||
userns_mode: host
|
||||
ipc: "shareable"
|
||||
image: cubb-build:24-1
|
||||
image: cubb-build:24-3
|
||||
environment:
|
||||
- cuBB_SDK=/opt/nvidia/cuBB
|
||||
command: bash -c "sudo rm -rf /tmp/phy.log && sudo chmod +x /opt/nvidia/cuBB/aerial_l1_entrypoint.sh && /opt/nvidia/cuBB/aerial_l1_entrypoint.sh"
|
||||
|
||||
@@ -107,3 +107,18 @@ or directly with
|
||||
")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(run_asn1c ASN1C_GRAMMAR ASN1C_PREFIX)
|
||||
set(options "")
|
||||
set(oneValueArgs COMMENT)
|
||||
set(multiValueArgs OUTPUT OPTIONS)
|
||||
cmake_parse_arguments(ASN1C "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
get_filename_component(GRAMMAR_FILE ${ASN1C_GRAMMAR} NAME)
|
||||
set(LOGFILE "${CMAKE_CURRENT_BINARY_DIR}/${GRAMMAR_FILE}.log")
|
||||
add_custom_command(OUTPUT ${ASN1C_OUTPUT}
|
||||
COMMAND ASN1C_PREFIX=${ASN1C_PREFIX} ${ASN1C_EXEC} ${ASN1C_OPTIONS} -D ${CMAKE_CURRENT_BINARY_DIR} ${ASN1C_GRAMMAR} > ${LOGFILE} 2>&1 || cat ${LOGFILE}
|
||||
DEPENDS ${ASN1C_GRAMMAR}
|
||||
COMMENT "Generating ${ASN1C_COMMENT} from ${GRAMMAR_FILE}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
@@ -157,14 +157,19 @@ int write_file_matlab(const char *fname, const char *vname, void *data, int leng
|
||||
|
||||
//printf("Writing %d elements of type %d to %s\n",length,format,fname);
|
||||
|
||||
const int fname_len = strlen(fname);
|
||||
char write_file_name[fname_len + 10];
|
||||
const char *fn_format = (format & MATLAB_RAW) ? "%s.bin" : "%s";
|
||||
snprintf(write_file_name, sizeof(write_file_name), fn_format, fname);
|
||||
|
||||
if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) {
|
||||
fp = fopen(fname,"a+");
|
||||
fp = fopen(write_file_name, "a+");
|
||||
} else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) {
|
||||
fp = fopen(fname,"w+");
|
||||
fp = fopen(write_file_name, "w+");
|
||||
}
|
||||
|
||||
if (fp== NULL) {
|
||||
printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n",fname);
|
||||
printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n", write_file_name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "assertions.h"
|
||||
#include "common/utils/utils.h"
|
||||
|
||||
#define MAX_SI_GROUPS 3
|
||||
#define NR_MAX_PDSCH_TBS 3824
|
||||
#define MAX_NUM_BEAM_PERIODS 4
|
||||
#define MAX_BWP_SIZE 275
|
||||
@@ -93,6 +94,12 @@ static inline const char *rnti_types(nr_rnti_type_t rr)
|
||||
// the total shift is 2 * 15, in dB scale thats 10log10(2^(15*2))
|
||||
#define SQ15_SQUARED_NORM_FACTOR_DB 90.3089986992
|
||||
|
||||
typedef struct {
|
||||
uint8_t *SIB_buffer;
|
||||
int SIB_size;
|
||||
int SIB_type;
|
||||
} nr_SIBs_t;
|
||||
|
||||
typedef struct nr_bandentry_s {
|
||||
int16_t band;
|
||||
uint64_t ul_min;
|
||||
|
||||
@@ -24,8 +24,11 @@ The hardware on which we have tried this tutorial:
|
||||
|----------------------------------------------------------------------------|----------------------------------|--------------------------------------------------|
|
||||
| Gigabyte Edge E251-U70 (Intel Xeon Gold 6240R, 2.4GHz, 24C48T, 96GB DDR4) |Ubuntu 22.04.3 LTS (5.15.0-72-lowlatency)| NVIDIA ConnectX®-6 Dx 22.38.1002 |
|
||||
| Dell PowerEdge R750 (Dual Intel Xeon Gold 6336Y CPU @ 2.4G, 24C/48T (185W), 512GB RDIMM, 3200MT/s) |Ubuntu 22.04.3 LTS (5.15.0-72-lowlatency)| NVIDIA Converged Accelerator A100X (24.39.2048) |
|
||||
| Supermicro Grace Hopper MGX ARS-111GL-NHR (Neoverse-V2, 3.4GHz, 72C/72T, 576GB LPDDR5) | Ubuntu 22.04.5 LTS (6.5.0-1019-nvidia-64k) |NVIDIA BlueField3 (32.41.1000)|
|
||||
|
||||
**NOTE**: These are not minimum hardware requirements. This is the configuration of our servers. The NIC card should support hardware PTP time stamping.
|
||||
**NOTE**:
|
||||
- These are not minimum hardware requirements. This is the configuration of our servers. The NIC card should support hardware PTP time stamping.
|
||||
- Starting from tag [2025.w13](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/2025.w13?ref_type=tags) of OAI, we are only testing with the Grace Hopper server.
|
||||
|
||||
PTP enabled switches and grandmaster clock we have tested with:
|
||||
|
||||
@@ -42,6 +45,7 @@ These are the radio units we've used for testing:
|
||||
|-------------|------------------|
|
||||
| Foxconn RPQN-7801E RU | 2.6.9r254 |
|
||||
| Foxconn RPQN-7801E RU | 3.1.15_0p4 |
|
||||
| Foxconn RPQN-7801E RU | v3.2.0q.551.12.E.rc2.srs-AIO |
|
||||
|
||||
|
||||
The UEs that have been tested and confirmed working with Aerial are the following:
|
||||
@@ -54,35 +58,30 @@ The UEs that have been tested and confirmed working with Aerial are the followin
|
||||
| Apaltec | Tributo 5G-Dongle |
|
||||
| OnePlus | Nord (AC2003) |
|
||||
| Apple iPhone | 14 Pro (MQ0G3RX/A) (iOS 17.3) |
|
||||
| Samsung | S23 Ultra |
|
||||
|
||||
|
||||
## Configure your server
|
||||
|
||||
The first step is to obtain the NVIDIA Aerial SDK, you'll need to request access [here](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/aerial-sdk).
|
||||
|
||||
After obtaining access to the SDK, you can refer to [this instructions page](https://docs.nvidia.com/aerial/aerial-ran-colab-ota/current/index.html) to setup the L1 components using NVIDIAs' SDK manager, or to [this instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html) in order to setup and install the components manually.
|
||||
|
||||
The currently used Aerial Version is 24-1, which is also the one currently used by the SDK Manager.
|
||||
To set up the L1 and install the components manually refer to this [instructions page](https://docs.nvidia.com/aerial/cuda-accelerated-ran/index.html).
|
||||
|
||||
**Note**:
|
||||
- To configure the Gigabyte server please refer to these [instructions](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/2025.w13/doc/Aerial_FAPI_Split_Tutorial.md)
|
||||
- The last release to support the Gigabyte server is **Aerial CUDA-Accelerated RAN 24-1**.
|
||||
|
||||
### CPU allocation
|
||||
|
||||
Currently, the CPU isolation is setup the following:
|
||||
| Server brand | Model | Nº of CPU Cores | Isolated CPUs |
|
||||
|------------------|---------------|:---------------:|:--------------:|
|
||||
| Grace Hopper MGX | ARS-111GL-NHR | 72 | 4-64 |
|
||||
|
||||
| Server brand | Model | Nº of CPU Cores | Isolated CPUs |
|
||||
|--------------|-----------|:---------------:|:--------------:|
|
||||
| Gigabyte | Edge E251-U70 | 24 | 2-10 |
|
||||
|
||||
|
||||
**Gigabyte Edge E251-U70**
|
||||
**Grace Hopper MGX ARS-111GL-NHR**
|
||||
|
||||
| Applicative Threads | Allocated CPUs |
|
||||
|------------------------|----------------|
|
||||
| Aerial L1 | 2,3,4,5,6,7,8 |
|
||||
| PTP & PHC2SYS Services | 9 |
|
||||
| PTP & PHC2SYS Services | 41 |
|
||||
| OAI `nr-softmodem` | 13-20 |
|
||||
|
||||
|
||||
## PTP configuration
|
||||
|
||||
1. You need to install the `linuxptp` debian package. It will install both ptp4l and phc2sys.
|
||||
@@ -99,14 +98,10 @@ Once installed you can use this configuration file for ptp4l (`/etc/ptp4l.conf`)
|
||||
domainNumber 24
|
||||
slaveOnly 1
|
||||
time_stamping hardware
|
||||
tx_timestamp_timeout 1
|
||||
logging_level 6
|
||||
summary_interval 0
|
||||
#priority1 127
|
||||
tx_timestamp_timeout 30
|
||||
|
||||
[your_PTP_ENABLED_NIC]
|
||||
network_transport L2
|
||||
hybrid_e2e 0
|
||||
|
||||
```
|
||||
|
||||
@@ -120,7 +115,7 @@ Documentation=man:ptp4l
|
||||
Restart=always
|
||||
RestartSec=5s
|
||||
Type=simple
|
||||
ExecStart=taskset -c 9 /usr/sbin/ptp4l -f /etc/ptp.conf
|
||||
ExecStart=taskset -c 41 /usr/sbin/ptp4l -f /etc/ptp.conf
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -149,17 +144,16 @@ WantedBy=multi-user.target
|
||||
|
||||
# Build OAI gNB
|
||||
|
||||
If installing with the Aerial SDK, you should already have the repository cloned in `~/openairinterface5g`, if
|
||||
Clone OAI code base in a suitable repository, here we are cloning in `~/openairinterface5g` directory,
|
||||
|
||||
If it's not already cloned, the first step is to clone OAI repository
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ~/openairinterface5g
|
||||
cd ~/openairinterface5g/
|
||||
```
|
||||
|
||||
## Get nvIPC sources from the L1 container
|
||||
The library used for communication between L1 and L2 components is called nvIPC, and was developed by NVIDIA, as such, it is not open-source and can't be freely distributed.
|
||||
In order to be able to use this library to achieve communication, we need to obtain the nvIPC source files from the L1 container (cuBB) and place it in out gNB project directory `~/openairinterface5g`.
|
||||
|
||||
The library used for communication between L1 and L2 components is called nvIPC, and is developed by NVIDIA. It is not open-source and can't be freely distributed.
|
||||
In order to achieve this communication, we need to obtain the nvIPC source files from the L1 container (cuBB) and place it in the gNB project directory `~/openairinterface5g`.
|
||||
This allows us to build and install this library when building the L2 docker container.
|
||||
|
||||
Check whether your L1 container is running:
|
||||
@@ -177,7 +171,7 @@ cuBB
|
||||
aerial@c_aerial_aerial:/opt/nvidia/cuBB#
|
||||
```
|
||||
|
||||
After logging into the container, we need to pack the nvIPC sources and copy them to the host ( the command creates a tar.gz file with the following name format: nvipc_src.YYYY.MM.DD.tar.gz)
|
||||
After logging into the container, you need to pack the nvIPC sources and copy them to the host ( the command creates a `tar.gz` file with the following name format: `nvipc_src.YYYY.MM.DD.tar.gz`)
|
||||
```bash
|
||||
~$ docker exec -it cuBB bash
|
||||
aerial@c_aerial_aerial:/opt/nvidia/cuBB# cd cuPHY-CP/gt_common_libs
|
||||
@@ -216,7 +210,7 @@ With the nvIPC sources in the project directory, the docker image can be built.
|
||||
|
||||
## Building OAI gNB docker image
|
||||
|
||||
In order to build the final image, there is an intermediary image to be built (ran-base)
|
||||
In order to build the target image (`oai-gnb-aerial`), first you should build a common shared image (`ran-base`)
|
||||
```bash
|
||||
~$ cd ~/openairinterface5g/
|
||||
~/openairinterface5g$ docker build . -f docker/Dockerfile.base.ubuntu22 --tag ran-base:latest
|
||||
@@ -224,21 +218,23 @@ In order to build the final image, there is an intermediary image to be built (r
|
||||
```
|
||||
|
||||
|
||||
## Running the setup
|
||||
In order to use Docker compose to automatically start and stop the setup, we need to first create a ready-made image of the L1, after compiling the L1 software and making the necessary adjustments to its configuration files.
|
||||
The process of preparing the L1 is covered on NVIDIAs' documentation, and falls outside the scope of this document.
|
||||
# Running the setup
|
||||
|
||||
### Prepare the L1 image
|
||||
After preparing the L1 software, the container needs to be committed in order for an image in which the L1 is ready to be executed, and that can be referenced by a docker-compose.yaml file later:
|
||||
*Note:* In preparing the L1 image, the default L1 configuration file is cuphycontroller_P5G_FXN.yaml, located in `/opt/nvidia/cuBB/cuPHY-CP/cuphycontroller/config/`.
|
||||
This is the file where the RU MAC address needs to be applied before commiting the image
|
||||
In order to use Docker Compose to automatically start and stop the setup, we first need to create a pre-built image of L1 after compiling the L1 software and making the necessary adjustments to its configuration files.
|
||||
The process of preparing L1 is covered in NVIDIA's documentation and falls outside the scope of this document.
|
||||
|
||||
## Prepare the L1 image
|
||||
After preparing the L1 software, the container needs to be committed to create an image where L1 is ready for execution, which can later be referenced by a `docker-compose.yaml` file.
|
||||
|
||||
*Note:* The default L1 configuration file is `cuphycontroller_P5G_FXN_GH.yaml`, located in `/opt/nvidia/cuBB/cuPHY-CP/cuphycontroller/config/`.
|
||||
In this file the RU MAC address needs to be specified before commiting the image.
|
||||
|
||||
```bash
|
||||
~$ docker commit nv-cubb cubb-build:24-1
|
||||
~$ docker commit nv-cubb cubb-build:24-3
|
||||
~$ docker image ls
|
||||
..
|
||||
cubb-build 24-1 824156e0334c 2 weeks ago 40.1GB
|
||||
..
|
||||
cubb-build 24-3 824156e0334c 2 weeks ago 23.9GB
|
||||
-..
|
||||
```
|
||||
|
||||
## Adapt the OAI-gNB configuration file to your system/workspace
|
||||
@@ -255,14 +251,12 @@ The default amf_ip_address:ipv4 value is 192.168.70.132, when installing the CN5
|
||||
Both 'GNB_IPV4_ADDRESS_FOR_NG_AMF' and 'GNB_IPV4_ADDRESS_FOR_NGU' need to be set to the IP address of the NIC referenced previously.
|
||||
|
||||
|
||||
### Running docker compose
|
||||
#### Aerial L1 entrypoint script
|
||||
Before running docker-compose, we can check which L1 configuration file is to be used by cuphycontroller_scf.
|
||||
This is set in the script [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh), which is used by the L1 container in order to start the L1 software.
|
||||
The script begins by setting up some environment variables, restarting NVIDIA MPS, and finally running cuphycontroller_scf.
|
||||
The L1 software is run with an argument that indicates which configuration file is to be used.
|
||||
This argument may be changed by providing an argument to the [`aerial_l1_entrypoint.sh`](../ci-scripts/yaml_files/sa_gnb_aerial/aerial_l1_entrypoint.sh) call in [`docker-compose.yaml`](../ci-scripts/yaml_files/sa_gnb_aerial/docker-compose.yaml).
|
||||
When no argument is provided (this is the default behaviour), it uses "P5G_FXN" as the cuphycontroller_scf argument.
|
||||
## Running docker compose
|
||||
### Aerial L1 entrypoint script
|
||||
The `aerial_l1_entrypoint` script is used by the L1 container to start the L1 software and is called in the Docker Compose file.
|
||||
It begins by setting up environment variables, restarting NVIDIA MPS, and finally running `cuphycontroller_scf`.
|
||||
|
||||
The L1 software is executed with an argument that specifies which configuration file to use. If not modified, the default argument is set to `P5G_FXN_GH`.
|
||||
|
||||
After building the gNB image, and preparing the configuration file, the setup can be run with the following command:
|
||||
|
||||
@@ -271,17 +265,18 @@ cd ci-scripts/yaml_files/sa_gnb_aerial/
|
||||
docker compose up -d
|
||||
|
||||
```
|
||||
This will start both containers, beginning with 'nv-cubb' and only after it being ready it starts 'oai-gnb-aerial'.
|
||||
This will start both containers, beginning with `nv-cubb`, and `oai-gnb-aerial` will start only after it is ready.
|
||||
|
||||
The gNB logs can be followed with:
|
||||
The logs can be followed using these commands:
|
||||
|
||||
```bash
|
||||
docker logs -f oai-gnb-aerial
|
||||
docker logs -f nv-cubb
|
||||
```
|
||||
#### Running with multiple L2s
|
||||
### Running with multiple L2s
|
||||
One L1 instance can support multiple L2 instances. See also the [aerial documentation](https://developer.nvidia.com/docs/gputelecom/aerial-sdk/text/cubb_quickstart/running_cubb-end-to-end.html#run-multiple-l2-instances-with-single-l1-instance) for more details.
|
||||
|
||||
In OAI the share memory prefix must be configured in the configuration file.
|
||||
In OAI the shared memory prefix must be configured in the configuration file.
|
||||
|
||||
```bash
|
||||
tr_s_preference = "aerial";
|
||||
@@ -289,9 +284,9 @@ In OAI the share memory prefix must be configured in the configuration file.
|
||||
```
|
||||
|
||||
|
||||
### Stopping the setup
|
||||
## Stopping the setup
|
||||
|
||||
Running the following command, will stop both containers, leaving the system ready to be run later:
|
||||
Run the following command to stop and remove both containers, leaving the system ready to be restarted later:
|
||||
```bash
|
||||
cd ci-scripts/yaml_files/sa_gnb_aerial/
|
||||
docker compose down
|
||||
|
||||
+3
-2
@@ -105,7 +105,7 @@ These modes of operation are supported:
|
||||
|
||||
- MAC -> PHY configuration using NR FAPI P5 interface
|
||||
- MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU
|
||||
- Scheduler procedures for SIB1
|
||||
- Generation of and scheduler procedures for MIB/SIB1
|
||||
- Scheduler procedures for RA
|
||||
- 4-Step RA
|
||||
- Contention Free RA procedure
|
||||
@@ -140,6 +140,7 @@ These modes of operation are supported:
|
||||
- MAC scheduling of SR reception
|
||||
- Intra-frequency handover
|
||||
- Initial support for RedCap
|
||||
- Scheduling of SIBs (2, 19)
|
||||
|
||||
## gNB RLC
|
||||
|
||||
@@ -174,7 +175,7 @@ These modes of operation are supported:
|
||||
|
||||
- NR RRC (38.331) Rel 17 messages using new [asn1c](https://github.com/mouse07410/asn1c)
|
||||
- LTE RRC (36.331) also updated to Rel 15
|
||||
- Generation of MIB/SIB1 (received from DU)
|
||||
- Generation of system information (SIB2)
|
||||
- RRC can configure PDCP, RLC, MAC
|
||||
- Interface with GTP-U (tunnel creation/handling for S1-U (NSA), N3 (SA), F1 interfaces)
|
||||
- Integration of RRC messages and procedures supporting UE 5G SA connection
|
||||
|
||||
@@ -232,7 +232,9 @@ In the `MACRLCs` section of the gNB/DU configuration file:
|
||||
|
||||
In the `gNBs` section of the gNB/DU configuration file: some of the parameters
|
||||
affect RRC configuration (CellGroupConfig) of a UE, and are therefore listed
|
||||
here, *also they pertain to the DU*, i.e., the scheduler.
|
||||
here, *also they pertain to the DU*, i.e., the scheduler. Note also that some
|
||||
SIBs are configured at the DU and some at the CU; please consult the [RRC
|
||||
configuration](../RRC/rrc-usage.md) as well for SIB configuration.
|
||||
|
||||
* `pdsch_AntennaPorts_XP` (default 1): number of XP logical antenna
|
||||
ports in PDSCH (see also [`RUNMODEM.md`](../RUNMODEM.md))
|
||||
@@ -267,6 +269,8 @@ here, *also they pertain to the DU*, i.e., the scheduler.
|
||||
options are 2, 4, 6, 8, 10, 12, 32; **32 is a Rel-17 features**)
|
||||
* `num_ulharq` (default 16): as `num_dlharq` for UL (other valid option is 32;
|
||||
**32 is i Rel-17 feature**)
|
||||
- `du_sibs` (default `[]`): list of SIBs to transmit in the cell. Currently,
|
||||
SIB19 (for NTN) is supported.
|
||||
|
||||
## ServingCellConfigCommon parameters
|
||||
|
||||
|
||||
@@ -67,6 +67,9 @@ RRC-specific configuration
|
||||
|
||||
### cell-specific options
|
||||
|
||||
Note that some SIBS are configured at the CU and some at the DU; please consult
|
||||
the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration.
|
||||
|
||||
- `gNB_ID` and `gNB_name`: ID and name of the gNB
|
||||
- `tracking_area_code`: the current tracking area code in the range `[0x0001,
|
||||
0xfffd]`
|
||||
@@ -84,6 +87,8 @@ RRC-specific configuration
|
||||
- `enable_sdap` (default: false): enable the use of the SDAP layer. If
|
||||
deactivated, a transparent SDAP header is prepended to packets, but no
|
||||
further processing is being done.
|
||||
- `cu_sibs` (default: `[]`) list of SIBs to give to the DU for transmission.
|
||||
Currently, SIB2 is supported.
|
||||
|
||||
### UE-specific configuration
|
||||
|
||||
|
||||
+16
-2
@@ -136,7 +136,15 @@ Here are some useful command line options for the NR UE:
|
||||
| Parameter | Description |
|
||||
|--------------------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| `--ue-scan-carrier` | Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. |
|
||||
| `--ue-fo-compensation` | Enables the frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. |
|
||||
| `--ue-fo-compensation` | Enables the initial frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. |
|
||||
| `--cont-fo-comp` | Enables the continuous frequency offset (FO) estimation and compensation. Parameter value `1` specifies that the main FO contribution comes from the local oscillator's (LO) accuracy. Parameter value `2` specifies that the main FO contribution comes from Doppler shift. |
|
||||
| `--initial-fo` | Sets the known initial frequency offset. Useful especially with large Doppler frequency, e.g. LEO satellite. |
|
||||
| `--freq-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the continuous frequency offset compensation. Default value 0.01. |
|
||||
| `--freq-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the continuous frequency offset compensation. Default value 0.001. |
|
||||
| `--ntn-initial-time-drift` | Sets the initial NTN DL time drift (feeder link and service link), given in µs/s. |
|
||||
| `--autonomous-ta` | Enables the autonomous TA update, based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite). |
|
||||
| `--time-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the time synchronization. Default value 0.5. |
|
||||
| `--time-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the time synchronization. Default value 0.0. |
|
||||
| `--usrp-args` | Equivalent to the `sdr_addrs` field in the gNB config file. Used to identify the USRP and set some basic parameters (like the clock source). |
|
||||
| `--clock-source` | Sets the clock source (internal or external). |
|
||||
| `--time-source` | Sets the time source (internal or external). |
|
||||
@@ -349,10 +357,16 @@ For LEO satellite scenarios, the parameter `--ntn-initial-time-drift` must be pr
|
||||
This parameter provides the drift rate of the complete DL timing (incl. feeder link and service link) in µs/s.
|
||||
Also, to perform an autonomous TA update based on the DL drift, the boolean parameter `--autonomous-ta` should be added in case of a LEO satellite scenario.
|
||||
|
||||
For LEO satellite scenario we assume the LO to be very accurate and the main FO contribution comes from Doppler shift.
|
||||
Therefore, we use the command line parameter `--cont-fo-comp 2` to continuously compensate the DL Doppler and pre-compensate the UL Doppler.
|
||||
The initial Doppler frequency offset must be provided via command line with the parameter `--initial-fo`.
|
||||
|
||||
For other information on optional NR UE command line options, please refer [here](#optional-nr-ue-command-line-options).
|
||||
|
||||
So an example NR UE command for FDD, 5MHz BW, 15 kHz SCS, transparent LEO satellite 5G NR NTN is this:
|
||||
```
|
||||
cd cmake_targets
|
||||
sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta
|
||||
sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf --band 254 -C 2488400000 --CO -873500000 -r 25 --numerology 0 --ssb 60 --rfsim --rfsimulator.prop_delay 20 --rfsimulator.options chanmod --time-sync-I 0.1 --ntn-initial-time-drift -46 --autonomous-ta --initial-fo 57340 --cont-fo-comp 2
|
||||
```
|
||||
|
||||
# Specific OAI modes
|
||||
|
||||
+4
-4
@@ -19,10 +19,10 @@
|
||||
| starsky | Starsky | eNB (B40) | b200mini (30A3E3C) |
|
||||
| carabe | Carabe | UE (B7UE) | B200mini (30AE8C9) |
|
||||
| avra | Avra | gNB (n78) | AW2S Jaguar (192.168.80.239) |
|
||||
| aerial2 | Aerial2 | gNB (PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial SDK integrated_ |
|
||||
| cacofonix | Cacofonix | gNB (n78, FHI7.2) | -- |
|
||||
| matix | Matix | gNB (n77) | N310 |
|
||||
| gracehopper1-oai | Gracehopper1 | build, gNB/Aerial | _Nvidia Aerial SDK integrated_ |
|
||||
| gracehopper1-oai | Gracehopper1 | gNB (n78, PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial integration_ |
|
||||
| gracehopper3-oai | Gracehopper3 | build | -- |
|
||||
|
||||
Note: The available resources, and their current usage, is indicated here:
|
||||
- [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/):
|
||||
@@ -127,7 +127,7 @@ information on how the images are built.
|
||||
- build unit tests from `ci-scripts/docker/Dockerfile.unittest.ubuntu22`, and run them
|
||||
- [RAN-Ubuntu-ARM-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu-ARM-Image-Builder/)
|
||||
~BUILD-ONLY ~4G-LTE ~5G-NR
|
||||
- gracehopper1-oai: ARM Ubuntu 22 image build using docker
|
||||
- gracehopper3-oai: ARM Ubuntu 22 image build using docker
|
||||
- base image from `Dockerfile.base.ubuntu22`
|
||||
- build image from `Dockerfile.build.ubuntu22`, followed by
|
||||
- target image from `Dockerfile.gNB.ubuntu22`
|
||||
@@ -199,7 +199,7 @@ information on how the images are built.
|
||||
- OpenShift cluster for CN deployment and container images for gNB and UE deployment
|
||||
- [RAN-SA-AERIAL-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AERIAL-CN5G/)
|
||||
~5G-NR
|
||||
- 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on Aerial2 + Foxconn RU, up2 + COTS UE (Quectel RM520N), OAI CN5G
|
||||
- 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on gracehopper1-oai + Foxconn RU, up2 + COTS UE (Quectel RM520N), OAI CN5G
|
||||
- container images for gNB deployment
|
||||
- [RAN-SA-2x2-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-2x2-Module-CN5G/)
|
||||
~5G-NR
|
||||
|
||||
@@ -29,6 +29,25 @@ cd cmake_targets/ran_build/build
|
||||
sudo LD_LIBRARY_PATH=. ./nr-softmodem ...
|
||||
```
|
||||
|
||||
### Possible problems
|
||||
|
||||
On some systems with specific ASan versions, executing a program compiled with
|
||||
ASan might fail with an error `DEADLYSIGNAL`, or simply a segmentation fault.
|
||||
Note that since OAI compiles and runs some programs _during compilation_ (for
|
||||
code generation), typically already the build is impacted.
|
||||
|
||||
The issue is related to Address Space Layout Randomization (ASLR) settings
|
||||
in Linux, a security feature designed to make it more difficult for attackers
|
||||
to predict the locations of processes in memory. In this case, it is possible
|
||||
to avoid the bug by running
|
||||
|
||||
```
|
||||
sudo sysctl vm.mmap_rnd_bits=30
|
||||
```
|
||||
|
||||
which reduces the number of bits for memory mappings used to randomize mmap
|
||||
base addresses. _This reduces the security of the system._
|
||||
|
||||
## Undefined Behavior Sanitizer (UBSAN)
|
||||
[Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) (UBSAN) is a runtime undefined behavior checker. It uses compile-time instrumentation to catch undefined behavior by inserting code that performs specific checks before operations that may cause it. UBSAN can be activated with the `--sanitize-undefined` option or `-fsanitize=undefined`.
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 80 KiB |
@@ -13,15 +13,15 @@
|
||||
duplexer/.style={draw,fill=white},
|
||||
]
|
||||
|
||||
\node[label=above:porcepix] (porcepix)
|
||||
\node[label=above:cluster] (cluster)
|
||||
{\includegraphics[width=1.2cm]{server}};
|
||||
|
||||
\node[above right=-0.8cm and 2cm of porcepix, label=above:aerial2] (aerial2)
|
||||
\node[above right=-0.6cm and 2cm of cluster, label=above:gracehopper1-oai] (gracehopper1-oai)
|
||||
{\includegraphics[width=1.2cm]{server}}
|
||||
edge (porcepix);
|
||||
\node[right=0.3cm of aerial2, label=above:Foxconn, draw,
|
||||
edge (cluster);
|
||||
\node[right=0.3cm of gracehopper1-oai, label=above:Foxconn, draw,
|
||||
minimum width=1.7cm, minimum height=0.8cm] (foxconn)
|
||||
{O-RU} edge (aerial2);
|
||||
{O-RU} edge (gracehopper1-oai);
|
||||
\node[below right=+0.45cm and 0.35cm of foxconn.east] (antf1)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (foxconn.east);
|
||||
\node[below right=-0.1cm and 0.35cm of foxconn.east] (antf2)
|
||||
@@ -31,7 +31,7 @@
|
||||
\node[above right=+0.45cm and 0.35cm of foxconn.east] (antf4)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (foxconn.east);
|
||||
|
||||
\node[above right=+1.3cm and 2cm of porcepix, label=above:matix] (matix)
|
||||
\node[above right=+1.5cm and 2cm of cluster, label=above:matix] (matix)
|
||||
{\includegraphics[width=1.2cm]{server}};
|
||||
\node[right=0.3cm of matix, label=above:N310] (n310a)
|
||||
{\includegraphics[width=1.5cm]{n310}} edge (matix);
|
||||
@@ -41,22 +41,9 @@
|
||||
\node[above right=-0.1cm and 0.35cm of b77o.east] (anto2)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (b77o);
|
||||
|
||||
\node[below right=-0.6cm and 2cm of porcepix, label=above:obelix] (obelix)
|
||||
\node[below right=-0.4cm and 2cm of cluster, label=above:cacofonix] (cacofonix)
|
||||
{\includegraphics[width=1.2cm]{server}}
|
||||
edge (porcepix);
|
||||
\node[right=0.3cm of obelix, label=above:N310] (n310o)
|
||||
{\includegraphics[width=1.5cm]{n310}} edge (obelix);
|
||||
\node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o);
|
||||
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
|
||||
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
|
||||
|
||||
\node[below=2cm of porcepix, label=above:Cluster] (cluster)
|
||||
{\includegraphics[width=1.2cm]{server}};
|
||||
\node[right=2cm of cluster, label=above:cacofonix] (cacofonix)
|
||||
{\includegraphics[width=1.2cm]{server}}
|
||||
edge (cluster);
|
||||
edge (cluster);
|
||||
\node[right=0.3cm of cacofonix, label=above:VVDN, draw,
|
||||
minimum width=1.7cm, minimum height=0.8cm] (vvdn)
|
||||
{O-RU} edge (cacofonix);
|
||||
@@ -69,7 +56,28 @@
|
||||
\node[above right=+0.45cm and 0.35cm of vvdn.east] (antv4)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (vvdn.east);
|
||||
|
||||
\node[above right=+0.0cm and 5.0cm of n310o.east, label=above:RM520N-GL] (quectel)
|
||||
\node[below=2cm of cluster, label=above:porcepix] (porcepix)
|
||||
{\includegraphics[width=1.2cm]{server}};
|
||||
\node[right=2cm of porcepix, label=above:obelix] (obelix)
|
||||
{\includegraphics[width=1.2cm]{server}}
|
||||
edge (porcepix);
|
||||
\node[right=0.3cm of obelix, label=above:N310] (n310o)
|
||||
{\includegraphics[width=1.5cm]{n310}} edge (obelix);
|
||||
\node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o);
|
||||
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
|
||||
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
|
||||
|
||||
%\node[right=0.3cm of cacofonix, label=above:N310] (n310o)
|
||||
% {\includegraphics[width=1.5cm]{n310}} edge (cacofonix);
|
||||
\node[right=.2cm of n310o, duplexer] (b78o) {n40} edge (n310o);
|
||||
\node[below right=-0.1cm and 0.35cm of b78o.east] (anto1)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
|
||||
\node[above right=-0.1cm and 0.35cm of b78o.east] (anto2)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (b78o);
|
||||
|
||||
\node[above right=+0.0cm and 5.0cm of vvdn.east, label=above:RM520N-GL] (quectel)
|
||||
{\includegraphics[height=1.2cm]{quectel}};
|
||||
\node[above left=-0.1cm and 0.8cm of quectel.west] (aq2)
|
||||
{\includegraphics[width=0.3cm]{antenna}} edge (quectel);
|
||||
|
||||
@@ -464,23 +464,14 @@ int start_L1L2(module_id_t gnb_id)
|
||||
|
||||
NR_BCCH_BCH_Message_t *mib = mac->common_channels[0].mib;
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1 = mac->common_channels[0].sib1;
|
||||
|
||||
/* update existing config in F1 Setup request structures */
|
||||
f1ap_setup_req_t *sr = mac->f1_config.setup_req;
|
||||
DevAssert(sr->num_cells_available == 1);
|
||||
f1ap_served_cell_info_t *info = &sr->cell[0].info;
|
||||
DevAssert(info->mode == F1AP_MODE_TDD);
|
||||
/* update existing config in F1 Setup request structures */
|
||||
DevAssert(scc->tdd_UL_DL_ConfigurationCommon != NULL);
|
||||
info->tdd = read_tdd_config(scc); /* updates radio config */
|
||||
/* send gNB-DU configuration update to RRC */
|
||||
f1ap_gnb_du_configuration_update_t update = {
|
||||
.transaction_id = 1,
|
||||
.num_cells_to_modify = 1,
|
||||
};
|
||||
update.cell_to_modify[0].old_nr_cellid = info->nr_cellid;
|
||||
update.cell_to_modify[0].info = *info;
|
||||
update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1);
|
||||
mac->mac_rrc.gnb_du_configuration_update(&update);
|
||||
prepare_du_configuration_update(mac, info, mib, sib1);
|
||||
|
||||
init_NR_RU(config_get_if(), NULL);
|
||||
|
||||
|
||||
+33
-23
@@ -41,6 +41,7 @@
|
||||
#include "instrumentation.h"
|
||||
#include "common/utils/threadPool/notified_fifo.h"
|
||||
#include "position_interface.h"
|
||||
#include "nr_phy_common.h"
|
||||
|
||||
/*
|
||||
* NR SLOT PROCESSING SEQUENCE
|
||||
@@ -104,7 +105,9 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
|
||||
static void start_process_slot_tx(void* arg) {
|
||||
notifiedFIFO_elt_t *newTx = arg;
|
||||
nr_rxtx_thread_data_t *curMsgTx = NotifiedFifoData(newTx);
|
||||
pushNotifiedFIFO(&curMsgTx->UE->ul_actor.fifo, newTx);
|
||||
int num_ul_actors_to_use =
|
||||
get_nrUE_params()->num_ul_actors == 0 ? NUM_UL_ACTORS : min(get_nrUE_params()->num_ul_actors, NUM_UL_ACTORS);
|
||||
pushNotifiedFIFO(&curMsgTx->UE->ul_actors[curMsgTx->proc.nr_slot_tx % num_ul_actors_to_use].fifo, newTx);
|
||||
}
|
||||
|
||||
static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len)
|
||||
@@ -436,9 +439,13 @@ static void UE_synch(void *arg) {
|
||||
((ret.rx_offset << 1) / fp->samples_per_subframe * fp->slots_per_subframe)
|
||||
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
|
||||
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
// todo: the freq_offset computed on DL shall be scaled before being applied to UL
|
||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
|
||||
if (get_nrUE_params()->cont_fo_comp) {
|
||||
UE->freq_offset = freq_offset;
|
||||
} else {
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
|
||||
}
|
||||
|
||||
if (get_nrUE_params()->agc) {
|
||||
nr_ue_adjust_rx_gain(UE, cfg0, UE->adjust_rxgain);
|
||||
@@ -452,7 +459,6 @@ static void UE_synch(void *arg) {
|
||||
cfg0->rx_freq[0],
|
||||
cfg0->tx_freq[0]);
|
||||
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
|
||||
UE->is_synchronized = 1;
|
||||
} else {
|
||||
int gain_change = 0;
|
||||
@@ -551,6 +557,15 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action)
|
||||
writeBlockSize -= dummyBlockSize;
|
||||
}
|
||||
|
||||
// pre-compensate UL frequency offset
|
||||
if (flags != TX_BURST_INVALID && get_nrUE_params()->cont_fo_comp) {
|
||||
double ul_freq_offset = -UE->freq_offset * ((double)fp->ul_CarrierFreq / (double)fp->dl_CarrierFreq);
|
||||
if (get_nrUE_params()->cont_fo_comp == 2) // different from LO frequency error compensation, Doppler UL pre-compensation has to be negative
|
||||
ul_freq_offset = -ul_freq_offset;
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
nr_fo_compensation(ul_freq_offset, fp->samples_per_subframe, writeTimestamp, txp[i], writeBlockSize);
|
||||
}
|
||||
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, txp, writeBlockSize, fp->nb_antennas_tx, flags);
|
||||
AssertFatal(tmp == writeBlockSize, "");
|
||||
}
|
||||
@@ -585,6 +600,7 @@ void processSlotTX(void *arg)
|
||||
UE->if_inst->sl_indication(&sl_indication);
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
dynamic_barrier_join(rxtxD->next_barrier);
|
||||
|
||||
if (phy_data.sl_tx_action) {
|
||||
|
||||
@@ -611,12 +627,14 @@ void processSlotTX(void *arg)
|
||||
UE->if_inst->ul_indication(&ul_indication);
|
||||
stop_meas(&UE->ue_ul_indication_stats);
|
||||
}
|
||||
dynamic_barrier_join(rxtxD->next_barrier);
|
||||
|
||||
phy_procedures_nrUE_TX(UE, proc, &phy_data);
|
||||
}
|
||||
} else {
|
||||
dynamic_barrier_join(rxtxD->next_barrier);
|
||||
}
|
||||
RU_write(rxtxD, sl_tx_action);
|
||||
dynamic_barrier_join(rxtxD->next_barrier);
|
||||
TracyCZoneEnd(ctx);
|
||||
}
|
||||
|
||||
@@ -656,7 +674,9 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
||||
for (int i = 0; i < NUM_DL_ACTORS; i++) {
|
||||
flush_actor(UE->dl_actors + i);
|
||||
}
|
||||
flush_actor(&UE->ul_actor);
|
||||
for (int i = 0; i < NUM_UL_ACTORS; i++) {
|
||||
flush_actor(UE->ul_actors + i);
|
||||
}
|
||||
|
||||
clean_UE_harq(UE);
|
||||
UE->is_synchronized = 0;
|
||||
@@ -861,13 +881,12 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
|
||||
NR_DL_FRAME_PARMS *fp,
|
||||
int slot_nr,
|
||||
bool *update_ntn_system_information,
|
||||
int *duration_rx_to_tx,
|
||||
int *timing_advance,
|
||||
int *ntn_koffset)
|
||||
{
|
||||
if (*update_ntn_system_information) {
|
||||
*update_ntn_system_information = false;
|
||||
if (UE->ntn_config_message->update) {
|
||||
UE->ntn_config_message->update = false;
|
||||
|
||||
double total_ta_ms = UE->ntn_config_message->ntn_config_params.ntn_total_time_advance_ms;
|
||||
UE->timing_advance = fp->samples_per_subframe * total_ta_ms;
|
||||
@@ -913,6 +932,8 @@ void *UE_thread(void *arg)
|
||||
if (usrp_tx_thread == 1)
|
||||
UE->rfdevice.trx_write_init(&UE->rfdevice);
|
||||
|
||||
InitSinLUT();
|
||||
|
||||
notifiedFIFO_t nf;
|
||||
initNotifiedFIFO(&nf);
|
||||
|
||||
@@ -947,13 +968,9 @@ void *UE_thread(void *arg)
|
||||
|
||||
double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
|
||||
int ntn_koffset = 0;
|
||||
|
||||
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
|
||||
int nr_slot_tx_offset = 0;
|
||||
bool update_ntn_system_information = false;
|
||||
|
||||
while (!oai_exit) {
|
||||
nr_slot_tx_offset = 0;
|
||||
if (syncRunning) {
|
||||
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
|
||||
|
||||
@@ -1078,12 +1095,6 @@ void *UE_thread(void *arg)
|
||||
absolute_slot++;
|
||||
TracyCFrameMark;
|
||||
|
||||
if (UE->ntn_config_message->update) {
|
||||
UE->ntn_config_message->update = false;
|
||||
update_ntn_system_information = true;
|
||||
nr_slot_tx_offset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset << fp->numerology_index;
|
||||
}
|
||||
|
||||
int slot_nr = absolute_slot % nb_slot_frame;
|
||||
nr_rxtx_thread_data_t curMsg = {0};
|
||||
curMsg.UE=UE;
|
||||
@@ -1173,8 +1184,8 @@ void *UE_thread(void *arg)
|
||||
shiftForNextFrame = ret;
|
||||
pushNotifiedFIFO(&UE->dl_actors[curMsg.proc.nr_slot_rx % NUM_DL_ACTORS].fifo, newRx);
|
||||
|
||||
// apply new duration next run to avoid thread dead lock
|
||||
apply_ntn_config(UE, fp, slot_nr, &update_ntn_system_information, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
|
||||
// apply new NTN timing information
|
||||
apply_ntn_config(UE, fp, slot_nr, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
|
||||
|
||||
// Start TX slot processing here. It runs in parallel with RX slot processing
|
||||
// in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot
|
||||
@@ -1185,7 +1196,6 @@ void *UE_thread(void *arg)
|
||||
curMsgTx->writeBlockSize = writeBlockSize;
|
||||
curMsgTx->proc.timestamp_tx = writeTimestamp;
|
||||
curMsgTx->UE = UE;
|
||||
curMsgTx->proc.nr_slot_tx_offset = nr_slot_tx_offset;
|
||||
|
||||
int slot = curMsgTx->proc.nr_slot_tx;
|
||||
int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame;
|
||||
|
||||
@@ -224,6 +224,8 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
UE->chest_freq = nrUE_params.chest_freq;
|
||||
UE->chest_time = nrUE_params.chest_time;
|
||||
UE->no_timing_correction = nrUE_params.no_timing_correction;
|
||||
UE->initial_fo = nrUE_params.initial_fo;
|
||||
UE->cont_fo_comp = nrUE_params.cont_fo_comp;
|
||||
|
||||
LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
|
||||
UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time);
|
||||
@@ -508,7 +510,9 @@ int main(int argc, char **argv)
|
||||
for (int i = 0; i < NUM_DL_ACTORS; i++) {
|
||||
init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1);
|
||||
}
|
||||
init_actor(&UE[CC_id]->ul_actor, "UL_", -1);
|
||||
for (int i = 0; i < NUM_UL_ACTORS; i++) {
|
||||
init_actor(&UE[CC_id]->ul_actors[i], "UL_", -1);
|
||||
}
|
||||
init_nr_ue_vars(UE[CC_id], inst);
|
||||
|
||||
if (UE[CC_id]->sl_mode) {
|
||||
@@ -578,7 +582,9 @@ int main(int argc, char **argv)
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id];
|
||||
if (phy_vars) {
|
||||
shutdown_actor(&phy_vars->ul_actor);
|
||||
for (int i = 0; i < NUM_UL_ACTORS; i++) {
|
||||
shutdown_actor(&phy_vars->ul_actors[i]);
|
||||
}
|
||||
for (int i = 0; i < NUM_DL_ACTORS; i++) {
|
||||
shutdown_actor(&phy_vars->dl_actors[i]);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,12 @@
|
||||
#define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n"
|
||||
#define CONFIG_HLP_NTN_INIT_TIME_DRIFT "Initial NTN DL time drift (feeder link and service link), given in µs/s\n"
|
||||
#define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n"
|
||||
#define CONFIG_HLP_INITIAL_FO "Initially compensated DL frequency offset (e.g. known Doppler shift in NTN LEO scenario)\n"
|
||||
#define CONFIG_HLP_FREQ_SYNC_P "coefficient for Proportional part of continuous frequency offset compensation PI controller\n"
|
||||
#define CONFIG_HLP_FREQ_SYNC_I "coefficient for Integrating part of continuous frequency offset compensation PI controller\n"
|
||||
#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift)\n"
|
||||
#define CONFIG_HLP_AGC "Rx Gain control used for UE\n"
|
||||
#define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to use the default value\n"
|
||||
|
||||
/***************************************************************************************************************************************/
|
||||
/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument
|
||||
@@ -65,7 +70,12 @@
|
||||
{"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
{"ntn-initial-time-drift", CONFIG_HLP_NTN_INIT_TIME_DRIFT, 0, .dblptr=&(nrUE_params.ntn_init_time_drift), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
{"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \
|
||||
{"initial-fo", CONFIG_HLP_INITIAL_FO, 0, .dblptr=&(nrUE_params.initial_fo), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
{"freq-sync-P", CONFIG_HLP_FREQ_SYNC_P, 0, .dblptr=&(nrUE_params.freq_sync_P), .defdblval=0.01, TYPE_DOUBLE, 0}, \
|
||||
{"freq-sync-I", CONFIG_HLP_FREQ_SYNC_I, 0, .dblptr=&(nrUE_params.freq_sync_I), .defdblval=0.001, TYPE_DOUBLE, 0}, \
|
||||
{"cont-fo-comp", CONFIG_HLP_CONT_FO_COMP, 0, .iptr=&(nrUE_params.cont_fo_comp), .defintval=0, TYPE_INT, 0}, \
|
||||
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \
|
||||
{"num-ul-actors", CONFIG_HLP_NUM_UL_ACTORS, 0, .iptr=&nrUE_params.num_ul_actors, .defintval=0, TYPE_INT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -89,6 +99,10 @@ typedef struct {
|
||||
double time_sync_I;
|
||||
double ntn_init_time_drift;
|
||||
int autonomous_ta;
|
||||
double initial_fo;
|
||||
double freq_sync_P;
|
||||
double freq_sync_I;
|
||||
int cont_fo_comp;
|
||||
int agc;
|
||||
char *usrp_args;
|
||||
char *tx_subdev;
|
||||
@@ -101,6 +115,7 @@ typedef struct {
|
||||
double rx_gain_off;
|
||||
int vcdflag;
|
||||
int tx_max_power;
|
||||
int num_ul_actors;
|
||||
} nrUE_params_t;
|
||||
extern uint64_t get_nrUE_optmask(void);
|
||||
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
|
||||
|
||||
@@ -171,7 +171,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
NR_DL_FRAME_PARMS *const fp = &ue->frame_parms;
|
||||
NR_UE_COMMON *const common_vars = &ue->common_vars;
|
||||
NR_UE_PRACH **const prach_vars = ue->prach_vars;
|
||||
NR_UE_SRS **const srs_vars = ue->srs_vars;
|
||||
|
||||
LOG_I(PHY, "Initializing UE vars for gNB TXant %u, UE RXant %u\n", fp->nb_antennas_tx, fp->nb_antennas_rx);
|
||||
|
||||
@@ -257,8 +256,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
// DLSCH
|
||||
for (int gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) {
|
||||
prach_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_PRACH));
|
||||
srs_vars[gNB_id] = malloc16_clear(sizeof(NR_UE_SRS));
|
||||
srs_vars[gNB_id]->active = false;
|
||||
|
||||
// ceil((NB_RB*8(max allocation per RB)*2(QPSK))/32)
|
||||
ue->nr_csi_info = malloc16_clear(sizeof(nr_csi_info_t));
|
||||
@@ -318,8 +315,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
|
||||
|
||||
free_and_zero(ue->nr_srs_info);
|
||||
|
||||
free_and_zero(ue->srs_vars[gNB_id]);
|
||||
|
||||
free_and_zero(ue->prach_vars[gNB_id]);
|
||||
}
|
||||
|
||||
@@ -487,7 +482,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE)
|
||||
for (int harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) {
|
||||
NR_UL_UE_HARQ_t *ul_harq_process = &UE->ul_harq_processes[harq_pid];
|
||||
ul_harq_process->tx_status = NEW_TRANSMISSION_HARQ;
|
||||
ul_harq_process->ULstatus = SCH_IDLE;
|
||||
ul_harq_process->round = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "nr_modulation.h"
|
||||
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
|
||||
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
|
||||
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
|
||||
#include <common/utils/LOG/log.h>
|
||||
|
||||
//#define DEBUG_FEP
|
||||
@@ -108,6 +109,12 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
rxdata_ptr = (int16_t *)tmp_dft_in;
|
||||
}
|
||||
|
||||
if (ue && ue->cont_fo_comp) {
|
||||
start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
|
||||
nr_fo_compensation(ue->freq_offset, frame_parms->samples_per_subframe, rx_offset, (c16_t *)rxdata_ptr, frame_parms->ofdm_symbol_size);
|
||||
stop_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
|
||||
}
|
||||
|
||||
if (ue)
|
||||
start_meas_nr_ue_phy(ue, RX_DFT_STATS);
|
||||
|
||||
|
||||
@@ -730,7 +730,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
#endif
|
||||
}
|
||||
uint32_t dmrs_idx = rel15->rbStart;
|
||||
if (rel15->rnti != SI_RNTI)
|
||||
if (rel15->refPoint == 0)
|
||||
dmrs_idx += rel15->BWPStart;
|
||||
dmrs_idx *= dmrs_Type == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
|
||||
c16_t txdataF_precoding[rel15->nrOfLayers][symbol_sz] __attribute__((aligned(64)));
|
||||
|
||||
@@ -47,7 +47,7 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN);
|
||||
|
||||
// search for maximum position within the cyclic prefix
|
||||
for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) {
|
||||
for (int i = -frame_parms->nb_prefix_samples; i < frame_parms->nb_prefix_samples; i++) {
|
||||
int temp = 0;
|
||||
|
||||
int j = (i < 0) ? (i + frame_parms->ofdm_symbol_size) : i;
|
||||
|
||||
@@ -640,6 +640,9 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
{
|
||||
int e_rx_cand_idx = 0;
|
||||
*dci_ind = (fapi_nr_dci_indication_t){.SFN = proc->frame_rx, .slot = proc->nr_slot_rx};
|
||||
// if DCI for SIB we don't break after finding 1st DCI with that RNTI
|
||||
// there might be SIB1 and otherSIB in the same slot with the same length
|
||||
bool is_SI = rel15->rnti == SI_RNTI;
|
||||
|
||||
for (int j = 0; j < rel15->number_of_candidates; j++) {
|
||||
int CCEind = rel15->CCE[j];
|
||||
@@ -653,7 +656,7 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
|
||||
int dci_length = rel15->dci_length_options[k];
|
||||
int ind;
|
||||
for (ind = 0; ind < dci_ind->number_of_dcis; ind++) {
|
||||
if (rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) {
|
||||
if (!is_SI && rel15->rnti == dci_ind->dci_list[ind].rnti && dci_length == dci_ind->dci_list[ind].payloadSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,10 +766,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
for (int a = 0; a < nbRx; a++) {
|
||||
int offset = (void *)rxdataF_comp[0][a] - (void *)rxdataF_comp[0] + symbol * rx_size_symbol * sizeof(c16_t);
|
||||
memcpy(ue->phy_sim_pdsch_rxdataF_comp + offset, rxdataF_comp[0][a] + symbol * rx_size_symbol, sizeof(c16_t) * rx_size_symbol);
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates + offset, dl_ch_estimates, pdsch_est_size * sizeof(c16_t));
|
||||
memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates + pdsch_est_size * a, dl_ch_estimates, pdsch_est_size * sizeof(c16_t));
|
||||
}
|
||||
if (ue->phy_sim_pdsch_dl_ch_estimates_ext)
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol, dl_ch_estimates_ext, sizeof(dl_ch_estimates_ext));
|
||||
memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol,
|
||||
dl_ch_estimates_ext,
|
||||
sizeof(dl_ch_estimates_ext));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -199,6 +199,9 @@ void nr_scan_ssb(void *arg)
|
||||
// initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame
|
||||
// only one frame is used for simulation tools
|
||||
for (int frame_id = 0; frame_id < ssbInfo->nFrames && !ssbInfo->syncRes.cell_detected; frame_id++) {
|
||||
if (ssbInfo->freqOffset)
|
||||
compensate_freq_offset(rxdata, fp, ssbInfo->freqOffset, frame_id);
|
||||
|
||||
/* process pss search on received buffer */
|
||||
ssbInfo->syncRes.frame_id = frame_id;
|
||||
int nid2;
|
||||
@@ -268,7 +271,7 @@ void nr_scan_ssb(void *arg)
|
||||
phase_tdd_ncp,
|
||||
ssbInfo->syncRes.rx_offset);
|
||||
#endif
|
||||
ssbInfo->freqOffset = freq_offset_pss + freq_offset_sss;
|
||||
ssbInfo->freqOffset += freq_offset_pss + freq_offset_sss;
|
||||
|
||||
if (ssbInfo->syncRes.cell_detected) { // we got sss channel
|
||||
ssbInfo->syncRes.cell_detected = nr_pbch_detection(ssbInfo->proc,
|
||||
@@ -319,6 +322,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
.syncRes.cell_detected = false,
|
||||
.nFrames = n_frames,
|
||||
.foFlag = ue->UE_fo_compensation,
|
||||
.freqOffset = ue->initial_fo,
|
||||
.targetNidCell = ue->target_Nid_cell};
|
||||
ssbInfo->rxdata = malloc16_clear(fp->nb_antennas_rx * sizeof(c16_t *));
|
||||
for (int ant = 0; ant < fp->nb_antennas_rx; ant++) {
|
||||
|
||||
@@ -525,3 +525,21 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
TracyCZoneEnd(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
int estimateSz,
|
||||
const c16_t dl_ch_estimates[][estimateSz])
|
||||
{
|
||||
const int i_ssb = frame_parms->ssb_index;
|
||||
const int symbol_offset = nr_get_ssb_start_symbol(frame_parms, i_ssb) % frame_parms->symbols_per_slot;
|
||||
const c16_t *dl_ch_est_symb1 = &dl_ch_estimates[0][(symbol_offset + 1) * frame_parms->ofdm_symbol_size];
|
||||
const c16_t *dl_ch_est_symb3 = &dl_ch_estimates[0][(symbol_offset + 3) * frame_parms->ofdm_symbol_size];
|
||||
const int nb_re = 240;
|
||||
const c32_t dot_prod_res = dot_product(dl_ch_est_symb1, dl_ch_est_symb3, nb_re, 8);
|
||||
const double res_phase = atan2(dot_prod_res.i, dot_prod_res.r);
|
||||
const int samples_per_symbol = frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples;
|
||||
const double t_ofdm = samples_per_symbol / (frame_parms->samples_per_subframe * 1000.0); // symbol duration in sec
|
||||
const double freq_offset = res_phase / (2 * M_PI * (3 - 1) * t_ofdm);
|
||||
|
||||
return freq_offset;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
|
||||
int Ncp = 0;
|
||||
int prach_start, prach_sequence_length, prach_len, dftlen, mu, n_ra_prb, k, prachStartSymbol, sample_offset_slot;
|
||||
|
||||
fd_occasion = 0;
|
||||
fd_occasion = prach_pdu->num_ra;
|
||||
prach_len = 0;
|
||||
dftlen = 0;
|
||||
first_nonzero_root_idx = 0;
|
||||
|
||||
@@ -204,6 +204,10 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
int rxdataFSize,
|
||||
const struct complex16 rxdataF[][rxdataFSize]);
|
||||
|
||||
double nr_ue_pbch_freq_offset(const NR_DL_FRAME_PARMS *frame_parms,
|
||||
int estimateSz,
|
||||
const c16_t dl_ch_estimates[][estimateSz]);
|
||||
|
||||
#ifndef modOrder
|
||||
#define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS
|
||||
#endif
|
||||
|
||||
@@ -46,8 +46,6 @@ typedef enum {
|
||||
typedef struct {
|
||||
/// HARQ tx status
|
||||
harq_result_t tx_status;
|
||||
/// Status Flag indicating for this ULSCH (idle,active,disabled)
|
||||
SCH_status_t ULstatus;
|
||||
/// Last TPC command
|
||||
uint8_t TPC;
|
||||
/// Length of ACK information (bits)
|
||||
@@ -87,6 +85,7 @@ typedef struct {
|
||||
} NR_UL_UE_HARQ_t;
|
||||
|
||||
typedef struct {
|
||||
SCH_status_t status;
|
||||
/// NDAPI struct for UE
|
||||
nfapi_nr_ue_pusch_pdu_t pusch_pdu;
|
||||
// UL number of harq processes
|
||||
|
||||
@@ -471,7 +471,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
||||
|
||||
if (UE->ul_harq_processes[harq_pid].ULstatus != ACTIVE)
|
||||
if (phy_data->ulsch.status != ACTIVE)
|
||||
return;
|
||||
|
||||
start_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
|
||||
@@ -542,8 +542,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
/////////////////////////ULSCH coding/////////////////////////
|
||||
|
||||
if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) {
|
||||
NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
|
||||
harq_process_ulsch->ULstatus = SCH_IDLE;
|
||||
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
|
||||
return;
|
||||
}
|
||||
@@ -820,12 +818,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
} // symbol loop
|
||||
} // port loop
|
||||
|
||||
NR_UL_UE_HARQ_t *harq_process_ulsch = NULL;
|
||||
harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
|
||||
harq_process_ulsch->ULstatus = SCH_IDLE;
|
||||
|
||||
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
|
||||
|
||||
}
|
||||
|
||||
uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
@@ -426,14 +426,15 @@ int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
|
||||
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
c16_t **txdataF,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT])
|
||||
{
|
||||
if(!ue->srs_vars[0]->active) {
|
||||
if(phy_data->srs_vars.active == false) {
|
||||
return -1;
|
||||
}
|
||||
ue->srs_vars[0]->active = false;
|
||||
|
||||
nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t*)&ue->srs_vars[0]->srs_config_pdu;
|
||||
// TODO: This is wrong: casting from UE fapi to gNB NFAPI srs pdu
|
||||
nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t *)&phy_data->srs_vars.srs_config_pdu;
|
||||
|
||||
int first_srs_symbol = ue->frame_parms.symbols_per_slot - 1 - srs_config_pdu->time_start_position;
|
||||
// Num consecutive SRS symbols according to 38.211 6.4.1.4.1
|
||||
|
||||
@@ -78,7 +78,10 @@ int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource,
|
||||
@param rxtx context
|
||||
@param current gNB_id identifier
|
||||
@returns 0 if srs is transmitted -1 otherwise */
|
||||
|
||||
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF, bool was_symbol_used[14]);
|
||||
int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
c16_t **txdataF,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]);
|
||||
|
||||
#endif /* SRS_MODULATION_NR_H */
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "tools_defs.h"
|
||||
|
||||
#define LUT_SIN_RESOL 128
|
||||
// look-up table for the sine (cosine) function
|
||||
static uint16_t LUTSin[LUT_SIN_RESOL + 1];
|
||||
|
||||
void InitSinLUT(void)
|
||||
{
|
||||
for (int i = 0; i < (LUT_SIN_RESOL + 1); i++) {
|
||||
LUTSin[i] = round(sin((M_PI * i) / (2 * LUT_SIN_RESOL)) * (1 << 14)); // Format: Q14
|
||||
}
|
||||
}
|
||||
|
||||
// fast calculation of e^{i*2*pi*phase}
|
||||
// ret.r == cosinus << 14
|
||||
// ret.i == sinus << 14
|
||||
c16_t get_sin_cos(double phase)
|
||||
{
|
||||
int index;
|
||||
if (phase < 0) {
|
||||
index = (int)(-phase * 4 * LUT_SIN_RESOL + 0.5) % (4 * LUT_SIN_RESOL);
|
||||
index = 4 * LUT_SIN_RESOL - index;
|
||||
} else {
|
||||
index = (int)(phase * 4 * LUT_SIN_RESOL + 0.5) % (4 * LUT_SIN_RESOL);
|
||||
}
|
||||
|
||||
c16_t ret;
|
||||
if (index < 2 * LUT_SIN_RESOL) { // check for 1st and 2nd Quadrant
|
||||
if (index < LUT_SIN_RESOL) { // 1st Quadrant
|
||||
ret.r = LUTSin[LUT_SIN_RESOL - index];
|
||||
ret.i = LUTSin[index];
|
||||
} else { // 2nd Quadrant
|
||||
ret.r = -LUTSin[index - LUT_SIN_RESOL];
|
||||
ret.i = LUTSin[2 * LUT_SIN_RESOL - index];
|
||||
}
|
||||
} else { // 3rd and 4th Quadrant
|
||||
if (index < 3 * LUT_SIN_RESOL) { // 3rd Quadrant
|
||||
ret.r = -LUTSin[3 * LUT_SIN_RESOL - index];
|
||||
ret.i = -LUTSin[index - 2 * LUT_SIN_RESOL];
|
||||
} else { // 4th Quadrant
|
||||
ret.r = LUTSin[index - 3 * LUT_SIN_RESOL];
|
||||
ret.i = -LUTSin[4 * LUT_SIN_RESOL - index];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -792,6 +792,13 @@ double interp(double x, double *xs, double *ys, int count);
|
||||
void simde_mm128_separate_real_imag_parts(simde__m128i *out_re, simde__m128i *out_im, simde__m128i in0, simde__m128i in1);
|
||||
void simde_mm256_separate_real_imag_parts(simde__m256i *out_re, simde__m256i *out_im, simde__m256i in0, simde__m256i in1);
|
||||
|
||||
void InitSinLUT(void);
|
||||
|
||||
// fast calculation of e^{i*2*pi*phase}
|
||||
// ret.r == cosinus << 14
|
||||
// ret.i == sinus << 14
|
||||
c16_t get_sin_cos(double phase);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
/// suppress compiler warning for unused arguments
|
||||
#define UNUSED(x) (void)x;
|
||||
#define NUM_DL_ACTORS 4
|
||||
#define NUM_UL_ACTORS 2
|
||||
|
||||
// Set the number of barriers for processSlotTX to 512. This value has to be at least 483 for NTN where
|
||||
// DL-to-UL offset is up to 483. The selected value is also half of the frame range so that
|
||||
@@ -401,7 +402,6 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
nr_synch_request_t synch_request;
|
||||
|
||||
NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_SRS *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
|
||||
NR_UE_PRS *prs_vars[NR_MAX_PRS_COMB_SIZE];
|
||||
uint8_t prs_active_gNBs;
|
||||
NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES];
|
||||
@@ -460,6 +460,11 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
int64_t max_pos_iir; /// Timing offset IIR filter
|
||||
int max_pos_acc; /// Timing offset accumuluated error for PI filter
|
||||
|
||||
double initial_fo; /// initial frequency offset provided by the user
|
||||
int cont_fo_comp; /// flag enabling the continuous frequency offset estimation and compensation
|
||||
double freq_offset; /// currently compensated frequency offset
|
||||
double freq_off_acc; /// accumulated frequency error (for PI controller)
|
||||
|
||||
/// Timing Advance updates variables
|
||||
/// Timing advance update computed from the TA command signalled from gNB
|
||||
int timing_advance;
|
||||
@@ -514,7 +519,7 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
sl_nr_ue_phy_params_t SL_UE_PHY_PARAMS;
|
||||
Actor_t sync_actor;
|
||||
Actor_t dl_actors[NUM_DL_ACTORS];
|
||||
Actor_t ul_actor;
|
||||
Actor_t ul_actors[NUM_UL_ACTORS];
|
||||
ntn_config_message_t* ntn_config_message;
|
||||
pthread_t main_thread;
|
||||
pthread_t stat_thread;
|
||||
@@ -525,10 +530,6 @@ typedef struct {
|
||||
int gNB_id;
|
||||
/// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission
|
||||
int nr_slot_tx;
|
||||
/// NR slot index tx offset to resume
|
||||
/// in case of NTN, tx_offset can be changed dynamically via SIB19
|
||||
/// we need to notify the right tx thread slot based on TX offset change
|
||||
int nr_slot_tx_offset;
|
||||
int rx_slot_type;
|
||||
/// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission
|
||||
int nr_slot_rx;
|
||||
@@ -571,6 +572,7 @@ typedef struct {
|
||||
typedef struct nr_phy_data_tx_s {
|
||||
NR_UE_ULSCH_t ulsch;
|
||||
NR_UE_PUCCH pucch_vars;
|
||||
NR_UE_SRS srs_vars;
|
||||
|
||||
// Sidelink Rx action decided by MAC
|
||||
sl_nr_tx_config_type_enum_t sl_tx_action;
|
||||
@@ -597,7 +599,7 @@ typedef struct nr_rxtx_thread_data_s {
|
||||
PHY_VARS_NR_UE *UE;
|
||||
int writeBlockSize;
|
||||
nr_phy_data_t phy_data;
|
||||
dynamic_barrier_t *next_barrier;
|
||||
dynamic_barrier_t* next_barrier;
|
||||
} nr_rxtx_thread_data_t;
|
||||
|
||||
typedef struct LDPCDecode_ue_s {
|
||||
|
||||
@@ -80,4 +80,6 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int
|
||||
void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal);
|
||||
void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay);
|
||||
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb);
|
||||
void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define FOREACH_NR_PHY_CPU_MEAS(FN) \
|
||||
FN(RX_PDSCH_STATS),\
|
||||
FN(DLSCH_RX_PDCCH_STATS),\
|
||||
FN(RX_FO_COMPENSATION_STATS),\
|
||||
FN(RX_DFT_STATS),\
|
||||
FN(DLSCH_CHANNEL_ESTIMATION_STATS),\
|
||||
FN(DLSCH_DECODING_STATS),\
|
||||
|
||||
@@ -453,3 +453,40 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, in
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size)
|
||||
{
|
||||
const double phase_inc = -fo_Hz / (samples_per_ms * 1000);
|
||||
double phase = sample_offset * phase_inc;
|
||||
phase -= (int)phase;
|
||||
#if 1
|
||||
// The bottleneck is the calculation of the complex rotation values using get_sin_cos().
|
||||
// This code path does not compute these values for the complete OFDM symbol, but only for a smaller CHUNK size.
|
||||
// After applying the rotation to a CHUNK size of the output, these rotation values are efficiently rotated further by `rot_vec`.
|
||||
// Unfortunately, this propagates small errors from one chunk to the next.
|
||||
// Therefore, there is a tradeoff between speed (better with small CHUNK sizes) and accuracy (better with large CHUNK sizes).
|
||||
#define CHUNK 128
|
||||
c16_t rot[CHUNK] __attribute__((aligned(32)));
|
||||
for (int i = 0; i < CHUNK; i++) {
|
||||
rot[i] = get_sin_cos(phase);
|
||||
phase += phase_inc;
|
||||
}
|
||||
const c16_t rot_vec = get_sin_cos(CHUNK * phase_inc);
|
||||
while (size > CHUNK) {
|
||||
mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, CHUNK, 14);
|
||||
rxdata_ptr += CHUNK;
|
||||
rotate_cpx_vector(rot, &rot_vec, rot, CHUNK, 14);
|
||||
size -= CHUNK;
|
||||
}
|
||||
mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, size, 14);
|
||||
#else
|
||||
// This code path computes the complex rotation values for the complete OFDM symbol using get_sin_cos().
|
||||
// This is more accurate, but also slower than the code path above.
|
||||
c16_t rot[size] __attribute__((aligned(32)));
|
||||
for (int i = 0; i < size; i++) {
|
||||
rot[i] = get_sin_cos(phase);
|
||||
phase += phase_inc;
|
||||
}
|
||||
mult_complex_vectors(rxdata_ptr, rot, rxdata_ptr, size, 14);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -518,7 +518,7 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r
|
||||
pdu->pusch_config_pdu.tx_request_body.pdu_length);
|
||||
}
|
||||
|
||||
harq_process_ul_ue->ULstatus = ACTIVE;
|
||||
phy_data->ulsch.status = ACTIVE;
|
||||
pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
|
||||
} break;
|
||||
|
||||
@@ -549,8 +549,8 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r
|
||||
|
||||
case FAPI_NR_UL_CONFIG_TYPE_SRS:
|
||||
// srs config pdu
|
||||
phy->srs_vars[0]->srs_config_pdu = pdu->srs_config_pdu;
|
||||
phy->srs_vars[0]->active = true;
|
||||
phy_data->srs_vars.srs_config_pdu = pdu->srs_config_pdu;
|
||||
phy_data->srs_vars.active = true;
|
||||
pdu->pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
|
||||
break;
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
|
||||
|
||||
nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used);
|
||||
|
||||
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, was_symbol_used);
|
||||
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, phy_data, was_symbol_used);
|
||||
|
||||
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used);
|
||||
|
||||
@@ -929,6 +929,17 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_
|
||||
sampleShift =
|
||||
nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384);
|
||||
}
|
||||
|
||||
if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) {
|
||||
double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates);
|
||||
LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz, accumulated frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset, ue->freq_off_acc);
|
||||
|
||||
// PI controller
|
||||
const double PID_P = get_nrUE_params()->freq_sync_P;
|
||||
const double PID_I = get_nrUE_params()->freq_sync_I;
|
||||
ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I;
|
||||
ue->freq_off_acc += freq_offset;
|
||||
}
|
||||
}
|
||||
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
|
||||
nr_ue_rrc_measurements(ue, proc, rxdataF);
|
||||
|
||||
@@ -958,6 +958,13 @@ printf("%d\n", slot);
|
||||
fprintf(csv_file,"avg_round,eff_rate,eff_throughput,TBS\n");
|
||||
}
|
||||
//---------------
|
||||
|
||||
Sched_INFO = malloc(sizeof(*Sched_INFO));
|
||||
if (Sched_INFO == NULL) {
|
||||
LOG_E(PHY, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (SNR = snr0; SNR < snr1 && !stop; SNR += .2) {
|
||||
|
||||
varArray_t *table_tx=initVarArray(1000,sizeof(double));
|
||||
@@ -988,6 +995,9 @@ printf("%d\n", slot);
|
||||
n_false_positive = 0;
|
||||
if (n_trials== 1) num_rounds = 1;
|
||||
|
||||
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
for (trial = 0; trial < n_trials && !stop; trial++) {
|
||||
|
||||
errors_bit = 0;
|
||||
@@ -1003,19 +1013,11 @@ printf("%d\n", slot);
|
||||
int harq_pid = slot;
|
||||
NR_DL_UE_HARQ_t *UE_harq_process = &UE->dl_harq_processes[0][harq_pid];
|
||||
|
||||
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
UE_harq_process->decodeResult = false;
|
||||
round = 0;
|
||||
UE_harq_process->DLround = round;
|
||||
UE_harq_process->first_rx = 1;
|
||||
|
||||
Sched_INFO = malloc(sizeof(*Sched_INFO));
|
||||
if (Sched_INFO == NULL) {
|
||||
LOG_E(PHY, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
memset(Sched_INFO, 0, sizeof(*Sched_INFO));
|
||||
Sched_INFO->sched_response_id = -1;
|
||||
|
||||
@@ -1109,10 +1111,10 @@ printf("%d\n", slot);
|
||||
sprintf(filename,"txsig%d.m", aa);//LOG_M
|
||||
LOG_M(filename,"txs", &txdata[aa][slot_offset +frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1);
|
||||
}
|
||||
}
|
||||
if (output_fd) {
|
||||
printf("writing txdata to binary file\n");
|
||||
fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
|
||||
if (output_fd) {
|
||||
printf("writing txdata to binary file\n");
|
||||
fwrite(txdata[0], sizeof(int32_t), frame_length_complex_samples, output_fd);
|
||||
}
|
||||
}
|
||||
|
||||
int txlev[n_tx];
|
||||
@@ -1296,15 +1298,38 @@ printf("%d\n", slot);
|
||||
}
|
||||
|
||||
if (n_trials == 1) {
|
||||
unsigned int op_format = 1;
|
||||
unsigned int dec = 1;
|
||||
if (output_fd) { // Write in bin format
|
||||
op_format |= MATLAB_RAW;
|
||||
}
|
||||
|
||||
LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1);
|
||||
LOG_M("rxsig0.m", "rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, dec, op_format);
|
||||
if (UE->frame_parms.nb_antennas_rx>1)
|
||||
LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1);
|
||||
LOG_M("rxF0.m","rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, 1, 1);
|
||||
LOG_M("rxF_ext.m","rxFe",UE->phy_sim_pdsch_rxdataF_ext,g_rbSize*12*14,1,1);
|
||||
LOG_M("chestF0.m","chF0",UE->phy_sim_pdsch_dl_ch_estimates_ext,g_rbSize*12*14,1,1);
|
||||
write_output("rxF_comp.m","rxFc",UE->phy_sim_pdsch_rxdataF_comp,N_RB_DL*12*14,1,1);
|
||||
LOG_M("rxF_llr.m","rxFllr",UE->phy_sim_pdsch_llr,available_bits,1,0);
|
||||
LOG_M("rxsig1.m", "rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, dec, op_format);
|
||||
LOG_M("rxF0.m", "rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, dec, op_format);
|
||||
LOG_M("rxF_ext.m", "rxFe", UE->phy_sim_pdsch_rxdataF_ext, g_rbSize * 12 * 14, dec, op_format);
|
||||
const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15);
|
||||
const uint32_t numValidReSym = g_rbSize * 12;
|
||||
{
|
||||
const int s = rel15->StartSymbolIndex;
|
||||
const int n = rel15->NrOfSymbols;
|
||||
for (int i = s; i < s + n; i++) {
|
||||
char fName[50];
|
||||
snprintf(fName, sizeof(fName), "chestF0_ext_s%d.m", i);
|
||||
LOG_M(fName,
|
||||
"chF0_ext",
|
||||
((c16_t *)UE->phy_sim_pdsch_dl_ch_estimates_ext) + (i * numReSym),
|
||||
numValidReSym,
|
||||
dec,
|
||||
op_format);
|
||||
snprintf(fName, sizeof(fName), "rxF_comp_s%d.m", i);
|
||||
LOG_M(fName, "rxFc", ((c16_t *)UE->phy_sim_pdsch_rxdataF_comp) + (i * numReSym), numValidReSym, dec, op_format);
|
||||
}
|
||||
}
|
||||
LOG_M("chestF0.m", "chF0", UE->phy_sim_pdsch_dl_ch_estimates, frame_parms->ofdm_symbol_size * 14, dec, op_format);
|
||||
op_format = (op_format & (~1));
|
||||
LOG_M("rxF_llr.m", "rxFllr", UE->phy_sim_pdsch_llr, available_bits, dec, op_format);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1316,6 +1341,8 @@ printf("%d\n", slot);
|
||||
n_errs = n_errors[0];
|
||||
} // NSR
|
||||
|
||||
free(Sched_INFO);
|
||||
|
||||
free_channel_desc_scm(gNB2UE);
|
||||
|
||||
for (i = 0; i < n_tx; i++) {
|
||||
|
||||
@@ -239,6 +239,7 @@ int main(int argc, char *argv[])
|
||||
int threadCnt=0;
|
||||
int max_ldpc_iterations = 5;
|
||||
int num_antennas_per_thread = 1;
|
||||
uint32_t log_format = 0;
|
||||
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
|
||||
exit_fun("[NR_ULSIM] Error, configuration module init failed\n");
|
||||
}
|
||||
@@ -250,8 +251,7 @@ int main(int argc, char *argv[])
|
||||
InitSinLUT();
|
||||
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:k:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) {
|
||||
|
||||
while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:jk:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) {
|
||||
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
|
||||
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
|
||||
if (c == 1 || c == '-' || c == 'O')
|
||||
@@ -345,7 +345,11 @@ int main(int argc, char *argv[])
|
||||
i+=2;
|
||||
} while (optarg[i-1] == ',');
|
||||
break;
|
||||
|
||||
|
||||
case 'j':
|
||||
log_format |= MATLAB_RAW;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
printf("Setting threequarter_fs_flag\n");
|
||||
openair0_cfg[0].threequarter_fs= 1;
|
||||
@@ -523,6 +527,7 @@ int main(int argc, char *argv[])
|
||||
printf("-g Channel model configuration. Arguments list: Number of arguments = 3, {Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300}, {Correlation: [l] Low, [m] Medium, [h] High}, {Maximum Doppler shift} e.g. -g A,l,10\n");
|
||||
printf("-h This message\n");
|
||||
printf("-i Change channel estimation technique. Arguments list: Number of arguments=2, Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}. e.g. -i 1,0\n");
|
||||
printf("-j Save signal buffers in binary format.");
|
||||
printf("-k 3/4 sampling\n");
|
||||
printf("-m MCS value\n");
|
||||
printf("-n Number of trials to simulate\n");
|
||||
@@ -559,7 +564,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logInit();
|
||||
set_glog(loglvl);
|
||||
|
||||
@@ -1214,12 +1219,12 @@ int main(int argc, char *argv[])
|
||||
phy_procedures_nrUE_TX(UE, &UE_proc, &phy_data);
|
||||
|
||||
if (n_trials == 1) {
|
||||
LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1 | log_format);
|
||||
if (precod_nbr_layers > 1) {
|
||||
LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1);
|
||||
if (precod_nbr_layers == 4) {
|
||||
LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1 | log_format);
|
||||
if (precod_nbr_layers == 4) {
|
||||
LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1 | log_format);
|
||||
LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1 | log_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1293,16 +1298,16 @@ int main(int argc, char *argv[])
|
||||
ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot, &UL_INFO);
|
||||
|
||||
if (n_trials == 1 && round == 0) {
|
||||
LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1 | log_format);
|
||||
LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
if (precod_nbr_layers > 1) {
|
||||
LOG_M("rxsig1.m", "rx1", &rxdata[1][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
if (precod_nbr_layers == 4) {
|
||||
LOG_M("rxsig2.m", "rx2", &rxdata[2][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsig3.m", "rx3", &rxdata[3][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1316,71 +1321,69 @@ int main(int argc, char *argv[])
|
||||
&pusch_vars->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
LOG_M("rxsigF0_comp.m",
|
||||
"rxsF0_comp",
|
||||
&pusch_vars->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
if (precod_nbr_layers == 2) {
|
||||
|
||||
LOG_M("chestF3.m",
|
||||
"chF3",
|
||||
&pusch_vars->ul_ch_estimates[3][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
LOG_M("rxsigF2_comp.m",
|
||||
"rxsF2_comp",
|
||||
&pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
}
|
||||
|
||||
if (precod_nbr_layers == 4) {
|
||||
|
||||
LOG_M("chestF5.m",
|
||||
"chF5",
|
||||
&pusch_vars->ul_ch_estimates[5][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("chestF10.m",
|
||||
"chF10",
|
||||
&pusch_vars->ul_ch_estimates[10][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("chestF15.m",
|
||||
"chF15",
|
||||
&pusch_vars->ul_ch_estimates[15][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
LOG_M("rxsigF4_comp.m",
|
||||
"rxsF4_comp",
|
||||
&pusch_vars->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("rxsigF8_comp.m",
|
||||
"rxsF8_comp",
|
||||
&pusch_vars->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("rxsigF12_comp.m",
|
||||
"rxsF12_comp",
|
||||
&pusch_vars->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
}
|
||||
|
||||
LOG_M("rxsigF0_llr.m",
|
||||
@@ -1388,7 +1391,7 @@ int main(int argc, char *argv[])
|
||||
&pusch_vars->llr[0],
|
||||
precod_nbr_layers * (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order,
|
||||
1,
|
||||
0);
|
||||
0 | log_format);
|
||||
}
|
||||
|
||||
if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) {
|
||||
|
||||
@@ -143,31 +143,6 @@ void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *des
|
||||
|
||||
#else
|
||||
|
||||
void add_noise(c16_t **rxdata,
|
||||
const double **r_re,
|
||||
const double **r_im,
|
||||
const double sigma,
|
||||
const int length,
|
||||
const int slot_offset,
|
||||
const double ts,
|
||||
const int delay,
|
||||
const uint16_t pdu_bit_map,
|
||||
const uint16_t ptrs_bit_map,
|
||||
const uint8_t nb_antennas_rx)
|
||||
{
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int ap = 0; ap < nb_antennas_rx; ap++) {
|
||||
c16_t *rxd = &rxdata[ap][slot_offset + i + delay];
|
||||
rxd->r = r_re[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); // convert to fixed point
|
||||
rxd->i = r_im[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0);
|
||||
/* Add phase noise if enabled */
|
||||
if (pdu_bit_map & ptrs_bit_map) {
|
||||
phase_noise(ts, &rxdata[ap][slot_offset + i + delay].r, &rxdata[ap][slot_offset + i + delay].i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *desc,
|
||||
double *tx_sig_re[NB_ANTENNAS_TX],
|
||||
double *tx_sig_im[NB_ANTENNAS_TX],
|
||||
|
||||
@@ -23,47 +23,41 @@
|
||||
#include "sim.h"
|
||||
|
||||
|
||||
static uint16_t LUTSin[ResolSinCos+1];
|
||||
/* linear phase noise model */
|
||||
void phase_noise(double ts, int16_t * InRe, int16_t * InIm)
|
||||
void phase_noise(double ts, int16_t *InRe, int16_t *InIm)
|
||||
{
|
||||
static uint64_t i=0;
|
||||
int32_t x=0 ,y=0;
|
||||
double fd = 300;//0.01*30000
|
||||
int16_t SinValue = 0, CosValue= 0;
|
||||
double IdxDouble = (double)(i*fd * ts * ResolSinCos * 4);
|
||||
int16_t IdxModulo = ((int32_t)(IdxDouble>0 ? IdxDouble+0.5 : IdxDouble-0.5)) % (ResolSinCos*4);
|
||||
IdxModulo = IdxModulo<0 ? IdxModulo+ResolSinCos*4 : IdxModulo;
|
||||
|
||||
if(IdxModulo<2*ResolSinCos) {//< 2 check for 1st and 2nd
|
||||
if(IdxModulo < ResolSinCos) {// 1st Quadrant
|
||||
SinValue = LUTSin[IdxModulo];
|
||||
CosValue = LUTSin[ResolSinCos-IdxModulo];
|
||||
}
|
||||
else {// 2nd Quadrant
|
||||
SinValue = LUTSin[2*ResolSinCos-IdxModulo];
|
||||
CosValue = -LUTSin[IdxModulo-ResolSinCos];
|
||||
}
|
||||
}
|
||||
else {// 3rd and 4th Quadrant
|
||||
if(IdxModulo < 3*ResolSinCos) {// 3rd Quadrant
|
||||
SinValue = -LUTSin[IdxModulo-2*ResolSinCos];
|
||||
CosValue = -LUTSin[3*ResolSinCos-IdxModulo];
|
||||
}
|
||||
else {//4th Quadrant
|
||||
SinValue = -LUTSin[4*ResolSinCos-IdxModulo];
|
||||
CosValue = LUTSin[IdxModulo-3*ResolSinCos];
|
||||
}
|
||||
}
|
||||
x = ( ((int32_t)InRe[0] * CosValue) - ((int32_t)InIm[0] * SinValue ));
|
||||
y = ( ((int32_t)InIm[0] * CosValue) + ((int32_t)InRe[0] * SinValue ));
|
||||
InRe[0]= (int16_t)(x>>14);
|
||||
InIm[0]= (int16_t)(y>>14);
|
||||
double phase = (double)(i * fd * ts);
|
||||
c16_t rot = get_sin_cos(phase);
|
||||
c16_t val = {.r = *InRe, .i = *InIm};
|
||||
val = c16mulShift(val, rot, 14);
|
||||
*InRe = val.r;
|
||||
*InIm = val.i;
|
||||
i++;
|
||||
}
|
||||
/* Initialisation function for SIN table values */
|
||||
void InitSinLUT( void ) {
|
||||
for ( int i=0; i<(ResolSinCos+1); i++ ) {
|
||||
LUTSin[i] = sin((double)(M_PI*i)/(2*ResolSinCos)) * (1<<14); //Format: Q14
|
||||
|
||||
void add_noise(c16_t **rxdata,
|
||||
const double **r_re,
|
||||
const double **r_im,
|
||||
const double sigma,
|
||||
const int length,
|
||||
const int slot_offset,
|
||||
const double ts,
|
||||
const int delay,
|
||||
const uint16_t pdu_bit_map,
|
||||
const uint16_t ptrs_bit_map,
|
||||
const uint8_t nb_antennas_rx)
|
||||
{
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int ap = 0; ap < nb_antennas_rx; ap++) {
|
||||
c16_t *rxd = &rxdata[ap][slot_offset + i + delay];
|
||||
rxd->r = r_re[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0); // convert to fixed point
|
||||
rxd->i = r_im[ap][i] + sqrt(sigma / 2) * gaussZiggurat(0.0, 1.0);
|
||||
/* Add phase noise if enabled */
|
||||
if (pdu_bit_map & ptrs_bit_map) {
|
||||
phase_noise(ts, &rxdata[ap][slot_offset + i + delay].r, &rxdata[ap][slot_offset + i + delay].i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1663,7 +1663,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
maxDoppler = 0;
|
||||
chan_desc->sat_height = 600e3;
|
||||
chan_desc->enable_dynamic_delay = true;
|
||||
chan_desc->enable_dynamic_Doppler = false; // TODO: requires UE to support continuous Doppler estimation, compensation and pre-compensation
|
||||
chan_desc->enable_dynamic_Doppler = true;
|
||||
fill_channel_desc(chan_desc,nb_tx,
|
||||
nb_rx,
|
||||
nb_taps,
|
||||
@@ -1762,6 +1762,11 @@ void set_channeldesc_name(channel_desc_t *cdesc,char *modelname) {
|
||||
cdesc->model_name=strdup(modelname);
|
||||
}
|
||||
|
||||
void set_channeldesc_direction(channel_desc_t *cdesc, bool is_uplink)
|
||||
{
|
||||
cdesc->is_uplink = is_uplink;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CH_POWER
|
||||
double accumulated_ch_power = 0;
|
||||
int ch_power_count = 0;
|
||||
|
||||
@@ -139,6 +139,8 @@ typedef struct {
|
||||
float Doppler_phase_inc;
|
||||
/// current Doppler phase of each RX antenna (for continuous phase from one block to the next)
|
||||
float *Doppler_phase_cur;
|
||||
/// flag indicating if channel direction is UL or DL
|
||||
bool is_uplink;
|
||||
} channel_desc_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -358,6 +360,7 @@ void free_channel_desc_scm(channel_desc_t *ch);
|
||||
\param module_id identifies the channel model. should be define as a macro in simu.h
|
||||
*/
|
||||
void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id);
|
||||
|
||||
/**
|
||||
\brief This function set a model name to a model descriptor, can be later used to identify a allocated channel model
|
||||
\param cdesc points to the model descriptor
|
||||
@@ -365,6 +368,13 @@ void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_i
|
||||
*/
|
||||
void set_channeldesc_name(channel_desc_t *cdesc,char *modelname);
|
||||
|
||||
/**
|
||||
\brief This function set a channel model direction to either uplink or downlink
|
||||
\param cdesc points to the model descriptor
|
||||
\param is_uplink indicates if this channel is applied in uplink (not downlink) direction
|
||||
*/
|
||||
void set_channeldesc_direction(channel_desc_t *cdesc, bool is_uplink);
|
||||
|
||||
/** \fn void get_cexp_doppler(struct complexd *cexp_doppler, channel_desc_t *chan_desc, const uint32_t length)
|
||||
\brief This routine generates the complex exponential to apply the Doppler shift
|
||||
\param cexp_doppler Output with the complex exponential of Doppler shift
|
||||
@@ -379,32 +389,6 @@ void get_cexp_doppler(struct complexd *cexp_doppler, channel_desc_t *chan_desc,
|
||||
*/
|
||||
int random_channel(channel_desc_t *desc, uint8_t abstraction_flag);
|
||||
|
||||
/**
|
||||
\brief Add AWGN noise and phase noise if enabled
|
||||
\param rxdata output data with noise
|
||||
\param r_re real part of input data without noise
|
||||
\param r_im imaginary part of input data without noise
|
||||
\param sigma noise power
|
||||
\param length number of samples to apply the noise
|
||||
\param slot_offset slot offset to start applying the noise
|
||||
\param ts sampling time
|
||||
\param delay introduce delay in terms of number of samples
|
||||
\param pdu_bit_map bitmap indicating presence of optional PDUs
|
||||
\param ptrs_bit_map
|
||||
\param nb_antennas_rx number of receive antennas
|
||||
*/
|
||||
void add_noise(c16_t **rxdata,
|
||||
const double **r_re,
|
||||
const double **r_im,
|
||||
const double sigma,
|
||||
const int length,
|
||||
const int slot_offset,
|
||||
const double ts,
|
||||
const int delay,
|
||||
const uint16_t pdu_bit_map,
|
||||
const uint16_t ptrs_bit_map,
|
||||
const uint8_t nb_antennas_rx);
|
||||
|
||||
/**\fn void multipath_channel(channel_desc_t *desc,
|
||||
double tx_sig_re[NB_ANTENNAS_TX],
|
||||
double tx_sig_im[NB_ANTENANS_TX],
|
||||
@@ -570,16 +554,38 @@ double N_RB2sampling_rate(uint16_t N_RB);
|
||||
double N_RB2channel_bandwidth(uint16_t N_RB);
|
||||
|
||||
/* Linear phase noise model */
|
||||
/*!
|
||||
/**
|
||||
\brief This function produce phase noise and add to input signal
|
||||
\param ts Sampling time
|
||||
\param ts Sampling time
|
||||
\param *Re *Im Real and Imag part of the signal
|
||||
*/
|
||||
//look-up table for the sine (cosine) function
|
||||
#define ResolSinCos 100
|
||||
void InitSinLUT( void );
|
||||
void phase_noise(double ts, int16_t * InRe, int16_t * InIm);
|
||||
void phase_noise(double ts, int16_t *InRe, int16_t *InIm);
|
||||
|
||||
/**
|
||||
\brief Add AWGN noise and phase noise if enabled
|
||||
\param rxdata output data with noise
|
||||
\param r_re real part of input data without noise
|
||||
\param r_im imaginary part of input data without noise
|
||||
\param sigma noise power
|
||||
\param length number of samples to apply the noise
|
||||
\param slot_offset slot offset to start applying the noise
|
||||
\param ts sampling time
|
||||
\param delay introduce delay in terms of number of samples
|
||||
\param pdu_bit_map bitmap indicating presence of optional PDUs
|
||||
\param ptrs_bit_map
|
||||
\param nb_antennas_rx number of receive antennas
|
||||
*/
|
||||
void add_noise(c16_t **rxdata,
|
||||
const double **r_re,
|
||||
const double **r_im,
|
||||
const double sigma,
|
||||
const int length,
|
||||
const int slot_offset,
|
||||
const double ts,
|
||||
const int delay,
|
||||
const uint16_t pdu_bit_map,
|
||||
const uint16_t ptrs_bit_map,
|
||||
const uint8_t nb_antennas_rx);
|
||||
|
||||
void do_DL_sig(sim_t *sim,
|
||||
uint16_t subframe,
|
||||
|
||||
@@ -9,10 +9,11 @@ else()
|
||||
message(FATAL_ERROR "unknown E1AP_RELEASE ${E1AP_RELEASE}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${e1ap_source} ${e1ap_headers}
|
||||
COMMAND ASN1C_PREFIX=E1AP_ ${ASN1C_EXEC} -gen-APER -gen-UPER -no-gen-JER -no-gen-BER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}
|
||||
COMMENT "Generating E1AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}"
|
||||
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${E1AP_GRAMMAR}
|
||||
"E1AP_"
|
||||
OUTPUT ${e1ap_source} ${e1ap_headers}
|
||||
OPTIONS -gen-APER -gen-UPER -no-gen-JER -no-gen-BER -no-gen-OER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps
|
||||
COMMENT "E1AP source files"
|
||||
)
|
||||
|
||||
add_library(asn1_e1ap ${e1ap_source})
|
||||
|
||||
@@ -8,10 +8,11 @@ else()
|
||||
message(FATAL_ERROR "unknown F1AP_RELEASE ${F1AP_RELEASE}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${f1ap_source} ${f1ap_headers}
|
||||
COMMAND ASN1C_PREFIX=F1AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}
|
||||
COMMENT "Generating F1AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}"
|
||||
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${F1AP_GRAMMAR}
|
||||
"F1AP_"
|
||||
OUTPUT ${f1ap_source} ${f1ap_headers}
|
||||
OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -findirect-choice -fno-include-deps
|
||||
COMMENT "F1AP source files"
|
||||
)
|
||||
|
||||
add_library(asn1_f1ap ${f1ap_source})
|
||||
|
||||
@@ -653,11 +653,9 @@ static void encode_cells_to_activate(const served_cells_to_activate_t *cell, F1A
|
||||
&cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation;
|
||||
const f1ap_sib_msg_t *SI_msg = &cell->SI_msg[n];
|
||||
if (SI_msg->SI_container != NULL) {
|
||||
if (SI_msg->SI_type > 6 && SI_msg->SI_type != 9) {
|
||||
asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item);
|
||||
sib_item->sIBtype = SI_msg->SI_type;
|
||||
OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length);
|
||||
}
|
||||
asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item);
|
||||
sib_item->sIBtype = SI_msg->SI_type;
|
||||
OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1221,7 +1219,7 @@ f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg)
|
||||
const f1ap_sib_msg_t *b_SI_msg = &msg_cell->SI_msg[j];
|
||||
cp_SI_msg->SI_container_length = b_SI_msg->SI_container_length;
|
||||
cp_SI_msg->SI_container = malloc_or_fail(cp_SI_msg->SI_container_length);
|
||||
*cp_SI_msg->SI_container = *b_SI_msg->SI_container;
|
||||
memcpy(cp_SI_msg->SI_container, b_SI_msg->SI_container, b_SI_msg->SI_container_length);
|
||||
cp_SI_msg->SI_type = b_SI_msg->SI_type;
|
||||
}
|
||||
}
|
||||
@@ -2109,8 +2107,12 @@ f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_a
|
||||
for (int i = 0; i < cp.num_cells_to_activate; i++) {
|
||||
cp.cells_to_activate[i] = msg->cells_to_activate[i];
|
||||
for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) {
|
||||
cp.cells_to_activate[i].SI_msg[s].SI_container = calloc_or_fail(1, sizeof(*cp.cells_to_activate[i].SI_msg[s].SI_container));
|
||||
*cp.cells_to_activate[i].SI_msg[s].SI_container = *msg->cells_to_activate[i].SI_msg[s].SI_container;
|
||||
f1ap_sib_msg_t *cp_sib = &cp.cells_to_activate[i].SI_msg[s];
|
||||
const f1ap_sib_msg_t *msg_sib = &msg->cells_to_activate[i].SI_msg[s];
|
||||
cp_sib->SI_type = msg_sib->SI_type;
|
||||
cp_sib->SI_container_length = msg_sib->SI_container_length;
|
||||
cp_sib->SI_container = calloc_or_fail(cp_sib->SI_container_length, sizeof(*cp_sib->SI_container));
|
||||
memcpy(cp_sib->SI_container, msg_sib->SI_container, cp_sib->SI_container_length);
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
|
||||
@@ -63,14 +63,15 @@
|
||||
#define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres"
|
||||
#define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper"
|
||||
#define CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER "dl_bler_target_lower"
|
||||
#define CONFIG_STRING_MACRLC_DL_MIN_MCS "dl_min_mcs"
|
||||
#define CONFIG_STRING_MACRLC_DL_MAX_MCS "dl_max_mcs"
|
||||
#define CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER "ul_bler_target_upper"
|
||||
#define CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER "ul_bler_target_lower"
|
||||
#define CONFIG_STRING_MACRLC_UL_MIN_MCS "ul_min_mcs"
|
||||
#define CONFIG_STRING_MACRLC_UL_MAX_MCS "ul_max_mcs"
|
||||
#define CONFIG_STRING_MACRLC_DL_HARQ_ROUND_MAX "dl_harq_round_max"
|
||||
#define CONFIG_STRING_MACRLC_UL_HARQ_ROUND_MAX "ul_harq_round_max"
|
||||
#define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb"
|
||||
#define CONFIG_STRING_MACRLC_MIN_GRANT_MCS "min_grant_mcs"
|
||||
#define CONFIG_STRING_MACRLC_IDENTITY_PM "identity_precoding_matrix"
|
||||
#define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming"
|
||||
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
|
||||
@@ -81,14 +82,15 @@
|
||||
#define HLP_MACRLC_UL_PRBBLACK "SNR threshold to decide whether a PRB will be blacklisted or not"
|
||||
#define HLP_MACRLC_DL_BLER_UP "Upper threshold of BLER to decrease DL MCS"
|
||||
#define HLP_MACRLC_DL_BLER_LO "Lower threshold of BLER to increase DL MCS"
|
||||
#define HLP_MACRLC_DL_MIN_MCS "Minimum DL MCS that should be used"
|
||||
#define HLP_MACRLC_DL_MAX_MCS "Maximum DL MCS that should be used"
|
||||
#define HLP_MACRLC_UL_BLER_UP "Upper threshold of BLER to decrease UL MCS"
|
||||
#define HLP_MACRLC_UL_BLER_LO "Lower threshold of BLER to increase UL MCS"
|
||||
#define HLP_MACRLC_UL_MIN_MCS "Minimum UL MCS that should be used"
|
||||
#define HLP_MACRLC_UL_MAX_MCS "Maximum UL MCS that should be used"
|
||||
#define HLP_MACRLC_DL_HARQ_MAX "Maximum number of DL HARQ rounds"
|
||||
#define HLP_MACRLC_UL_HARQ_MAX "Maximum number of UL HARQ rounds"
|
||||
#define HLP_MACRLC_MIN_GRANT_PRB "Minimal Periodic ULSCH Grant PRBs"
|
||||
#define HLP_MACRLC_MIN_GRANT_MCS "Minimal Periodic ULSCH Grant MCS"
|
||||
#define HLP_MACRLC_IDENTITY_PM "Flag to use only identity matrix in DL precoding"
|
||||
#define HLP_MACRLC_AB "Flag to enable analog beamforming"
|
||||
#define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams"
|
||||
@@ -125,14 +127,15 @@
|
||||
{CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, .iptr=NULL, .defintval=10, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, HLP_MACRLC_DL_BLER_UP, 0, .dblptr=NULL, .defdblval=0.15, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_MACRLC_DL_BLER_TARGET_LOWER, HLP_MACRLC_DL_BLER_LO, 0, .dblptr=NULL, .defdblval=0.05, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_MACRLC_DL_MIN_MCS, HLP_MACRLC_DL_MIN_MCS, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_DL_MAX_MCS, HLP_MACRLC_DL_MAX_MCS, 0, .u8ptr=NULL, .defintval=28, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_UL_BLER_TARGET_UPPER, HLP_MACRLC_UL_BLER_UP, 0, .dblptr=NULL, .defdblval=0.15, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_MACRLC_UL_BLER_TARGET_LOWER, HLP_MACRLC_UL_BLER_LO, 0, .dblptr=NULL, .defdblval=0.05, TYPE_DOUBLE, 0}, \
|
||||
{CONFIG_STRING_MACRLC_UL_MIN_MCS, HLP_MACRLC_UL_MIN_MCS, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_UL_MAX_MCS, HLP_MACRLC_UL_MAX_MCS, 0, .u8ptr=NULL, .defintval=28, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_DL_HARQ_ROUND_MAX, HLP_MACRLC_DL_HARQ_MAX, 0, .u8ptr=NULL, .defintval=4, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_UL_HARQ_ROUND_MAX, HLP_MACRLC_UL_HARQ_MAX, 0, .u8ptr=NULL, .defintval=4, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_MIN_GRANT_PRB, HLP_MACRLC_MIN_GRANT_PRB, 0, .u8ptr=NULL, .defintval=5, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_MIN_GRANT_MCS, HLP_MACRLC_MIN_GRANT_MCS, 0, .u8ptr=NULL, .defintval=9, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_IDENTITY_PM, HLP_MACRLC_IDENTITY_PM, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \
|
||||
@@ -170,23 +173,24 @@
|
||||
#define MACRLC_PUSCHFAILURETHRES_IDX 20
|
||||
#define MACRLC_DL_BLER_TARGET_UPPER_IDX 21
|
||||
#define MACRLC_DL_BLER_TARGET_LOWER_IDX 22
|
||||
#define MACRLC_DL_MAX_MCS_IDX 23
|
||||
#define MACRLC_UL_BLER_TARGET_UPPER_IDX 24
|
||||
#define MACRLC_UL_BLER_TARGET_LOWER_IDX 25
|
||||
#define MACRLC_UL_MAX_MCS_IDX 26
|
||||
#define MACRLC_DL_HARQ_ROUND_MAX_IDX 27
|
||||
#define MACRLC_UL_HARQ_ROUND_MAX_IDX 28
|
||||
#define MACRLC_MIN_GRANT_PRB_IDX 29
|
||||
#define MACRLC_MIN_GRANT_MCS_IDX 30
|
||||
#define MACRLC_IDENTITY_PM_IDX 31
|
||||
#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 32
|
||||
#define MACRLC_TRANSPORT_S_SHM_PREFIX 33
|
||||
#define MACRLC_TRANSPORT_S_POLL_CORE 34
|
||||
#define MACRLC_ANALOG_BEAMFORMING_IDX 35
|
||||
#define MACRLC_ANALOG_BEAM_DURATION_IDX 36
|
||||
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 37
|
||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 38
|
||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 39
|
||||
#define MACRLC_DL_MIN_MCS_IDX 23
|
||||
#define MACRLC_DL_MAX_MCS_IDX 24
|
||||
#define MACRLC_UL_BLER_TARGET_UPPER_IDX 25
|
||||
#define MACRLC_UL_BLER_TARGET_LOWER_IDX 26
|
||||
#define MACRLC_UL_MIN_MCS_IDX 27
|
||||
#define MACRLC_UL_MAX_MCS_IDX 28
|
||||
#define MACRLC_DL_HARQ_ROUND_MAX_IDX 29
|
||||
#define MACRLC_UL_HARQ_ROUND_MAX_IDX 30
|
||||
#define MACRLC_MIN_GRANT_PRB_IDX 31
|
||||
#define MACRLC_IDENTITY_PM_IDX 32
|
||||
#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 33
|
||||
#define MACRLC_TRANSPORT_S_SHM_PREFIX 34
|
||||
#define MACRLC_TRANSPORT_S_POLL_CORE 35
|
||||
#define MACRLC_ANALOG_BEAMFORMING_IDX 36
|
||||
#define MACRLC_ANALOG_BEAM_DURATION_IDX 37
|
||||
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 38
|
||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 39
|
||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 40
|
||||
|
||||
#define MACRLCPARAMS_CHECK { \
|
||||
{ .s5 = { NULL } }, \
|
||||
@@ -212,14 +216,15 @@
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s2 = { config_check_intrange, {0, 31} } }, /* DL min MCS */ \
|
||||
{ .s2 = { config_check_intrange, {0, 31} } }, /* DL max MCS */ \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s2 = { config_check_intrange, {0, 31} } }, /* UL min MCS */ \
|
||||
{ .s2 = { config_check_intrange, {0, 31} } }, /* UL max MCS */ \
|
||||
{ .s2 = { config_check_intrange, {1, 8} } }, /* DL max HARQ rounds */ \
|
||||
{ .s2 = { config_check_intrange, {1, 8} } }, /* UL max HARQ rounds */ \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s2 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
|
||||
@@ -1141,7 +1141,7 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf
|
||||
css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1;
|
||||
} else {
|
||||
css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0;
|
||||
css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1;
|
||||
css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2;
|
||||
css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0;
|
||||
}
|
||||
css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0;
|
||||
@@ -1312,7 +1312,7 @@ static f1ap_fdd_info_t read_fdd_config(const NR_ServingCellConfigCommon_t *scc)
|
||||
return fdd;
|
||||
}
|
||||
|
||||
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1)
|
||||
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1, seq_arr_t *du_SIBs)
|
||||
{
|
||||
int buf_len = 3;
|
||||
f1ap_gnb_du_system_info_t *sys_info = calloc_or_fail(1, sizeof(*sys_info));
|
||||
@@ -1329,15 +1329,24 @@ f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCC
|
||||
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
|
||||
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
|
||||
|
||||
if (du_SIBs) {
|
||||
for (int i = 0; i < du_SIBs->size; i++) {
|
||||
nr_SIBs_t *si = (nr_SIBs_t *)seq_arr_at(du_SIBs, i);
|
||||
// other SIB in gNB-DU System Information not implemented yet
|
||||
// only DU SIB not included in this message is SIB19
|
||||
AssertFatal(si->SIB_type == 19, "Cannot handle SIB%d in gNB-DU System Information\n", si->SIB_type);
|
||||
}
|
||||
}
|
||||
return sys_info;
|
||||
}
|
||||
|
||||
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
const char *name,
|
||||
const f1ap_served_cell_info_t *info,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_BCCH_BCH_Message_t *mib,
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1)
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1,
|
||||
seq_arr_t *du_SIBs)
|
||||
{
|
||||
f1ap_setup_req_t *req = calloc(1, sizeof(*req));
|
||||
AssertFatal(req != NULL, "out of memory\n");
|
||||
@@ -1381,7 +1390,7 @@ f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
if (IS_SA_MODE(get_softmodem_params())) {
|
||||
// in NSA we don't transmit SIB1, so cannot fill DU system information
|
||||
// so cannot send MIB either
|
||||
req->cell[0].sys_info = get_sys_info(mib, sib1);
|
||||
req->cell[0].sys_info = get_sys_info(mib, sib1, du_SIBs);
|
||||
}
|
||||
|
||||
int num = read_version(TO_STRING(NR_RRC_VERSION), &req->rrc_ver[0], &req->rrc_ver[1], &req->rrc_ver[2]);
|
||||
@@ -1421,6 +1430,31 @@ static nr_redcap_config_t *get_redcap_config(int gnb_idx)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray)
|
||||
{
|
||||
if (NODE_IS_DU(get_node_type()))
|
||||
AssertFatal(GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0, "This is DU, do not input CU SIBs\n");
|
||||
|
||||
if (!config_isparamset(GNBparamarray, GNB_DU_SIBS_IDX))
|
||||
return NULL;
|
||||
|
||||
seq_arr_t *du_SIBs = malloc(sizeof(seq_arr_t));
|
||||
seq_arr_init(du_SIBs, sizeof(nr_SIBs_t));
|
||||
for (int i = 0; i < GNBparamarray[GNB_DU_SIBS_IDX].numelt; i++) {
|
||||
int sib_value = GNBparamarray[GNB_DU_SIBS_IDX].iptr[i];
|
||||
// SIB10, SIB12, SIB13, SIB14, SIB15, SIB17, SIB18, SIB19 and SIB20 are generated by the DU
|
||||
// all the rest in the DU
|
||||
AssertFatal((sib_value > 9 && sib_value < 21) && sib_value != 11 && sib_value != 16,
|
||||
"SIB%d is not a DU SIB, to be configured in DU section\n",
|
||||
sib_value);
|
||||
nr_SIBs_t *du_sib = calloc_or_fail(1, sizeof(nr_SIBs_t));
|
||||
du_sib->SIB_type = sib_value;
|
||||
LOG_I(GNB_APP, "activate SIB%d at DU\n", sib_value);
|
||||
seq_arr_push_back(du_SIBs, du_sib, sizeof(nr_SIBs_t));
|
||||
}
|
||||
return du_SIBs;
|
||||
}
|
||||
|
||||
void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
{
|
||||
int j = 0;
|
||||
@@ -1650,6 +1684,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler;
|
||||
dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr);
|
||||
dl_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr);
|
||||
dl_bler_options->min_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MIN_MCS_IDX].u8ptr);
|
||||
dl_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr);
|
||||
if (config.disable_harq)
|
||||
dl_bler_options->harq_round_max = 1;
|
||||
@@ -1658,13 +1693,13 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
NR_bler_options_t *ul_bler_options = &RC.nrmac[j]->ul_bler;
|
||||
ul_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_UPPER_IDX].dblptr);
|
||||
ul_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_LOWER_IDX].dblptr);
|
||||
ul_bler_options->min_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MIN_MCS_IDX].u8ptr);
|
||||
ul_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MAX_MCS_IDX].u8ptr);
|
||||
if (config.disable_harq)
|
||||
ul_bler_options->harq_round_max = 1;
|
||||
else
|
||||
ul_bler_options->harq_round_max = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_HARQ_ROUND_MAX_IDX].u8ptr);
|
||||
RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr);
|
||||
RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr);
|
||||
RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr);
|
||||
// PRB Blacklist
|
||||
uint16_t prbbl[MAX_BWP_SIZE] = {0};
|
||||
@@ -1692,17 +1727,18 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
f1ap_served_cell_info_t info;
|
||||
read_du_cell_info(cfg, NODE_IS_DU(node_type), &gnb_id, &gnb_du_id, &name, &info, 1);
|
||||
|
||||
if (IS_SA_MODE(get_softmodem_params())) {
|
||||
NR_COMMON_channels_t *cc = &RC.nrmac[0]->common_channels[0];
|
||||
cc->du_SIBs = fill_du_sibs(GNBParamList.paramarray[0]);
|
||||
|
||||
if (IS_SA_MODE(get_softmodem_params()))
|
||||
nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac);
|
||||
if (scc->ext2 && scc->ext2->ntn_Config_r17)
|
||||
nr_mac_configure_sib19(RC.nrmac[0]);
|
||||
}
|
||||
|
||||
// read F1 Setup information from config and generated MIB/SIB1
|
||||
// and store it at MAC for sending later
|
||||
NR_BCCH_BCH_Message_t *mib = RC.nrmac[0]->common_channels[0].mib;
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1 = RC.nrmac[0]->common_channels[0].sib1;
|
||||
f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1);
|
||||
seq_arr_t *du_SIBs = RC.nrmac[0]->common_channels[0].du_SIBs;
|
||||
f1ap_setup_req_t *req = RC_read_F1Setup(gnb_du_id, name, &info, scc, mib, sib1, du_SIBs);
|
||||
AssertFatal(req != NULL, "could not read F1 Setup information\n");
|
||||
RC.nrmac[0]->f1_config.setup_req = req;
|
||||
RC.nrmac[0]->f1_config.gnb_id = gnb_id;
|
||||
@@ -1846,6 +1882,31 @@ static int sort_neighbour_cell_config_by_cell_id(const void *a, const void *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static seq_arr_t *fill_cu_sibs(paramdef_t *GNBparamarray)
|
||||
{
|
||||
if (NODE_IS_CU(get_node_type()))
|
||||
AssertFatal(GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0, "This is CU, do not input DU SIBs\n");
|
||||
|
||||
if (!config_isparamset(GNBparamarray, GNB_CU_SIBS_IDX))
|
||||
return NULL;
|
||||
|
||||
seq_arr_t *SIBs = malloc(sizeof(seq_arr_t));
|
||||
seq_arr_init(SIBs, sizeof(nr_SIBs_t));
|
||||
for (int i = 0; i < GNBparamarray[GNB_CU_SIBS_IDX].numelt; i++) {
|
||||
int sib_value = GNBparamarray[GNB_CU_SIBS_IDX].iptr[i];
|
||||
// SIB10, SIB12, SIB13, SIB14, SIB15, SIB17, SIB18, SIB19 and SIB20 are generated by the DU
|
||||
// all the rest in the CU
|
||||
AssertFatal((sib_value > 1 && sib_value < 10) || sib_value == 11 || sib_value == 16,
|
||||
"SIB%d is not a CU SIB, to be configured in DU section\n",
|
||||
sib_value);
|
||||
nr_SIBs_t *cu_sib = calloc_or_fail(1, sizeof(*cu_sib));
|
||||
cu_sib->SIB_type = sib_value;
|
||||
LOG_I(GNB_APP, "activate SIB%d at CU\n", sib_value);
|
||||
seq_arr_push_back(SIBs, cu_sib, sizeof(nr_SIBs_t));
|
||||
}
|
||||
return SIBs;
|
||||
}
|
||||
|
||||
static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
||||
{
|
||||
char gnbpath[MAX_OPTNAME_SIZE + 8];
|
||||
@@ -2085,6 +2146,8 @@ gNB_RRC_INST *RCconfig_NRRRC()
|
||||
|
||||
fill_measurement_configuration(k, rrc);
|
||||
|
||||
rrc->SIBs = fill_cu_sibs(GNBParamList.paramarray[i]);
|
||||
|
||||
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
|
||||
|
||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||
|
||||
@@ -95,14 +95,8 @@ gNB_RRC_INST *RCconfig_NRRRC();
|
||||
int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
|
||||
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
|
||||
void wait_f1_setup_response(void);
|
||||
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
|
||||
const char *name,
|
||||
const f1ap_served_cell_info_t *info,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
NR_BCCH_BCH_Message_t *mib,
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1);
|
||||
f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc);
|
||||
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1);
|
||||
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1, seq_arr_t *du_SIBs);
|
||||
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update);
|
||||
MessageDef *RCconfig_NR_CU_E1(const E1_t *entity);
|
||||
ngran_node_t get_node_type(void);
|
||||
|
||||
@@ -139,6 +139,8 @@ typedef enum {
|
||||
#define GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES "num_ulharq"
|
||||
#define GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST "beam_weights"
|
||||
#define GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST "uess_agg_levels"
|
||||
#define GNB_CONFIG_STRING_CU_SIB_LIST "cu_sibs"
|
||||
#define GNB_CONFIG_STRING_DU_SIB_LIST "du_sibs"
|
||||
|
||||
#define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n"
|
||||
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
|
||||
@@ -150,6 +152,8 @@ typedef enum {
|
||||
#define GNB_CONFIG_HLP_NUM_DL_HARQ "Set Num DL harq processes. Valid values 2,4,6,8,10,12,16,32. Default 16"
|
||||
#define GNB_CONFIG_HLP_NUM_UL_HARQ "Set Num UL harq processes. Valid values 16,32. Default 16"
|
||||
#define GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST "List of aggregation levels with number of candidates per level. Element 0 - aggregation level 1"
|
||||
#define GNB_CONFIG_HLP_CU_SIBS "List of CU generated SIBs to be transmitted"
|
||||
#define GNB_CONFIG_HLP_DU_SIBS "List of DU generated SIBs to be transmitted"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* cell configuration parameters */
|
||||
@@ -195,6 +199,8 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
|
||||
{GNB_CONFIG_STRING_UESS_AGG_LEVEL_LIST, \
|
||||
GNB_CONFIG_HLP_UESS_AGG_LEVEL_LIST, 0, .iptr=NULL, .defintarrayval=NULL, TYPE_INTARRAY, 0}, \
|
||||
{GNB_CONFIG_STRING_CU_SIB_LIST, GNB_CONFIG_HLP_CU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
|
||||
{GNB_CONFIG_STRING_DU_SIB_LIST, GNB_CONFIG_HLP_DU_SIBS, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -236,6 +242,8 @@ typedef enum {
|
||||
#define GNB_NUM_UL_HARQ_IDX 34
|
||||
#define GNB_BEAMWEIGHTS_IDX 35
|
||||
#define GNB_UESS_AGG_LEVEL_LIST_IDX 36
|
||||
#define GNB_CU_SIBS_IDX 37
|
||||
#define GNB_DU_SIBS_IDX 38
|
||||
|
||||
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
|
||||
#define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32}
|
||||
@@ -279,6 +287,8 @@ typedef enum {
|
||||
{ .s1 = { config_check_intval, NUM_UL_HARQ_OKVALUES,2 } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -1505,6 +1505,74 @@ void find_aggregation_candidates(uint8_t *aggregation_level,
|
||||
}
|
||||
}
|
||||
|
||||
void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset)
|
||||
{
|
||||
switch(ss->monitoringSlotPeriodicityAndOffset->present) {
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
|
||||
*period = 1;
|
||||
*offset = 0;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
|
||||
*period = 2;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
|
||||
*period = 4;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
|
||||
*period = 5;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
|
||||
*period = 8;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
|
||||
*period = 10;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
|
||||
*period = 16;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
|
||||
*period = 20;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
|
||||
*period = 40;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
|
||||
*period = 80;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
|
||||
*period = 160;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
|
||||
*period = 320;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
|
||||
*period = 640;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
|
||||
*period = 1280;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
|
||||
*period = 2560;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid monitoring slot periodicity value\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss,
|
||||
uint16_t period,
|
||||
|
||||
@@ -213,6 +213,7 @@ uint8_t nr_get_Qm_ul(uint8_t Imcs, uint8_t table_idx);
|
||||
uint32_t nr_get_code_rate_ul(uint8_t Imcs, uint8_t table_idx);
|
||||
|
||||
uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset);
|
||||
void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset);
|
||||
|
||||
uint32_t nr_compute_tbslbrm(uint16_t table,
|
||||
uint16_t nb_rb,
|
||||
|
||||
@@ -936,10 +936,7 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source)
|
||||
target->intraFreqReselection = source->intraFreqReselection;
|
||||
}
|
||||
|
||||
void nr_rrc_mac_config_req_mib(module_id_t module_id,
|
||||
int cc_idP,
|
||||
NR_MIB_t *mib,
|
||||
int sched_sib)
|
||||
void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
int ret = pthread_mutex_lock(&mac->if_mutex);
|
||||
@@ -952,8 +949,8 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id,
|
||||
mac->phy_config.CC_id = cc_idP;
|
||||
if (sched_sib == 1)
|
||||
mac->get_sib1 = true;
|
||||
else if (sched_sib == 2)
|
||||
mac->get_otherSI = true;
|
||||
else if (sched_sib > 1)
|
||||
mac->get_otherSI[sched_sib - 2] = true;
|
||||
nr_ue_decode_mib(mac, cc_idP);
|
||||
ret = pthread_mutex_unlock(&mac->if_mutex);
|
||||
AssertFatal(!ret, "mutex failed %d\n", ret);
|
||||
|
||||
@@ -539,7 +539,7 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
int servCellIndex;
|
||||
long physCellId;
|
||||
bool get_sib1;
|
||||
bool get_otherSI;
|
||||
bool get_otherSI[MAX_SI_GROUPS];
|
||||
NR_MIB_t *mib;
|
||||
|
||||
si_schedInfo_t si_SchedInfo;
|
||||
|
||||
@@ -68,12 +68,12 @@ void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch);
|
||||
\param sibs_mask sibs mask
|
||||
\param pduP pointer to pdu
|
||||
\param pdu_length length of pdu */
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint8_t ack_nack,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len);
|
||||
void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint8_t ack_nack,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len);
|
||||
|
||||
void release_dl_BWP(NR_UE_MAC_INST_t *mac, int index);
|
||||
void release_ul_BWP(NR_UE_MAC_INST_t *mac, int index);
|
||||
|
||||
@@ -56,7 +56,8 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
||||
LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id);
|
||||
nr_ue_reset_sync_state(mac);
|
||||
mac->get_sib1 = false;
|
||||
mac->get_otherSI = false;
|
||||
for (int i = 0; i < MAX_SI_GROUPS; i++)
|
||||
mac->get_otherSI[i] = false;
|
||||
memset(&mac->phy_config, 0, sizeof(mac->phy_config));
|
||||
mac->si_SchedInfo.si_window_start = -1;
|
||||
mac->servCellIndex = 0;
|
||||
|
||||
@@ -343,76 +343,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac,
|
||||
dl_config->number_pdus += 1;
|
||||
}
|
||||
|
||||
|
||||
void get_monitoring_period_offset(const NR_SearchSpace_t *ss, int *period, int *offset)
|
||||
{
|
||||
switch(ss->monitoringSlotPeriodicityAndOffset->present) {
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
|
||||
*period = 1;
|
||||
*offset = 0;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
|
||||
*period = 2;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
|
||||
*period = 4;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
|
||||
*period = 5;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
|
||||
*period = 8;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
|
||||
*period = 10;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
|
||||
*period = 16;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
|
||||
*period = 20;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
|
||||
*period = 40;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
|
||||
*period = 80;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
|
||||
*period = 160;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
|
||||
*period = 320;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
|
||||
*period = 640;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
|
||||
*period = 1280;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
|
||||
*period = 2560;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid monitoring slot periodicity value\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss)
|
||||
{
|
||||
if (!ss)
|
||||
@@ -445,7 +375,6 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac,
|
||||
if (((frame * slots_per_frame + slot - offset - i) % period) == 0) {
|
||||
int N = mac->ssb_list.nb_tx_ssb;
|
||||
int K = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb];
|
||||
|
||||
// numbering current frame and slot in terms of monitoring occasions in window
|
||||
int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start;
|
||||
int current_monitor_occasion = (rel_slot % period) + (duration * rel_slot / period);
|
||||
@@ -469,44 +398,41 @@ bool is_window_valid(NR_UE_MAC_INST_t *mac, int window_slots, int abs_slot)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
|
||||
const NR_SearchSpace_t *ss,
|
||||
const int slots_per_frame,
|
||||
const int frame,
|
||||
const int slot)
|
||||
static bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac,
|
||||
const NR_SearchSpace_t *ss,
|
||||
const int si_idx,
|
||||
const int slots_per_frame,
|
||||
const int frame,
|
||||
const int slot)
|
||||
{
|
||||
// according to 5.2.2.3.2 in 331
|
||||
const int abs_slot = frame * slots_per_frame + slot;
|
||||
|
||||
for (int i = 0; i < mac->si_SchedInfo.si_SchedInfo_list.count; i++) {
|
||||
si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[i];
|
||||
int window_slots = 5 << mac->si_SchedInfo.si_WindowLength;
|
||||
int x = (config->si_WindowPosition - 1) * window_slots;
|
||||
int T = 8 << config->si_Periodicity; // radio frame periodicity
|
||||
bool check_valid;
|
||||
switch (config->type) {
|
||||
case NR_SI_INFO :
|
||||
if (mac->si_SchedInfo.si_window_start == -1) {
|
||||
if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0))
|
||||
mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number
|
||||
}
|
||||
check_valid = is_window_valid(mac, window_slots, abs_slot);
|
||||
if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame))
|
||||
return true;
|
||||
break;
|
||||
case NR_SI_INFO_v1700 :
|
||||
if (mac->si_SchedInfo.si_window_start == -1) {
|
||||
if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame))
|
||||
mac->si_SchedInfo.si_window_start = abs_slot;
|
||||
}
|
||||
window_slots = 10; // TODO window length hardcoded to 10 at gNB for NTN
|
||||
check_valid = is_window_valid(mac, window_slots, abs_slot);
|
||||
if (check_valid && (config->si_WindowPosition - 1) == slot)
|
||||
return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame);
|
||||
break;
|
||||
default :
|
||||
AssertFatal(false, "Invalid SI-SchedulingInfo case\n");
|
||||
}
|
||||
si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[si_idx];
|
||||
int window_slots = 5 << mac->si_SchedInfo.si_WindowLength;
|
||||
int x = (config->si_WindowPosition - 1) * window_slots;
|
||||
int T = 8 << config->si_Periodicity; // radio frame periodicity
|
||||
bool check_valid;
|
||||
switch (config->type) {
|
||||
case NR_SI_INFO :
|
||||
if (mac->si_SchedInfo.si_window_start == -1) {
|
||||
if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0))
|
||||
mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number
|
||||
}
|
||||
check_valid = is_window_valid(mac, window_slots, abs_slot);
|
||||
if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame))
|
||||
return true;
|
||||
break;
|
||||
case NR_SI_INFO_v1700 :
|
||||
if (mac->si_SchedInfo.si_window_start == -1) {
|
||||
if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame))
|
||||
mac->si_SchedInfo.si_window_start = abs_slot;
|
||||
}
|
||||
if (is_window_valid(mac, window_slots, abs_slot))
|
||||
return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame);
|
||||
break;
|
||||
default :
|
||||
AssertFatal(false, "Invalid SI-SchedulingInfo case\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -549,13 +475,15 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl
|
||||
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, mac->search_space_zero);
|
||||
}
|
||||
}
|
||||
if (mac->get_otherSI) {
|
||||
for (int i = 0; i < MAX_SI_GROUPS; i++) {
|
||||
if (!mac->get_otherSI[i])
|
||||
continue;
|
||||
// If searchSpaceOtherSystemInformation is set to zero,
|
||||
// PDCCH monitoring occasions for SI message reception in SI-window
|
||||
// are same as PDCCH monitoring occasions for SIB1
|
||||
const NR_SearchSpace_t *ss = pdcch_config->otherSI_SS ? pdcch_config->otherSI_SS : mac->search_space_zero;
|
||||
// TODO configure SI-window
|
||||
if (monitor_dci_for_other_SI(mac, ss, slots_per_frame, frame, slot)) {
|
||||
if (monitor_dci_for_other_SI(mac, ss, i, slots_per_frame, frame, slot)) {
|
||||
LOG_D(NR_MAC_DCI, "Monitoring DCI for other SIs in frame %d slot %d\n", frame, slot);
|
||||
config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss);
|
||||
}
|
||||
|
||||
@@ -300,18 +300,22 @@ static void configure_ratematching_csi(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsc
|
||||
}
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint8_t ack_nack,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len)
|
||||
void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint8_t ack_nack,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len)
|
||||
{
|
||||
if(ack_nack) {
|
||||
LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
|
||||
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
|
||||
mac->get_sib1 = false;
|
||||
mac->get_otherSI = false;
|
||||
if (mac->get_sib1)
|
||||
mac->get_sib1 = false;
|
||||
for (int i = 0; i < MAX_SI_GROUPS; i++) {
|
||||
if (mac->get_otherSI[i])
|
||||
mac->get_otherSI[i] = false;
|
||||
}
|
||||
T(T_NRUE_MAC_DL_PDU_WITH_DATA,
|
||||
T_INT(SI_RNTI),
|
||||
T_INT(-1 /* frame, unavailable here */),
|
||||
@@ -319,9 +323,10 @@ int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
|
||||
T_INT(0 /* harq_pid */),
|
||||
T_BUFFER(pduP, pdu_len));
|
||||
}
|
||||
else
|
||||
else {
|
||||
LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI");
|
||||
return 0;
|
||||
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -742,8 +747,10 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dlsch_pdu->rb_offset = dlsch_pdu->start_rb + dlsch_pdu->BWPStart;
|
||||
if (mac->get_sib1 || mac->get_otherSI)
|
||||
|
||||
if (mac->get_sib1)
|
||||
dlsch_pdu->rb_offset -= dlsch_pdu->BWPStart;
|
||||
|
||||
/* TIME_DOM_RESOURCE_ASSIGNMENT */
|
||||
@@ -2993,7 +3000,7 @@ static void extract_10_ra_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->tb_scaling, 2);
|
||||
}
|
||||
|
||||
static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB)
|
||||
static uint8_t extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB)
|
||||
{
|
||||
LOG_D(NR_MAC_DCI, "Received dci 1_0 SI rnti\n");
|
||||
|
||||
@@ -3009,6 +3016,7 @@ static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2);
|
||||
// System information indicator 1 bit
|
||||
EXTRACT_DCI_ITEM(dci_pdu_rel15->system_info_indicator, 1);
|
||||
return dci_pdu_rel15->system_info_indicator;
|
||||
}
|
||||
|
||||
static bool extract_10_c_rnti(NR_UE_MAC_INST_t *mac,
|
||||
@@ -3312,7 +3320,10 @@ static nr_dci_format_t nr_extract_dci_00_10(NR_UE_MAC_INST_t *mac,
|
||||
n_RB = get_nrb_for_dci(mac, format, ss_type);
|
||||
if (n_RB == 0)
|
||||
return NR_DCI_NONE;
|
||||
extract_10_si_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB);
|
||||
uint8_t sys_info = extract_10_si_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB);
|
||||
// sys info = 0 for SIB1 and 1 for other SIB
|
||||
if (mac->get_sib1 == 0 && sys_info == 0)
|
||||
return NR_DCI_NONE;
|
||||
break;
|
||||
case TYPE_C_RNTI_ :
|
||||
// Identifier for DCI formats
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "BIT_STRING.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "GNB_APP/gnb_config.h"
|
||||
#include "NR_MIB.h"
|
||||
#include "NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "NR_BCCH-BCH-Message.h"
|
||||
@@ -863,30 +864,98 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
NR_RA_t *ra = &cc->ra[n];
|
||||
nr_clear_ra_proc(ra);
|
||||
}
|
||||
|
||||
nr_fill_sched_osi(nrmac, scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon);
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
|
||||
if (IS_SA_MODE(get_softmodem_params()))
|
||||
config_sched_ctrlCommon(nrmac);
|
||||
}
|
||||
|
||||
void nr_fill_sched_osi(gNB_MAC_INST *nrmac, const struct NR_SetupRelease_PDCCH_ConfigCommon *pdcch_ConfigCommon)
|
||||
bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib])
|
||||
{
|
||||
NR_SearchSpaceId_t *osi_SearchSpace = pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation;
|
||||
if (osi_SearchSpace) {
|
||||
nrmac->sched_osi = CALLOC(1, sizeof(*nrmac->sched_osi));
|
||||
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
|
||||
seq_arr_t *du_SIBs = nrmac->common_channels[0].du_SIBs;
|
||||
int num_du_sib = 0;
|
||||
if (du_SIBs)
|
||||
num_du_sib = du_SIBs->size;
|
||||
if (num_cu_sib + num_du_sib == 0)
|
||||
return false; /* no updates */
|
||||
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList =
|
||||
pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n");
|
||||
for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
|
||||
NR_SearchSpace_t *ss = commonSearchSpaceList->list.array[i];
|
||||
if (ss->searchSpaceId == *osi_SearchSpace)
|
||||
nrmac->sched_osi->search_space = ss;
|
||||
int config_sibs[num_cu_sib + num_du_sib];
|
||||
NR_SystemInformation_IEs_t *sysInfo = calloc(1, sizeof(*sysInfo)); //for SIB up to 14 included
|
||||
NR_SystemInformation_IEs_t *sysInfov17 = calloc(1, sizeof(*sysInfov17)); // for othersibs
|
||||
for (int i = 0; i < num_cu_sib; i++) {
|
||||
config_sibs[i] = cu_sib[i].SI_type;
|
||||
switch (config_sibs[i]) {
|
||||
case 2: {
|
||||
struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type = calloc(1, sizeof(*type));
|
||||
type->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2;
|
||||
// SIB2 coming from CU need to decode it
|
||||
NR_SIB2_t *sib2 = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode(NULL,
|
||||
&asn_DEF_NR_SIB2,
|
||||
(void **)&sib2,
|
||||
cu_sib[i].SI_container,
|
||||
cu_sib[i].SI_container_length,
|
||||
0,
|
||||
0);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_E(NR_MAC, "cannot decode SIB%d from CU\n", config_sibs[i]);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SIB2, cu_sib[i].SI_container);
|
||||
}
|
||||
type->choice.sib2 = sib2;
|
||||
add_sib_to_systeminformation(sysInfo, type);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
AssertFatal(false, "Invalid or not supported SIB%d\n", config_sibs[i]);
|
||||
}
|
||||
AssertFatal(nrmac->sched_osi->search_space != NULL, "SearchSpace cannot be null for OSI\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_du_sib; i++) {
|
||||
nr_SIBs_t *si = (nr_SIBs_t *)seq_arr_at(du_SIBs, i);
|
||||
int sib_idx = i + num_cu_sib;
|
||||
config_sibs[sib_idx] = si->SIB_type;
|
||||
switch (config_sibs[sib_idx]) {
|
||||
case 19: {
|
||||
struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type_du = calloc(1, sizeof(*type_du));
|
||||
type_du->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700;
|
||||
NR_SIB19_r17_t *sib19 = get_SIB19_NR(cc->ServingCellConfigCommon);
|
||||
type_du->choice.sib19_v1700 = sib19;
|
||||
add_sib_to_systeminformation(sysInfov17, type_du);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
AssertFatal(false, "Invalid or not supported SIB%d\n", sib_idx);
|
||||
}
|
||||
}
|
||||
|
||||
update_SIB1_NR_SI(cc->sib1, num_cu_sib + num_du_sib, config_sibs);
|
||||
cc->sib1_bcch_length = encode_SIB_NR(cc->sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu));
|
||||
AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n");
|
||||
|
||||
// generate otherSIB payloads
|
||||
cc->other_sib_bcch_length[0] = encode_sysinfo_ie(sysInfo, cc->other_sib_bcch_pdu[0], sizeof(cc->other_sib_bcch_pdu[0]));
|
||||
cc->other_sib_bcch_length[1] = encode_sysinfo_ie(sysInfov17, cc->other_sib_bcch_pdu[1], sizeof(cc->other_sib_bcch_pdu[1]));
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfo);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SystemInformation_IEs, sysInfov17);
|
||||
return true;
|
||||
}
|
||||
|
||||
void prepare_du_configuration_update(gNB_MAC_INST *mac,
|
||||
f1ap_served_cell_info_t *info,
|
||||
NR_BCCH_BCH_Message_t *mib,
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1)
|
||||
{
|
||||
/* send gNB-DU configuration update to RRC */
|
||||
f1ap_gnb_du_configuration_update_t update = {
|
||||
.transaction_id = 1,
|
||||
.num_cells_to_modify = 1,
|
||||
};
|
||||
update.cell_to_modify[0].old_nr_cellid = info->nr_cellid;
|
||||
update.cell_to_modify[0].info = *info;
|
||||
update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1, NULL);
|
||||
mac->mac_rrc.gnb_du_configuration_update(&update);
|
||||
}
|
||||
|
||||
void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_t cellID, int tac)
|
||||
@@ -897,21 +966,10 @@ void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, plmn, cellID, tac, &nrmac->radio_config);
|
||||
cc->sib1 = sib1;
|
||||
cc->sib1_bcch_length = encode_SIB1_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu));
|
||||
cc->sib1_bcch_length = encode_SIB_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu));
|
||||
AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n");
|
||||
}
|
||||
|
||||
void nr_mac_configure_sib19(gNB_MAC_INST *nrmac)
|
||||
{
|
||||
AssertFatal(IS_SA_MODE(get_softmodem_params()), "error: SIB19 only applicable for SA\n");
|
||||
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_BCCH_DL_SCH_Message_t *sib19 = get_SIB19_NR(scc);
|
||||
cc->sib19 = sib19;
|
||||
cc->sib19_bcch_length = encode_SIB19_NR(sib19, cc->sib19_bcch_pdu, sizeof(cc->sib19_bcch_pdu));
|
||||
AssertFatal(cc->sib19_bcch_length > 0, "could not encode SIB19\n");
|
||||
}
|
||||
|
||||
bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup)
|
||||
{
|
||||
/* ideally, instead of this function, "users" of this function should call
|
||||
|
||||
@@ -219,8 +219,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
|
||||
// SIB19 will be scheduled if ntn_Config_r17 is initialized
|
||||
if (IS_SA_MODE(get_softmodem_params())) {
|
||||
schedule_nr_sib1(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req);
|
||||
if (cc->sib19)
|
||||
schedule_nr_sib19(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req, cc->sib19_bcch_length, cc->sib19_bcch_pdu);
|
||||
schedule_nr_other_sib(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req);
|
||||
}
|
||||
|
||||
// This schedule PRACH if we are not in phy_test mode
|
||||
|
||||
@@ -878,7 +878,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
ul_dci_req->numPdus += 1;
|
||||
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch, false);
|
||||
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch);
|
||||
nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15;
|
||||
}
|
||||
|
||||
@@ -1250,81 +1250,11 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_
|
||||
nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu);
|
||||
}
|
||||
|
||||
|
||||
static void find_monitoring_periodicity_offset_common(const NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset)
|
||||
{
|
||||
switch (ss->monitoringSlotPeriodicityAndOffset->present) {
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1:
|
||||
*slot_period = 1;
|
||||
*offset = 0;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2:
|
||||
*slot_period = 2;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4:
|
||||
*slot_period = 4;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl4;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5:
|
||||
*slot_period = 5;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl5;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8:
|
||||
*slot_period = 8;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl8;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10:
|
||||
*slot_period = 10;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl10;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16:
|
||||
*slot_period = 16;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl16;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20:
|
||||
*slot_period = 20;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl20;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40:
|
||||
*slot_period = 40;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl40;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80:
|
||||
*slot_period = 80;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl80;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160:
|
||||
*slot_period = 160;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl160;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320:
|
||||
*slot_period = 320;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl320;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640:
|
||||
*slot_period = 640;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl640;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280:
|
||||
*slot_period = 1280;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl1280;
|
||||
break;
|
||||
case NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560:
|
||||
*slot_period = 2560;
|
||||
*offset = ss->monitoringSlotPeriodicityAndOffset->choice.sl2560;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Invalid monitoring slot periodicity and offset value\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_msg2_monitoring(const NR_RA_t *ra, int slots_per_frame, int current_frame, int current_slot)
|
||||
{
|
||||
// check if the slot is not among the PDCCH monitored ones (38.213 10.1)
|
||||
uint16_t monitoring_slot_period, monitoring_offset;
|
||||
find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset);
|
||||
int monitoring_slot_period, monitoring_offset;
|
||||
get_monitoring_period_offset(ra->ra_ss, &monitoring_slot_period, &monitoring_offset);
|
||||
if ((current_frame * slots_per_frame + current_slot - monitoring_offset) % monitoring_slot_period != 0)
|
||||
return false;
|
||||
return true;
|
||||
@@ -1432,7 +1362,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
|
||||
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
dl_req->nPDUs += 1;
|
||||
pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch, false);
|
||||
nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch);
|
||||
nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15;
|
||||
}
|
||||
|
||||
|
||||
@@ -274,76 +274,75 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_tbs(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
NR_sched_pdsch_t *pdsch,
|
||||
uint32_t num_total_bytes,
|
||||
uint16_t *vrb_map)
|
||||
static uint32_t get_tbs_bch(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
NR_sched_pdsch_t *pdsch,
|
||||
uint32_t num_total_bytes,
|
||||
uint16_t *vrb_map)
|
||||
{
|
||||
NR_tda_info_t *tda_info = &pdsch->tda_info;
|
||||
|
||||
const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs;
|
||||
int rbStart = type0_PDCCH_CSS_config->cset_start_rb;
|
||||
|
||||
// Calculate number of PRB_DMRS
|
||||
uint8_t N_PRB_DMRS = pdsch->dmrs_parms.N_PRB_DMRS;
|
||||
uint16_t dmrs_length = pdsch->dmrs_parms.N_DMRS_SLOT;
|
||||
LOG_D(MAC, "dlDmrsSymbPos %x\n", pdsch->dmrs_parms.dl_dmrs_symb_pos);
|
||||
int mcsTableIdx = 0;
|
||||
int rbSize = 0;
|
||||
uint32_t TBS = 0;
|
||||
do {
|
||||
if (rbSize < bwpSize && !(vrb_map[rbStart + rbSize] & SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols)))
|
||||
rbSize++;
|
||||
const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
|
||||
int bwpSize = type0_PDCCH_CSS_config->num_rbs;
|
||||
int bwpStart = type0_PDCCH_CSS_config->cset_start_rb;
|
||||
int rbStop = bwpSize - 1;
|
||||
int rbStart = 0;
|
||||
uint16_t rbSize = 0;
|
||||
while (rbStart < rbStop) {
|
||||
if (vrb_map[rbStart + bwpStart] & slbitmap)
|
||||
rbStart++;
|
||||
else {
|
||||
if (pdsch->mcs < 10)
|
||||
pdsch->mcs++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
TBS = nr_compute_tbs(nr_get_Qm_dl(pdsch->mcs, mcsTableIdx),
|
||||
nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx),
|
||||
rbSize,
|
||||
tda_info->nrOfSymbols,
|
||||
N_PRB_DMRS * dmrs_length,
|
||||
0,
|
||||
0,
|
||||
1)
|
||||
>> 3;
|
||||
} while (TBS < num_total_bytes);
|
||||
int max_rbSize = 0;
|
||||
while (rbStart + max_rbSize <= rbStop && !(vrb_map[rbStart + max_rbSize + bwpStart] & slbitmap))
|
||||
max_rbSize++;
|
||||
|
||||
if (TBS < num_total_bytes) {
|
||||
for (int rb = 0; rb < bwpSize; rb++)
|
||||
LOG_I(NR_MAC, "vrb_map[%d] %x\n", rbStart + rb, vrb_map[rbStart + rb]);
|
||||
bool res = false;
|
||||
while (res == false && pdsch->mcs < 10) {
|
||||
res = nr_find_nb_rb(nr_get_Qm_dl(pdsch->mcs, mcsTableIdx),
|
||||
nr_get_code_rate_dl(pdsch->mcs, mcsTableIdx),
|
||||
1, // no transform precoding for DL
|
||||
1, // single layer
|
||||
tda_info->nrOfSymbols,
|
||||
pdsch->dmrs_parms.N_PRB_DMRS * pdsch->dmrs_parms.N_DMRS_SLOT,
|
||||
num_total_bytes,
|
||||
1, // min_rbSize
|
||||
max_rbSize,
|
||||
&TBS,
|
||||
&rbSize);
|
||||
if (!res)
|
||||
pdsch->mcs++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
AssertFatal(
|
||||
TBS >= num_total_bytes,
|
||||
"Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d SLmask %x - [%d,%d])\n",
|
||||
num_total_bytes,
|
||||
rbStart,
|
||||
rbSize,
|
||||
bwpSize,
|
||||
SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols),
|
||||
tda_info->startSymbolIndex,
|
||||
tda_info->nrOfSymbols);
|
||||
AssertFatal(TBS >= num_total_bytes,
|
||||
"Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d)\n",
|
||||
num_total_bytes,
|
||||
rbStart,
|
||||
rbSize,
|
||||
bwpSize);
|
||||
|
||||
pdsch->rbSize = rbSize;
|
||||
pdsch->rbStart = 0;
|
||||
pdsch->rbStart = rbStart;
|
||||
|
||||
LOG_D(
|
||||
NR_MAC,
|
||||
"mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n",
|
||||
pdsch->mcs,
|
||||
tda_info->startSymbolIndex,
|
||||
tda_info->nrOfSymbols,
|
||||
pdsch->rbSize,
|
||||
TBS,
|
||||
dmrs_length,
|
||||
N_PRB_DMRS,
|
||||
tda_info->mapping_type);
|
||||
LOG_D(NR_MAC,
|
||||
"mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n",
|
||||
pdsch->mcs,
|
||||
tda_info->startSymbolIndex,
|
||||
tda_info->nrOfSymbols,
|
||||
rbSize,
|
||||
TBS,
|
||||
pdsch->dmrs_parms.N_DMRS_SLOT,
|
||||
N_PRB_DMRS,
|
||||
tda_info->mapping_type);
|
||||
return TBS;
|
||||
}
|
||||
|
||||
static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac,
|
||||
int CC_id,
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
int time_domain_allocation,
|
||||
@@ -353,7 +352,6 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
int beam,
|
||||
uint16_t num_total_bytes)
|
||||
{
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
|
||||
AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n");
|
||||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
|
||||
uint16_t *vrb_map = cc->vrb_map[beam];
|
||||
@@ -382,7 +380,10 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
|
||||
AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n");
|
||||
|
||||
uint32_t TBS = get_tbs(type0_PDCCH_CSS_config, &gNB_mac->sched_ctrlCommon->sched_pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map);
|
||||
uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config,
|
||||
&gNB_mac->sched_ctrlCommon->sched_pdsch,
|
||||
gNB_mac->sched_ctrlCommon->num_total_bytes,
|
||||
vrb_map);
|
||||
|
||||
// Mark the corresponding RBs as used
|
||||
fill_pdcch_vrb_map(gNB_mac,
|
||||
@@ -397,92 +398,22 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
return TBS;
|
||||
}
|
||||
|
||||
static uint32_t schedule_control_other_si(module_id_t module_id,
|
||||
int CC_id,
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
int time_domain_allocation,
|
||||
NR_pdsch_dmrs_t *dmrs_parms,
|
||||
NR_tda_info_t *tda_info,
|
||||
uint8_t candidate_idx,
|
||||
int beam,
|
||||
uint16_t num_total_bytes)
|
||||
static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac,
|
||||
NR_sched_pdsch_t *pdsch,
|
||||
NR_sched_pdcch_t *pdcch,
|
||||
NR_SearchSpace_t *search_space,
|
||||
NR_ControlResourceSet_t *coreset,
|
||||
int aggregation_level,
|
||||
int cce_index,
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req,
|
||||
int pdu_index,
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
uint32_t TBS,
|
||||
int StartSymbolIndex,
|
||||
int NrOfSymbols,
|
||||
bool is_sib1,
|
||||
int beam_index)
|
||||
{
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
|
||||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
uint16_t *vrb_map = cc->vrb_map[beam];
|
||||
|
||||
if (!gNB_mac->sched_osi->coreset) {
|
||||
gNB_mac->sched_osi->coreset =
|
||||
get_coreset(gNB_mac, scc, NULL, gNB_mac->sched_osi->search_space, NR_SearchSpace__searchSpaceType_PR_common);
|
||||
gNB_mac->sched_osi->sched_pdcch =
|
||||
set_pdcch_structure(NULL, gNB_mac->sched_osi->search_space, gNB_mac->sched_osi->coreset, scc, NULL, type0_PDCCH_CSS_config);
|
||||
}
|
||||
|
||||
NR_sched_pdsch_t *pdsch = &gNB_mac->sched_osi->sched_pdsch;
|
||||
pdsch->time_domain_allocation = time_domain_allocation;
|
||||
pdsch->dmrs_parms = *dmrs_parms;
|
||||
pdsch->tda_info = *tda_info;
|
||||
pdsch->mcs = 0; // starting from mcs 0
|
||||
gNB_mac->sched_osi->num_total_bytes = num_total_bytes;
|
||||
|
||||
uint8_t nr_of_candidates;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
find_aggregation_candidates(&gNB_mac->sched_osi->aggregation_level,
|
||||
&nr_of_candidates,
|
||||
gNB_mac->sched_ctrlCommon->search_space,
|
||||
4 << i);
|
||||
if (nr_of_candidates > 0)
|
||||
break; // choosing the lower value of aggregation level available
|
||||
}
|
||||
AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n");
|
||||
gNB_mac->sched_osi->cce_index = find_pdcch_candidate(gNB_mac,
|
||||
CC_id,
|
||||
gNB_mac->sched_osi->aggregation_level,
|
||||
nr_of_candidates,
|
||||
beam,
|
||||
&gNB_mac->sched_osi->sched_pdcch,
|
||||
gNB_mac->sched_osi->coreset,
|
||||
0);
|
||||
|
||||
AssertFatal(gNB_mac->sched_osi->cce_index >= 0, "Could not find CCE for coreset0\n");
|
||||
|
||||
// Calculate number of PRB_DMRS
|
||||
uint32_t TBS = get_tbs(type0_PDCCH_CSS_config, &gNB_mac->sched_osi->sched_pdsch, gNB_mac->sched_osi->num_total_bytes, vrb_map);
|
||||
// Mark the corresponding RBs as used
|
||||
fill_pdcch_vrb_map(gNB_mac,
|
||||
CC_id,
|
||||
&gNB_mac->sched_osi->sched_pdcch,
|
||||
gNB_mac->sched_osi->cce_index,
|
||||
gNB_mac->sched_osi->aggregation_level,
|
||||
beam);
|
||||
for (int rb = 0; rb < pdsch->rbSize; rb++) {
|
||||
vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
|
||||
}
|
||||
return TBS;
|
||||
}
|
||||
|
||||
static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
|
||||
NR_UE_sched_osi_ctrl_t *sched_osi,
|
||||
NR_UE_sched_ctrl_t *sched_ctrlCommon,
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req,
|
||||
int pdu_index,
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
|
||||
uint32_t TBS,
|
||||
int StartSymbolIndex,
|
||||
int NrOfSymbols,
|
||||
int beam_index)
|
||||
{
|
||||
// will set data according to SIB type (SIB1/OtherSI)
|
||||
NR_sched_pdsch_t *pdsch = (sched_ctrlCommon ? &sched_ctrlCommon->sched_pdsch : &sched_osi->sched_pdsch);
|
||||
NR_sched_pdcch_t *pdcch = (sched_ctrlCommon ? &sched_ctrlCommon->sched_pdcch : &sched_osi->sched_pdcch);
|
||||
NR_SearchSpace_t *search_space = (sched_ctrlCommon ? sched_ctrlCommon->search_space : sched_osi->search_space);
|
||||
NR_ControlResourceSet_t *coreset = (sched_ctrlCommon ? sched_ctrlCommon->coreset : sched_osi->coreset);
|
||||
uint8_t aggregation_level = (sched_ctrlCommon ? sched_ctrlCommon->aggregation_level : sched_osi->aggregation_level);
|
||||
int cce_index = (sched_ctrlCommon ? sched_ctrlCommon->cce_index : sched_osi->cce_index);
|
||||
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP];
|
||||
NR_COMMON_channels_t *cc = gNB_mac->common_channels;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
int mcsTableIdx = 0;
|
||||
@@ -493,10 +424,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
|
||||
dl_tti_pdcch_pdu->PDUSize = (uint16_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
dl_req->nPDUs += 1;
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
nr_configure_pdcch(pdcch_pdu_rel15,
|
||||
coreset,
|
||||
pdcch,
|
||||
sched_ctrlCommon ? false : true);
|
||||
nr_configure_pdcch(pdcch_pdu_rel15, coreset, pdcch);
|
||||
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
|
||||
memset(dl_tti_pdsch_pdu, 0, sizeof(*dl_tti_pdcch_pdu));
|
||||
@@ -532,7 +460,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
|
||||
pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
|
||||
pdsch_pdu_rel15->nrOfLayers = 1;
|
||||
pdsch_pdu_rel15->transmissionScheme = 0;
|
||||
pdsch_pdu_rel15->refPoint = 1;
|
||||
pdsch_pdu_rel15->refPoint = is_sib1;
|
||||
pdsch_pdu_rel15->dmrsConfigType = 0;
|
||||
pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
|
||||
pdsch_pdu_rel15->SCID = 0;
|
||||
@@ -598,7 +526,7 @@ static void nr_fill_nfapi_dl_SIB_pdu(int Mod_idP,
|
||||
dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0;
|
||||
dci_payload.antenna_ports.val = 0;
|
||||
dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
|
||||
dci_payload.system_info_indicator = sched_ctrlCommon ? 0 : 1;
|
||||
dci_payload.system_info_indicator = is_sib1 ? 0 : 1;
|
||||
|
||||
int dci_format = NR_DL_DCI_FORMAT_1_0;
|
||||
int rnti_type = TYPE_SI_RNTI_;
|
||||
@@ -696,7 +624,8 @@ void schedule_nr_sib1(module_id_t module_idP,
|
||||
|
||||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
|
||||
// Configure sched_ctrlCommon for SIB1
|
||||
uint32_t TBS = schedule_control_sib1(module_idP, CC_id,
|
||||
uint32_t TBS = schedule_control_sib1(gNB_mac,
|
||||
CC_id,
|
||||
type0_PDCCH_CSS_config,
|
||||
time_domain_allocation,
|
||||
&dmrs_parms,
|
||||
@@ -707,17 +636,21 @@ void schedule_nr_sib1(module_id_t module_idP,
|
||||
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
int pdu_index = gNB_mac->pdu_index[0]++;
|
||||
LOG_D(NR_MAC, "%s() %4d.%2d\n", __func__, frameP, slotP);
|
||||
nr_fill_nfapi_dl_SIB_pdu(module_idP,
|
||||
NULL,
|
||||
gNB_mac->sched_ctrlCommon,
|
||||
dl_req,
|
||||
pdu_index,
|
||||
type0_PDCCH_CSS_config,
|
||||
TBS,
|
||||
tda_info.startSymbolIndex,
|
||||
tda_info.nrOfSymbols,
|
||||
beam_index);
|
||||
nr_fill_nfapi_dl_SIB_pdu(gNB_mac,
|
||||
&gNB_mac->sched_ctrlCommon->sched_pdsch,
|
||||
&gNB_mac->sched_ctrlCommon->sched_pdcch,
|
||||
gNB_mac->sched_ctrlCommon->search_space,
|
||||
gNB_mac->sched_ctrlCommon->coreset,
|
||||
gNB_mac->sched_ctrlCommon->aggregation_level,
|
||||
gNB_mac->sched_ctrlCommon->cce_index,
|
||||
dl_req,
|
||||
pdu_index,
|
||||
type0_PDCCH_CSS_config,
|
||||
TBS,
|
||||
tda_info.startSymbolIndex,
|
||||
tda_info.nrOfSymbols,
|
||||
true,
|
||||
beam_index);
|
||||
|
||||
const int ntx_req = TX_req->Number_of_PDUs;
|
||||
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
|
||||
@@ -762,133 +695,227 @@ struct NR_SchedulingInfo2_r17 *find_sib19_sched_info(const struct NR_SI_Scheduli
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void schedule_nr_sib19(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
slot_t slotP,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req,
|
||||
int sib19_bcch_length,
|
||||
uint8_t *sib19_bcch_pdu)
|
||||
static void other_sib_sched_control(module_id_t module_idP,
|
||||
frame_t frame,
|
||||
slot_t slot,
|
||||
int beam_index,
|
||||
NR_SearchSpace_t *ss,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req,
|
||||
int payload_idx)
|
||||
{
|
||||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||||
|
||||
const int CC_id = 0;
|
||||
uint8_t candidate_idx = 0;
|
||||
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
|
||||
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon;
|
||||
int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, beam_index, n_slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate otherSIB corresponding for SSB number %d in any available beam\n", beam_index);
|
||||
LOG_D(NR_MAC, "(%d.%d) otherSIB payload %d transmission for ssb number %d\n", frame, slot, payload_idx, beam_index);
|
||||
|
||||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[cc->ssb_index[beam_index]];
|
||||
AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n");
|
||||
NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup;
|
||||
int time_domain_allocation = 1;
|
||||
NR_tda_info_t tda_info = set_tda_info_from_list(pdsch_ConfigCommon->pdsch_TimeDomainAllocationList, time_domain_allocation);
|
||||
LOG_D(NR_MAC,"tda_info.startSymbolIndex: %d, tda_info.nrOfSymbols: %d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
|
||||
// there is no reason to execute further if sched_osi not initialized
|
||||
if (!gNB_mac->sched_osi)
|
||||
return;
|
||||
NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1);
|
||||
|
||||
// get sib19 scheduling info from sib1
|
||||
struct NR_SI_SchedulingInfo_v1700 *si_schedulinginfo2_r17 = cc->sib1->message.choice.c1->choice.systemInformationBlockType1->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->si_SchedulingInfo_v1700;
|
||||
if (!si_schedulinginfo2_r17) {
|
||||
LOG_E(GNB_APP, "SIB1 does not contain si_SchedulingInfo_v1700\n");
|
||||
return;
|
||||
uint8_t aggregation_level = 0;
|
||||
uint8_t nr_of_candidates = 0;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 16 >> i);
|
||||
if (nr_of_candidates > 0)
|
||||
break; // choosing the higher value of aggregation level available
|
||||
}
|
||||
|
||||
struct NR_SchedulingInfo2_r17 *sib19_sched_info = find_sib19_sched_info(si_schedulinginfo2_r17);
|
||||
if (!sib19_sched_info) {
|
||||
LOG_D(GNB_APP, "SIB1 does not contain scheduling info for SIB19\n");
|
||||
AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n");
|
||||
NR_ControlResourceSet_t *coreset = get_coreset(gNB_mac, scc, NULL, ss, NR_SearchSpace__searchSpaceType_PR_common);
|
||||
if (!gNB_mac->sched_pdcch_otherSI) {
|
||||
gNB_mac->sched_pdcch_otherSI = calloc(1, sizeof(*gNB_mac->sched_pdcch_otherSI));
|
||||
*gNB_mac->sched_pdcch_otherSI = set_pdcch_structure(gNB_mac, ss, coreset, scc, NULL, type0_PDCCH_CSS_config);
|
||||
}
|
||||
int cce_index = find_pdcch_candidate(gNB_mac,
|
||||
0,
|
||||
aggregation_level,
|
||||
nr_of_candidates,
|
||||
beam.idx,
|
||||
gNB_mac->sched_pdcch_otherSI,
|
||||
coreset,
|
||||
0);
|
||||
|
||||
AssertFatal(cce_index >= 0, "Could not find CCE for otherSIB DCI\n");
|
||||
|
||||
// Mark the corresponding RBs as used
|
||||
fill_pdcch_vrb_map(gNB_mac, 0, gNB_mac->sched_pdcch_otherSI, cce_index, aggregation_level, beam.idx);
|
||||
|
||||
NR_sched_pdsch_t sched_pdsch_otherSI = {0};
|
||||
sched_pdsch_otherSI.time_domain_allocation = time_domain_allocation;
|
||||
sched_pdsch_otherSI.dmrs_parms = dmrs_parms;
|
||||
sched_pdsch_otherSI.tda_info = tda_info;
|
||||
sched_pdsch_otherSI.mcs = 0; // starting from mcs 0
|
||||
|
||||
uint16_t *vrb_map = cc->vrb_map[beam.idx];
|
||||
uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx];
|
||||
int num_total_bytes = cc->other_sib_bcch_length[payload_idx];
|
||||
uint32_t TBS = get_tbs_bch(type0_PDCCH_CSS_config, &sched_pdsch_otherSI, num_total_bytes, vrb_map);
|
||||
|
||||
for (int rb = 0; rb < sched_pdsch_otherSI.rbSize; rb++) {
|
||||
vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
}
|
||||
|
||||
int pdu_index = gNB_mac->pdu_index[0]++;
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
nr_fill_nfapi_dl_SIB_pdu(gNB_mac,
|
||||
&sched_pdsch_otherSI,
|
||||
gNB_mac->sched_pdcch_otherSI,
|
||||
ss,
|
||||
coreset,
|
||||
aggregation_level,
|
||||
cce_index,
|
||||
dl_req,
|
||||
pdu_index,
|
||||
type0_PDCCH_CSS_config,
|
||||
TBS,
|
||||
tda_info.startSymbolIndex,
|
||||
tda_info.nrOfSymbols,
|
||||
false,
|
||||
beam_index);
|
||||
|
||||
const int ntx_req = TX_req->Number_of_PDUs;
|
||||
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
|
||||
|
||||
// Data to be transmitted
|
||||
memcpy(tx_req->TLVs[0].value.direct, sib_bcch_pdu, TBS);
|
||||
|
||||
tx_req->PDU_length = TBS;
|
||||
tx_req->PDU_index = pdu_index;
|
||||
tx_req->num_TLV = 1;
|
||||
tx_req->TLVs[0].length = TBS + 2;
|
||||
TX_req->Number_of_PDUs++;
|
||||
TX_req->SFN = frame;
|
||||
TX_req->Slot = slot;
|
||||
|
||||
T(T_GNB_MAC_DL_PDU_WITH_DATA,
|
||||
T_INT(module_idP),
|
||||
T_INT(0),
|
||||
T_INT(SI_RNTI),
|
||||
T_INT(frame),
|
||||
T_INT(slot),
|
||||
T_INT(0), // harq_pid
|
||||
T_BUFFER(sib_bcch_pdu, num_total_bytes));
|
||||
}
|
||||
|
||||
// This function verifies if we need to schedule otherSIB in frame and slot
|
||||
static bool test_other_sib_sched_occasion(int window_pos,
|
||||
int window_len,
|
||||
int period,
|
||||
int n_slots_frame,
|
||||
int frame,
|
||||
int slot,
|
||||
int rel_frame,
|
||||
int rel_slot)
|
||||
{
|
||||
int x = window_pos * window_len;
|
||||
int T = 8 << period;
|
||||
int test_frame = (frame - rel_frame) % MAX_FRAME_NUMBER;
|
||||
int si_slot = (x % n_slots_frame) + rel_slot;
|
||||
bool res = ((test_frame % T) != (x / n_slots_frame)) || (si_slot != slot);
|
||||
return res;
|
||||
}
|
||||
|
||||
void schedule_nr_other_sib(module_id_t module_idP,
|
||||
frame_t frame,
|
||||
slot_t slot,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req)
|
||||
{
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
|
||||
NR_SIB1_t *sib1 = cc->sib1->message.choice.c1->choice.systemInformationBlockType1;
|
||||
NR_SI_SchedulingInfo_t *schedInfo = sib1->si_SchedulingInfo;
|
||||
if (!schedInfo)
|
||||
return;
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[0].ServingCellConfigCommon;
|
||||
NR_PDCCH_ConfigCommon_t *pdcch_common = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
|
||||
NR_SearchSpaceId_t *ss_id = pdcch_common->searchSpaceOtherSystemInformation;
|
||||
AssertFatal(ss_id, "searchSpaceOtherSystemInformation not present\n");
|
||||
NR_SearchSpace_t *ss = NULL;
|
||||
for (int i = 0; i < pdcch_common->commonSearchSpaceList->list.count; i++) {
|
||||
if (pdcch_common->commonSearchSpaceList->list.array[i]->searchSpaceId == *ss_id)
|
||||
ss = pdcch_common->commonSearchSpaceList->list.array[i];
|
||||
}
|
||||
AssertFatal(ss, "searchSpaceOtherSystemInformation not found\n");
|
||||
|
||||
NR_SI_SchedulingInfo_v1700_t *schedInfo17 = NULL;
|
||||
if (sib1->nonCriticalExtension) {
|
||||
NR_SIB1_v1610_IEs_t *sib1_v1610 = sib1->nonCriticalExtension;
|
||||
if (sib1_v1610 && sib1_v1610->nonCriticalExtension && sib1_v1610->nonCriticalExtension->nonCriticalExtension) {
|
||||
NR_SIB1_v1700_IEs_t *sib1_v17 = sib1_v1610->nonCriticalExtension->nonCriticalExtension;
|
||||
schedInfo17 = sib1_v17->si_SchedulingInfo_v1700;
|
||||
}
|
||||
}
|
||||
|
||||
// convert periodicity enum type into actual frames number
|
||||
int frame = 8 << sib19_sched_info->si_Periodicity_r17;
|
||||
|
||||
int time_domain_allocation = 1; // row 0 of pdsch tda common table
|
||||
int L_max;
|
||||
switch (scc->ssb_PositionsInBurst->present) {
|
||||
case 1:
|
||||
L_max = 4;
|
||||
break;
|
||||
case 2:
|
||||
L_max = 8;
|
||||
break;
|
||||
case 3:
|
||||
L_max = 64;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
|
||||
scc->ssb_PositionsInBurst->present);
|
||||
int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
|
||||
int window_length_sl = 5 << schedInfo->si_WindowLength;
|
||||
int window_length_f = (window_length_sl / n_slots_frame) + ((window_length_sl % n_slots_frame) > 0);
|
||||
int num_ssb = cc->num_active_ssb;
|
||||
// number of PDCCH monitoring occasions in SI-window
|
||||
int period, offset;
|
||||
get_monitoring_period_offset(ss, &period, &offset);
|
||||
// The UE assumes that, in the SI window, PDCCH for an SI message is transmitted
|
||||
// in at least one PDCCH monitoring occasion corresponding to each transmitted SSB
|
||||
// frame and slot relative to start of window
|
||||
// The [x×N+K]th PDCCH monitoring occasion(s) for SI message in SI-window corresponds to the Kth transmitted SSB
|
||||
// in our implmentation we transmit only once per SSB per window so N = 1
|
||||
// Section 5.2.2.3.2 of 38.331
|
||||
int temp_slot = offset % n_slots_frame;
|
||||
int temp_frame = offset / n_slots_frame;
|
||||
int rel_slot[num_ssb];
|
||||
int rel_frame[num_ssb];
|
||||
int ssb = 0;
|
||||
while (ssb < num_ssb) {
|
||||
AssertFatal(temp_frame < window_length_f, "Couldn't fit %d SSB in window length of %d slots\n", num_ssb, window_length_sl);
|
||||
if (is_dl_slot(temp_slot, &gNB_mac->frame_structure)) {
|
||||
rel_slot[ssb] = temp_slot;
|
||||
rel_frame[ssb] = temp_frame;
|
||||
ssb++;
|
||||
}
|
||||
temp_frame += (temp_slot + period) / n_slots_frame;
|
||||
temp_slot = (temp_slot + period) % n_slots_frame;
|
||||
}
|
||||
|
||||
const int window_length = 10;
|
||||
for (int i = 0; i < L_max; i++) {
|
||||
for (int ssb = 0; ssb < num_ssb; ssb++) {
|
||||
for (int i = 0; i < schedInfo->schedulingInfoList.list.count; i++) {
|
||||
NR_SchedulingInfo_t *schedulingInfo = schedInfo->schedulingInfoList.list.array[i];
|
||||
if (test_other_sib_sched_occasion(i,
|
||||
window_length_sl,
|
||||
schedulingInfo->si_Periodicity,
|
||||
n_slots_frame,
|
||||
frame,
|
||||
slot,
|
||||
rel_frame[ssb],
|
||||
rel_slot[ssb]))
|
||||
continue;
|
||||
|
||||
NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i];
|
||||
if(((frameP - 1) % frame == 0) &&
|
||||
(slotP == ((sib19_sched_info->si_WindowPosition_r17 % window_length) - 1)) &&
|
||||
(type0_PDCCH_CSS_config->num_rbs > 0)) {
|
||||
other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 0);
|
||||
}
|
||||
if (!schedInfo17)
|
||||
continue;
|
||||
for (int i = 0; i < schedInfo17->schedulingInfoList2_r17.list.count; i++) {
|
||||
NR_SchedulingInfo2_r17_t *schedulingInfo2_r17 = schedInfo17->schedulingInfoList2_r17.list.array[i];
|
||||
if (test_other_sib_sched_occasion(schedulingInfo2_r17->si_WindowPosition_r17,
|
||||
window_length_sl,
|
||||
schedulingInfo2_r17->si_Periodicity_r17,
|
||||
n_slots_frame,
|
||||
frame,
|
||||
slot,
|
||||
rel_frame[ssb],
|
||||
rel_slot[ssb]))
|
||||
continue;
|
||||
|
||||
const int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame;
|
||||
int beam_index = get_fapi_beamforming_index(gNB_mac, i);
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, beam_index, n_slots_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SIB19 corresponding to SSB %d in any available beam\n", i);
|
||||
LOG_D(NR_MAC,"(%d.%d) SIB19 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index);
|
||||
|
||||
NR_tda_info_t tda_info = set_tda_info_from_list(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList, time_domain_allocation);
|
||||
LOG_D(NR_MAC,"tda_info.startSymbolIndex: %d, tda_info.nrOfSymbols: %d\n", tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
|
||||
AssertFatal((tda_info.startSymbolIndex + tda_info.nrOfSymbols) < 14, "SIB19 TDA %d would cause overlap with CSI-RS. Please select a different SIB1 TDA.\n", time_domain_allocation);
|
||||
|
||||
NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc,
|
||||
NULL,
|
||||
&tda_info,
|
||||
1);
|
||||
|
||||
// Configure sched_osi for SIB19
|
||||
uint32_t TBS = schedule_control_other_si(module_idP,
|
||||
CC_id,
|
||||
type0_PDCCH_CSS_config,
|
||||
time_domain_allocation,
|
||||
&dmrs_parms,
|
||||
&tda_info,
|
||||
candidate_idx,
|
||||
beam.idx,
|
||||
sib19_bcch_length);
|
||||
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
|
||||
int pdu_index = gNB_mac->pdu_index[0]++;
|
||||
|
||||
nr_fill_nfapi_dl_SIB_pdu(module_idP,
|
||||
gNB_mac->sched_osi,
|
||||
NULL,
|
||||
dl_req,
|
||||
pdu_index,
|
||||
type0_PDCCH_CSS_config,
|
||||
TBS,
|
||||
tda_info.startSymbolIndex,
|
||||
tda_info.nrOfSymbols,
|
||||
beam_index);
|
||||
|
||||
const int ntx_req = TX_req->Number_of_PDUs;
|
||||
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
|
||||
|
||||
// Data to be transmitted
|
||||
memcpy(tx_req->TLVs[0].value.direct, sib19_bcch_pdu, TBS);
|
||||
|
||||
tx_req->PDU_length = TBS;
|
||||
tx_req->PDU_index = pdu_index;
|
||||
tx_req->num_TLV = 1;
|
||||
tx_req->TLVs[0].length = TBS + 2;
|
||||
TX_req->Number_of_PDUs++;
|
||||
TX_req->SFN = frameP;
|
||||
TX_req->Slot = slotP;
|
||||
|
||||
type0_PDCCH_CSS_config->active = false;
|
||||
|
||||
T(T_GNB_MAC_DL_PDU_WITH_DATA,
|
||||
T_INT(module_idP),
|
||||
T_INT(CC_id),
|
||||
T_INT(SI_RNTI),
|
||||
T_INT(frameP),
|
||||
T_INT(slotP),
|
||||
T_INT(0 /* harq_pid */),
|
||||
T_BUFFER(sib19_bcch_pdu, sib19_bcch_length));
|
||||
other_sib_sched_control(module_idP, frame, slot, ssb, ss, DL_req, TX_req, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1045,7 +1045,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
LOG_D(NR_MAC,"Trying to configure DL pdcch for UE %04x, bwp %d, cs %d\n", UE->rnti, bwp_id, coresetid);
|
||||
NR_ControlResourceSet_t *coreset = sched_ctrl->coreset;
|
||||
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch, false);
|
||||
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch);
|
||||
gNB_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu;
|
||||
}
|
||||
|
||||
|
||||
@@ -281,8 +281,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx)
|
||||
NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
|
||||
const NR_UE_DL_BWP_t *dl_bwp,
|
||||
const NR_tda_info_t *tda_info,
|
||||
const int Layers) {
|
||||
|
||||
const int Layers)
|
||||
{
|
||||
NR_pdsch_dmrs_t dmrs = {0};
|
||||
int frontloaded_symb = 1; // default value
|
||||
nr_dci_format_t dci_format = dl_bwp ? dl_bwp->dci_format : NR_DL_DCI_FORMAT_1_0;
|
||||
@@ -732,12 +732,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
int max_mcs,
|
||||
frame_t frame)
|
||||
{
|
||||
/* first call: everything is zero. Initialize to sensible default */
|
||||
if (bler_stats->last_frame == 0 && bler_stats->mcs == 0) {
|
||||
bler_stats->last_frame = frame;
|
||||
bler_stats->mcs = 9;
|
||||
bler_stats->bler = (bler_options->lower + bler_options->upper) / 2.0f;
|
||||
}
|
||||
int diff = frame - bler_stats->last_frame;
|
||||
if (diff < 0) // wrap around
|
||||
diff += 1024;
|
||||
@@ -756,11 +750,11 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
int new_mcs = old_mcs;
|
||||
if (bler_stats->bler < bler_options->lower && old_mcs < max_mcs && num_dl_sched > 3)
|
||||
new_mcs += 1;
|
||||
else if ((bler_stats->bler > bler_options->upper && old_mcs > 6) // above threshold
|
||||
|| (num_dl_sched <= 3 && old_mcs > 9)) // no activity
|
||||
else if (bler_stats->bler > bler_options->upper || num_dl_sched <= 3) // above threshold or no activity
|
||||
new_mcs -= 1;
|
||||
// else we are within threshold boundaries
|
||||
|
||||
new_mcs = max(new_mcs, bler_options->min_mcs);
|
||||
bler_stats->last_frame = frame;
|
||||
bler_stats->mcs = new_mcs;
|
||||
memcpy(bler_stats->rounds, stats->rounds, sizeof(stats->rounds));
|
||||
@@ -865,12 +859,8 @@ int nr_get_default_pucch_res(int pucch_ResourceCommon) {
|
||||
return(default_pucch_csset[pucch_ResourceCommon]);
|
||||
}
|
||||
|
||||
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
|
||||
NR_ControlResourceSet_t *coreset,
|
||||
NR_sched_pdcch_t *pdcch,
|
||||
bool otherSI) {
|
||||
|
||||
|
||||
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *pdcch)
|
||||
{
|
||||
pdcch_pdu->BWPSize = pdcch->BWPSize;
|
||||
pdcch_pdu->BWPStart = pdcch->BWPStart;
|
||||
pdcch_pdu->SubcarrierSpacing = pdcch->SubcarrierSpacing;
|
||||
@@ -879,19 +869,23 @@ void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
|
||||
|
||||
pdcch_pdu->DurationSymbols = coreset->duration;
|
||||
|
||||
for (int i=0;i<6;i++)
|
||||
for (int i = 0; i < 6; i++)
|
||||
pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i];
|
||||
|
||||
LOG_D(MAC,"Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %d\n",
|
||||
pdcch_pdu->BWPStart,pdcch_pdu->BWPSize,(int)pdcch_pdu->SubcarrierSpacing,(int)coreset->frequencyDomainResources.buf[0],(int)coreset->duration);
|
||||
LOG_D(NR_MAC,
|
||||
"Coreset : BWPstart %d, BWPsize %d, SCS %d, freq %x, , duration %ld\n",
|
||||
pdcch_pdu->BWPStart,
|
||||
pdcch_pdu->BWPSize,
|
||||
pdcch_pdu->SubcarrierSpacing,
|
||||
coreset->frequencyDomainResources.buf[0],
|
||||
coreset->duration);
|
||||
|
||||
pdcch_pdu->CceRegMappingType = pdcch->CceRegMappingType;
|
||||
pdcch_pdu->RegBundleSize = pdcch->RegBundleSize;
|
||||
pdcch_pdu->InterleaverSize = pdcch->InterleaverSize;
|
||||
pdcch_pdu->ShiftIndex = pdcch->ShiftIndex;
|
||||
|
||||
pdcch_pdu->CoreSetType =
|
||||
(otherSI || coreset->controlResourceSetId != 0) ? NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG : NFAPI_NR_CSET_CONFIG_MIB_SIB1;
|
||||
pdcch_pdu->CoreSetType = coreset->controlResourceSetId != 0 ? NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG : NFAPI_NR_CSET_CONFIG_MIB_SIB1;
|
||||
|
||||
//precoderGranularity
|
||||
pdcch_pdu->precoderGranularity = coreset->precoderGranularity;
|
||||
@@ -2492,6 +2486,13 @@ void reset_srs_stats(NR_UE_info_t *UE) {
|
||||
}
|
||||
}
|
||||
|
||||
static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats_t *bler_stats, frame_t frame)
|
||||
{
|
||||
bler_stats->last_frame = frame;
|
||||
bler_stats->mcs = bler_options->min_mcs;
|
||||
bler_stats->bler = (float)(bler_options->lower + bler_options->upper) / 2.0f;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup)
|
||||
{
|
||||
@@ -2522,6 +2523,10 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
|
||||
sched_ctrl->sched_srs.slot = -1;
|
||||
sched_ctrl->pdcch_cl_adjust = 0;
|
||||
|
||||
// Initialize bler_stats
|
||||
init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame);
|
||||
init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame);
|
||||
|
||||
// initialize LCID structure
|
||||
seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t));
|
||||
|
||||
@@ -3322,7 +3327,7 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
|
||||
int CC_id = 0;
|
||||
int srb_id = 1;
|
||||
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig;
|
||||
const NR_ServingCellConfig_t *sccd = UE->is_redcap ? NULL : mac->common_channels[CC_id].pre_ServingCellConfig;
|
||||
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = cellGroupConfig;
|
||||
|
||||
@@ -100,7 +100,7 @@ static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot,
|
||||
#define MIN_RSRP_VALUE -141
|
||||
#define MAX_RSRP_VALUE -43
|
||||
|
||||
//Measured RSRP Values Table 10.1.16.1-1 from 36.133
|
||||
//Measured RSRP Values Table 10.1.16.1-1 from 38.133
|
||||
//Stored all the upper limits[Max RSRP Value of corresponding index]
|
||||
//stored -1 for invalid values
|
||||
static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = {
|
||||
@@ -119,7 +119,7 @@ static const int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1 // 120 - 127
|
||||
};
|
||||
|
||||
//Differential RSRP values Table 10.1.6.1-2 from 36.133
|
||||
//Differential RSRP values Table 10.1.6.1-2 from 38.133
|
||||
//Stored the upper limits[MAX RSRP Value]
|
||||
static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = {
|
||||
0,
|
||||
|
||||
@@ -350,6 +350,7 @@ static int nr_process_mac_pdu(instance_t module_idP,
|
||||
|
||||
if (lcid == UL_SCH_LCID_CCCH_48_BITS_REDCAP) {
|
||||
LOG_I(MAC, "UE with RNTI %04x is RedCap\n", UE->rnti);
|
||||
UE->is_redcap = true;
|
||||
}
|
||||
|
||||
if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) {
|
||||
@@ -2050,7 +2051,6 @@ static void pf_ul(module_id_t module_id,
|
||||
fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx);
|
||||
|
||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||
sched_pusch->mcs = max(nrmac->min_grant_mcs, sched_pusch->mcs);
|
||||
update_ul_ue_R_Qm(sched_pusch->mcs, current_BWP->mcs_table, current_BWP->pusch_Config, &sched_pusch->R, &sched_pusch->Qm);
|
||||
sched_pusch->rbStart = rbStart;
|
||||
sched_pusch->rbSize = min_rb;
|
||||
@@ -2680,7 +2680,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_
|
||||
ul_dci_request_pdu->PDUSize = (uint8_t)(4+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
|
||||
pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
|
||||
ul_dci_req->numPdus += 1;
|
||||
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch, false);
|
||||
nr_configure_pdcch(pdcch_pdu, coreset, &sched_ctrl->sched_pdcch);
|
||||
pdcch_pdu_coreset[coresetid] = pdcch_pdu;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,8 @@ void mac_top_init_gNB(ngran_node_t node_type,
|
||||
void nr_mac_send_f1_setup_req(void);
|
||||
|
||||
void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *mac_config);
|
||||
void nr_fill_sched_osi(gNB_MAC_INST *nrmac, const struct NR_SetupRelease_PDCCH_ConfigCommon *pdcch_ConfigCommon);
|
||||
void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_t cellID, int tac);
|
||||
void nr_mac_configure_sib19(gNB_MAC_INST *nrmac);
|
||||
|
||||
bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]);
|
||||
bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
|
||||
bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
|
||||
|
||||
@@ -97,13 +95,11 @@ void schedule_nr_sib1(module_id_t module_idP,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req);
|
||||
|
||||
void schedule_nr_sib19(module_id_t module_idP,
|
||||
frame_t frameP,
|
||||
slot_t slotP,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req,
|
||||
int sib19_bcch_length,
|
||||
uint8_t *sib19_bcch_pdu);
|
||||
void schedule_nr_other_sib(module_id_t module_idP,
|
||||
frame_t frame,
|
||||
slot_t slot,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req);
|
||||
|
||||
struct NR_SchedulingInfo2_r17* find_sib19_sched_info(const struct NR_SI_SchedulingInfo_v1700*);
|
||||
|
||||
@@ -215,10 +211,7 @@ void find_search_space(int ss_type,
|
||||
NR_BWP_Downlink_t *bwp,
|
||||
NR_SearchSpace_t *ss);
|
||||
|
||||
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
|
||||
NR_ControlResourceSet_t *coreset,
|
||||
NR_sched_pdcch_t *pdcch,
|
||||
bool otherSI);
|
||||
void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_ControlResourceSet_t *coreset, NR_sched_pdcch_t *pdcch);
|
||||
|
||||
NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac,
|
||||
NR_SearchSpace_t *ss,
|
||||
@@ -474,4 +467,8 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid);
|
||||
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti);
|
||||
void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected);
|
||||
|
||||
void prepare_du_configuration_update(gNB_MAC_INST *mac,
|
||||
f1ap_served_cell_info_t *info,
|
||||
NR_BCCH_BCH_Message_t *mib,
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1);
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -165,7 +165,15 @@ void f1_setup_response(const f1ap_setup_resp_t *resp)
|
||||
AssertFatal(check_plmn_identity(&du_cell->plmn, &cu_cell->plmn), "PLMN mismatch\n");
|
||||
AssertFatal(du_cell->nr_pci == cu_cell->nrpci, "PCI mismatch: DU %d vs CU %d\n", du_cell->nr_pci, cu_cell->nrpci);
|
||||
|
||||
AssertFatal(cu_cell->num_SI == 0, "handling of CU-provided SIBs: not implemented\n");
|
||||
// we can configure other SIB only after having received the ones generated by CU
|
||||
bool update = nr_mac_configure_other_sib(mac, cu_cell->num_SI, cu_cell->SI_msg);
|
||||
if (update) {
|
||||
f1ap_setup_req_t *sr = mac->f1_config.setup_req;
|
||||
DevAssert(sr->num_cells_available == 1);
|
||||
f1ap_served_cell_info_t *info = &sr->cell[0].info;
|
||||
NR_COMMON_channels_t *cc = &mac->common_channels[0];
|
||||
prepare_du_configuration_update(mac, info, cc->mib, cc->sib1);
|
||||
}
|
||||
|
||||
mac->f1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp));
|
||||
AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n");
|
||||
|
||||
@@ -276,7 +276,7 @@ typedef struct {
|
||||
frame_type_t frame_type;
|
||||
NR_BCCH_BCH_Message_t *mib;
|
||||
NR_BCCH_DL_SCH_Message_t *sib1;
|
||||
NR_BCCH_DL_SCH_Message_t *sib19;
|
||||
seq_arr_t *du_SIBs;
|
||||
NR_ServingCellConfigCommon_t *ServingCellConfigCommon;
|
||||
/// pre-configured ServingCellConfig that is default for every UE
|
||||
NR_ServingCellConfig_t *pre_ServingCellConfig;
|
||||
@@ -285,9 +285,9 @@ typedef struct {
|
||||
/// Outgoing BCCH pdu for PHY
|
||||
uint8_t sib1_bcch_pdu[NR_MAX_SIB_LENGTH / 8];
|
||||
int sib1_bcch_length;
|
||||
/// used for sib19 data
|
||||
uint8_t sib19_bcch_pdu[NR_MAX_SIB_LENGTH / 8];
|
||||
int sib19_bcch_length;
|
||||
/// used for otherSIB data
|
||||
uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8];
|
||||
int other_sib_bcch_length[2];
|
||||
/// Template for RA computations
|
||||
NR_RA_t ra[NR_NB_RA_PROC_MAX];
|
||||
/// VRB map for common channels
|
||||
@@ -691,19 +691,6 @@ typedef struct {
|
||||
float pdcch_cl_adjust;
|
||||
} NR_UE_sched_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
NR_SearchSpace_t *search_space;
|
||||
NR_ControlResourceSet_t *coreset;
|
||||
|
||||
NR_sched_pdcch_t sched_pdcch;
|
||||
NR_sched_pdsch_t sched_pdsch;
|
||||
|
||||
uint32_t num_total_bytes;
|
||||
|
||||
int cce_index;
|
||||
uint8_t aggregation_level;
|
||||
} NR_UE_sched_osi_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
uicc_t *uicc;
|
||||
} NRUEcontext_t;
|
||||
@@ -738,6 +725,7 @@ typedef struct NR_mac_stats {
|
||||
typedef struct NR_bler_options {
|
||||
double upper;
|
||||
double lower;
|
||||
uint8_t min_mcs;
|
||||
uint8_t max_mcs;
|
||||
uint8_t harq_round_max;
|
||||
} NR_bler_options_t;
|
||||
@@ -783,6 +771,7 @@ typedef struct {
|
||||
float ul_thr_ue;
|
||||
float dl_thr_ue;
|
||||
long pdsch_HARQ_ACK_Codebook;
|
||||
bool is_redcap;
|
||||
} NR_UE_info_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -927,9 +916,8 @@ typedef struct gNB_MAC_INST_s {
|
||||
|
||||
nr_mac_config_t radio_config;
|
||||
|
||||
NR_UE_sched_osi_ctrl_t *sched_osi;
|
||||
NR_UE_sched_ctrl_t *sched_ctrlCommon;
|
||||
|
||||
NR_sched_pdcch_t *sched_pdcch_otherSI;
|
||||
uint16_t cset0_bwp_start;
|
||||
uint16_t cset0_bwp_size;
|
||||
NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config[64];
|
||||
@@ -938,7 +926,6 @@ typedef struct gNB_MAC_INST_s {
|
||||
NR_bler_options_t dl_bler;
|
||||
NR_bler_options_t ul_bler;
|
||||
uint8_t min_grant_prb;
|
||||
uint8_t min_grant_mcs;
|
||||
bool identity_pm;
|
||||
int precoding_matrix_size[NR_MAX_NB_LAYERS];
|
||||
int fapi_beam_index[MAX_NUM_OF_SSB];
|
||||
|
||||
@@ -155,13 +155,13 @@ typedef struct nr_pdcp_entity_t {
|
||||
stream_security_context_t *security_context;
|
||||
void (*cipher)(stream_security_context_t *security_context,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction);
|
||||
int bearer, uint32_t count, int direction);
|
||||
void (*free_security)(stream_security_context_t *security_context);
|
||||
stream_security_context_t *integrity_context;
|
||||
void (*integrity)(stream_security_context_t *integrity_context,
|
||||
unsigned char *out,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction);
|
||||
int bearer, uint32_t count, int direction);
|
||||
void (*free_integrity)(stream_security_context_t *integrity_context);
|
||||
/* security/integrity algorithms need to know uplink/downlink information
|
||||
* which is reverse for gnb and ue, so we need to know if this
|
||||
|
||||
@@ -42,7 +42,7 @@ stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_
|
||||
void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context,
|
||||
unsigned char *out,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction)
|
||||
int bearer, uint32_t count, int direction)
|
||||
{
|
||||
nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)integrity_context;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_
|
||||
void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context,
|
||||
unsigned char *out,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction);
|
||||
int bearer, uint32_t count, int direction);
|
||||
|
||||
void nr_pdcp_integrity_nia1_free_integrity(stream_security_context_t *integrity_context);
|
||||
|
||||
|
||||
@@ -39,14 +39,13 @@ stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]
|
||||
return (stream_security_context_t *)ctx;
|
||||
}
|
||||
|
||||
void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction)
|
||||
void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, uint32_t count, int direction)
|
||||
{
|
||||
DevAssert(integrity_context != NULL);
|
||||
DevAssert(out != NULL);
|
||||
DevAssert(buffer != NULL);
|
||||
DevAssert(length > -1);
|
||||
DevAssert(bearer > 0 && bearer < 33);
|
||||
DevAssert(count > -1);
|
||||
|
||||
cbc_cmac_ctx_t *ctx = (cbc_cmac_ctx_t *)integrity_context;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]
|
||||
void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context,
|
||||
unsigned char *out,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction);
|
||||
int bearer, uint32_t count, int direction);
|
||||
|
||||
void nr_pdcp_integrity_nia2_free_integrity(stream_security_context_t *integrity_context);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context,
|
||||
unsigned char *buffer,
|
||||
int length,
|
||||
int bearer,
|
||||
int count,
|
||||
uint32_t count,
|
||||
int direction)
|
||||
{
|
||||
nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)security_context;
|
||||
|
||||
@@ -30,7 +30,7 @@ void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context,
|
||||
unsigned char *buffer,
|
||||
int length,
|
||||
int bearer,
|
||||
int count,
|
||||
uint32_t count,
|
||||
int direction);
|
||||
|
||||
void nr_pdcp_security_nea1_free_security(stream_security_context_t *security_context);
|
||||
|
||||
@@ -36,14 +36,13 @@ stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_k
|
||||
return (stream_security_context_t *)ciphering_key;
|
||||
}
|
||||
|
||||
void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, int count, int direction)
|
||||
void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, uint32_t count, int direction)
|
||||
{
|
||||
DevAssert(security_context != NULL);
|
||||
DevAssert(buffer != NULL);
|
||||
DevAssert(length > 0);
|
||||
DevAssert(bearer > -1 && bearer < 32);
|
||||
DevAssert(direction > -1 && direction < 2);
|
||||
DevAssert(count > -1);
|
||||
|
||||
aes_128_t p = {0};
|
||||
const uint8_t *ciphering_key = (uint8_t const *)security_context;
|
||||
|
||||
@@ -28,7 +28,7 @@ stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_k
|
||||
|
||||
void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction);
|
||||
int bearer, uint32_t count, int direction);
|
||||
|
||||
void nr_pdcp_security_nea2_free_security(stream_security_context_t *security_context);
|
||||
|
||||
|
||||
@@ -18,10 +18,11 @@ else()
|
||||
message(FATAL_ERROR "unknown M2AP_RELEASE ${M2AP_RELEASE}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${m2ap_source} ${m2ap_headers}
|
||||
COMMAND ASN1C_PREFIX=M2AP_ ${ASN1C_EXEC} -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}
|
||||
COMMENT "Generating M2AP source files from ${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}"
|
||||
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${M2AP_GRAMMAR}
|
||||
"M2AP_"
|
||||
OUTPUT ${m2ap_source} ${m2ap_headers}
|
||||
OPTIONS -gen-APER -no-gen-BER -no-gen-JER -no-gen-OER -gen-UPER -fcompound-names -no-gen-example -fno-include-deps
|
||||
COMMENT "M2AP source files"
|
||||
)
|
||||
|
||||
add_library(asn1_m2ap ${m2ap_source})
|
||||
|
||||
@@ -1108,7 +1108,8 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len)
|
||||
{
|
||||
return nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len);
|
||||
nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// L2 Abstraction Layer
|
||||
|
||||
@@ -10,10 +10,11 @@ else()
|
||||
message(FATAL_ERROR "unknown LTE_RRC_RELEASE ${LTE_RRC_RELEASE}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${lte_rrc_source} ${lte_rrc_headers}
|
||||
COMMAND ASN1C_PREFIX=LTE_ ${ASN1C_EXEC} -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}
|
||||
COMMENT "Generating LTE RRC source file from ${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}"
|
||||
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${LTE_RRC_GRAMMAR}
|
||||
"LTE_"
|
||||
OUTPUT ${lte_rrc_source} ${lte_rrc_headers}
|
||||
OPTIONS -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example
|
||||
COMMENT "LTE RRC source files"
|
||||
)
|
||||
|
||||
# Many other targets include LTE RRC ASN.1 headers, without actually needing
|
||||
|
||||
@@ -10,10 +10,11 @@ else()
|
||||
message(FATAL_ERROR "unknown NR_RRC_RELEASE ${NR_RRC_RELEASE}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${nr_rrc_source} ${nr_rrc_headers}
|
||||
COMMAND ASN1C_PREFIX=NR_ ${ASN1C_EXEC} -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -findirect-choice -D ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}
|
||||
COMMENT "Generating NR RRC source file from ${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}"
|
||||
run_asn1c(${CMAKE_CURRENT_SOURCE_DIR}/${NR_RRC_GRAMMAR}
|
||||
"NR_"
|
||||
OUTPUT ${nr_rrc_source} ${nr_rrc_headers}
|
||||
OPTIONS -pdu=all -fcompound-names -gen-UPER -no-gen-BER -no-gen-JER -no-gen-OER -gen-APER -no-gen-example -findirect-choice
|
||||
COMMENT "NR RRC source files"
|
||||
)
|
||||
|
||||
# Many other targets include NR RRC ASN.1 headers, without actually needing the
|
||||
|
||||
@@ -197,51 +197,37 @@ int xer_nr_sprint(char *string, size_t string_size, asn_TYPE_descriptor_t *td, v
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int do_SIB23_NR(rrc_gNB_carrier_data_t *carrier)
|
||||
int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc)
|
||||
{
|
||||
asn_enc_rval_t enc_rval;
|
||||
SystemInformation_IEs__sib_TypeAndInfo__Member *sib2 = NULL;
|
||||
SystemInformation_IEs__sib_TypeAndInfo__Member *sib3 = NULL;
|
||||
NR_SIB2_t *sib2 = calloc(1, sizeof(*sib2));
|
||||
sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB0;
|
||||
struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars *speed = calloc(1, sizeof(*speed));
|
||||
NR_MobilityStateParameters_t mobilityStateParameters = {0};
|
||||
mobilityStateParameters.t_Evaluation = NR_MobilityStateParameters__t_Evaluation_s30;
|
||||
mobilityStateParameters.t_HystNormal = NR_MobilityStateParameters__t_HystNormal_s30;
|
||||
mobilityStateParameters.n_CellChangeMedium = 1;
|
||||
mobilityStateParameters.n_CellChangeHigh = 2;
|
||||
speed->mobilityStateParameters = mobilityStateParameters;
|
||||
struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF qhyst = {0};
|
||||
qhyst.sf_Medium = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_Medium_dB_4;
|
||||
qhyst.sf_High = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_High_dB_6;
|
||||
speed->q_HystSF = qhyst;
|
||||
sib2->cellReselectionInfoCommon.speedStateReselectionPars = speed;
|
||||
sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 0; // INTEGER (0..7)
|
||||
sib2->cellReselectionServingFreqInfo.threshServingLowP = 0;
|
||||
NR_ReselectionThresholdQ_t *threshServingLowQ = calloc(1, sizeof(*threshServingLowQ));
|
||||
*threshServingLowQ = 0;
|
||||
sib2->cellReselectionServingFreqInfo.threshServingLowQ = threshServingLowQ;
|
||||
sib2->intraFreqCellReselectionInfo.q_RxLevMin = -56; // INTEGER (-70..-22)
|
||||
sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 22; // INTEGER (0..31)
|
||||
sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 1; // INTEGER (0..7)
|
||||
sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true;
|
||||
sib2->intraFreqCellReselectionInfo.smtc = ssbmtc;
|
||||
|
||||
NR_BCCH_DL_SCH_Message_t *sib_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t));
|
||||
sib_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1;
|
||||
sib_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1));
|
||||
sib_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation;
|
||||
sib_message->message.choice.c1->choice.systemInformation = CALLOC(1,sizeof(struct NR_SystemInformation));
|
||||
|
||||
struct NR_SystemInformation *sib = sib_message->message.choice.c1->choice.systemInformation;
|
||||
sib->criticalExtensions.present = NR_SystemInformation__criticalExtensions_PR_systemInformation;
|
||||
sib->criticalExtensions.choice.systemInformation = CALLOC(1, sizeof(struct NR_SystemInformation_IEs));
|
||||
|
||||
struct NR_SystemInformation_IEs *ies = sib->criticalExtensions.choice.systemInformation;
|
||||
sib2 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member));
|
||||
sib2->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2;
|
||||
sib2->choice.sib2 = CALLOC(1, sizeof(struct NR_SIB2));
|
||||
sib2->choice.sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB1;
|
||||
sib2->choice.sib2->cellReselectionServingFreqInfo.threshServingLowP = 2; // INTEGER (0..31)
|
||||
sib2->choice.sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 2; // INTEGER (0..7)
|
||||
sib2->choice.sib2->intraFreqCellReselectionInfo.q_RxLevMin = -50; // INTEGER (-70..-22)
|
||||
sib2->choice.sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 2; // INTEGER (0..31)
|
||||
sib2->choice.sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 2; // INTEGER (0..7)
|
||||
sib2->choice.sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true;
|
||||
asn1cSeqAdd(&ies->sib_TypeAndInfo.list, sib2);
|
||||
|
||||
sib3 = CALLOC(1, sizeof(SystemInformation_IEs__sib_TypeAndInfo__Member));
|
||||
sib3->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3;
|
||||
sib3->choice.sib3 = CALLOC(1, sizeof(struct NR_SIB3));
|
||||
asn1cSeqAdd(&ies->sib_TypeAndInfo.list, sib3);
|
||||
|
||||
//encode SIB to data
|
||||
// carrier->SIB23 = (uint8_t *) malloc16(128);
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message,
|
||||
NULL,
|
||||
(void *)sib_message,
|
||||
carrier->SIB23,
|
||||
100);
|
||||
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_DL_SCH_Message, sib_message);
|
||||
return((enc_rval.encoded+7)/8);
|
||||
ssize_t size = uper_encode_to_new_buffer(&asn_DEF_NR_SIB2, NULL, (void *)sib2, (void **)msg_SIB2);
|
||||
AssertFatal (size > 0, "ASN1 message encoding failed (encoded %lu bytes)!\n", size);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2);
|
||||
return size;
|
||||
}
|
||||
|
||||
int do_RRCReject(uint8_t *const buffer)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user