Commit 48b630f4 authored by Remi Hardy's avatar Remi Hardy

Merge branch 'integration_2020_wk45' into 'develop'

MR902 Nr mac ssb ro ue idcc
- Construction of SSB-RO mapping table on the UE
- RO selection based on SSB index
- RACH preamble selection based on SSB index in a selected RO
- RA-RNTI calculation
  

MR928 nr: add MAC PDU traces for wireshark
- The T tracer macpdu2wireshark has been modified to handle the new traces. The usage is the same as for LTE.  

MR929 RA fixes for NR UE  

MR938 CI: Parse UE TUN interface correctly in S1 mode
- The TUN interface configuration is changed to use program "ip" only. 
- The CI script parsing is changed accordingly: the pipeline will recognize the attempt to bring up the interface of the first UE.

MR933 nr rlc: bugfix 
- ret.next was not set in a particular case
parents 709d1f5e bd3b9090
...@@ -45,8 +45,8 @@ gNBs = ...@@ -45,8 +45,8 @@ gNBs =
dl_carrierBandwidth = 106; dl_carrierBandwidth = 106;
#initialDownlinkBWP #initialDownlinkBWP
#genericParameters #genericParameters
# this is RBstart=0,L=50 (275*(L-1))+RBstart # this is RBstart=41,L=24 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 13475; initialDLBWPlocationAndBandwidth = 6366;
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1; initialDLBWPsubcarrierSpacing = 1;
...@@ -59,7 +59,7 @@ gNBs = ...@@ -59,7 +59,7 @@ gNBs =
#initialULBWPmappingType #initialULBWPmappingType
#0=typeA,1=typeB #0=typeA,1=typeB
initialDLBWPmappingType_0 = 0; initialDLBWPmappingType_0 = 0;
#this is SS=2,L=3 #this is SS=1,L=13
initialDLBWPstartSymbolAndLength_0 = 40; initialDLBWPstartSymbolAndLength_0 = 40;
initialDLBWPk0_1 = 0; initialDLBWPk0_1 = 0;
...@@ -74,7 +74,7 @@ gNBs = ...@@ -74,7 +74,7 @@ gNBs =
initialDLBWPk0_3 = 0; initialDLBWPk0_3 = 0;
initialDLBWPmappingType_3 = 0; initialDLBWPmappingType_3 = 0;
#this is SS=1,L=4 #this is SS=1,L=5
initialDLBWPstartSymbolAndLength_3 = 57; initialDLBWPstartSymbolAndLength_3 = 57;
#uplinkConfigCommon #uplinkConfigCommon
...@@ -89,7 +89,7 @@ gNBs = ...@@ -89,7 +89,7 @@ gNBs =
pMax = 20; pMax = 20;
#initialUplinkBWP #initialUplinkBWP
#genericParameters #genericParameters
initialULBWPlocationAndBandwidth = 13475; initialULBWPlocationAndBandwidth = 6366;
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1; initialULBWPsubcarrierSpacing = 1;
...@@ -249,7 +249,7 @@ RUs = ( ...@@ -249,7 +249,7 @@ RUs = (
eNB_instances = [0]; eNB_instances = [0];
#beamforming 1x4 matrix: #beamforming 1x4 matrix:
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2"; sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2";
clock_src = "external"; clock_src = "external";
} }
); );
......
...@@ -470,7 +470,7 @@ function report_test { ...@@ -470,7 +470,7 @@ function report_test {
then then
NB_UE_TUNNEL_UP=`egrep -c "Interface oaitun_ue1 successfully configured" $UE_LOG` NB_UE_TUNNEL_UP=`egrep -c "Interface oaitun_ue1 successfully configured" $UE_LOG`
else else
NB_UE_TUNNEL_UP=`egrep -c "executing ifconfig oaitun_ue1" $UE_LOG` NB_UE_TUNNEL_UP=`egrep -c "ip link set oaitun_ue1 up" $UE_LOG`
fi fi
if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -gt 0 ] && [ $NB_ENB_SYNCED_WITH_UE -gt 0 ] if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -gt 0 ] && [ $NB_ENB_SYNCED_WITH_UE -gt 0 ]
then then
...@@ -768,55 +768,47 @@ function report_test { ...@@ -768,55 +768,47 @@ function report_test {
#RA test (--do-ra option) #RA test (--do-ra option)
# Currently disabled #build log files names
# #build log files names RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log
# RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log RA_UE_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log
# RA_UE_LOG=$ARCHIVES_LOC/ra_check_${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ]
# if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ] then
# then #get rid of full path
# #get rid of full path NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"`
# NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"` NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"`
# NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"` echo " <tr>" >> ./test_simulator_results.html
# echo " <tr>" >> ./test_simulator_results.html echo " <td>$NAME_ENB --- $NAME_UE</td>" >> ./test_simulator_results.html
# echo " <td>$NAME_ENB --- $NAME_UE</td>" >> ./test_simulator_results.html echo " <td>Check if RA proc succeeded</td>" >> ./test_simulator_results.html
# echo " <td>Check if RA proc succeeded</td>" >> ./test_simulator_results.html
# #gNB RA check
# #gNB RA check GNB_RECEIVED=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $RA_ENB_LOG`
# GNB_RECEIVED=`egrep -c "received correctly" $RA_ENB_LOG` #UE RA check
# GNB_CONNECTED=`egrep -c "now 5G connected" $RA_ENB_LOG` UE_RA_PROC_OK=`egrep -c "\[RAPROC\] RA procedure succeeded" $RA_UE_LOG`
# #UE RA check
# UE_RA_PROC_OK=`egrep -c "RA procedure succeeded" $RA_UE_LOG`
# if [ $GNB_RECEIVED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ]
# then
# if [ $GNB_RECEIVED -gt 0 ] && [ $GNB_CONNECTED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ] echo " <td bgcolor = \"green\" >OK</td>" >> ./test_simulator_results.html
# then else
# echo " <td bgcolor = \"green\" >OK</td>" >> ./test_simulator_results.html echo " <td bgcolor = \"red\" >KO</td>" >> ./test_simulator_results.html
# else fi
# echo " <td bgcolor = \"red\" >KO</td>" >> ./test_simulator_results.html
# fi echo " <td><pre>" >> ./test_simulator_results.html
# if [ $GNB_RECEIVED -gt 0 ]
# echo " <td><pre>" >> ./test_simulator_results.html then
# if [ $GNB_RECEIVED -gt 0 ] echo "<font color = \"blue\">- gNB --> RA received</font>" >> ./test_simulator_results.html
# then else
# echo "<font color = \"blue\">- gNB --> RA received</font>" >> ./test_simulator_results.html echo "<font color = \"red\"><b>- gNB RA NOT RECEIVED</b></font>" >> ./test_simulator_results.html
# else fi
# echo "<font color = \"red\"><b>- gNB RA NOT RECEIVED</b></font>" >> ./test_simulator_results.html if [ $UE_RA_PROC_OK -gt 0 ]
# fi then
# if [ $GNB_CONNECTED -gt 0 ] echo "<font color = \"blue\">- NR UE --> RA procedure succeded</font>" >> ./test_simulator_results.html
# then else
# echo "<font color = \"blue\">- gNB --> 5G connected</font>" >> ./test_simulator_results.html echo "<font color = \"red\"><b>- NR UE RA procedure failed</b></font>" >> ./test_simulator_results.html
# else fi
# echo "<font color = \"red\"><b>- gNB NOT 5G CONNECTED</b></font>" >> ./test_simulator_results.html echo " </pre></td>" >> ./test_simulator_results.html
# fi echo " </tr>" >> ./test_simulator_results.html
# if [ $UE_RA_PROC_OK -gt 0 ] fi
# then
# echo "<font color = \"blue\">- NR UE --> RA procedure succeded</font>" >> ./test_simulator_results.html
# else
# echo "<font color = \"red\"><b>- NR UE RA procedure failed</b></font>" >> ./test_simulator_results.html
# fi
# echo " </pre></td>" >> ./test_simulator_results.html
# echo " </tr>" >> ./test_simulator_results.html
# fi
#SYNC test #SYNC test
ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb.log ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb.log
......
...@@ -281,14 +281,35 @@ function check_ra_result { ...@@ -281,14 +281,35 @@ function check_ra_result {
local LOC_GNB_LOG=$1 local LOC_GNB_LOG=$1
local LOC_UE_LOG=$2 local LOC_UE_LOG=$2
#if log files exist
if [ -f $LOC_GNB_LOG ] && [ -f $LOC_UE_LOG ]
then
#gNB RA test #gNB RA test
#console check
echo "Checking gNB Log for RA success" echo "Checking gNB Log for RA success"
egrep "received correctly" $1 egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1
egrep "now 5G connected" $1 #script check
local GNB_COMPLETE=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1`
#UE RA test #UE RA test
#console check
echo 'Checking UE Log for RA success' echo 'Checking UE Log for RA success'
egrep "RA procedure succeeded" $2 egrep "\[RAPROC\] RA procedure succeeded" $2
#script check
local UE_COMPLETE=`egrep -c "\[RAPROC\] RA procedure succeeded" $2`
#generate status
if [ $GNB_COMPLETE -eq 0 ] || [ $UE_COMPLETE -eq 0 ]
then
RA_STATUS=-1
echo "RA test FAILED, could not find the markers"
fi
#case where log files do not exist
else
echo "RA test log files not present"
RA_STATUS=-1
fi
} }
...@@ -1225,16 +1246,6 @@ function start_rf_sim_gnb { ...@@ -1225,16 +1246,6 @@ function start_rf_sim_gnb {
ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1 ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1
rm $1 rm $1
# For the moment, in RA test, no check and no copy of generated raw files
if [ $LOC_RA_TEST -eq 1 ] # RA test
then
sleep 30
echo "echo \"free -m\"" > $1
echo "free -m" >> $1
ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1
rm $1
return 0
fi
local i="0" local i="0"
echo "egrep -c \"got sync\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1 echo "egrep -c \"got sync\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1
...@@ -1258,7 +1269,9 @@ function start_rf_sim_gnb { ...@@ -1258,7 +1269,9 @@ function start_rf_sim_gnb {
GNB_SYNC=1 GNB_SYNC=1
echo "RF-SIM gNB is sync'ed: waiting for UE(s) to connect" echo "RF-SIM gNB is sync'ed: waiting for UE(s) to connect"
fi fi
if [ $LOC_S1_CONFIGURATION -eq 0 ]
# check noS1 config only outside RA test (as it does not support noS1)
if [ $LOC_S1_CONFIGURATION -eq 0 ] && [ $LOC_RA_TEST -eq 0 ]
then then
echo "ifconfig oaitun_enb1 | egrep -c \"inet addr\"" > $1 echo "ifconfig oaitun_enb1 | egrep -c \"inet addr\"" > $1
# Checking oaitun_enb1 interface has now an IP address # Checking oaitun_enb1 interface has now an IP address
...@@ -1341,14 +1354,6 @@ function start_rf_sim_nr_ue { ...@@ -1341,14 +1354,6 @@ function start_rf_sim_nr_ue {
ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1 ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1
rm $1 rm $1
# In case of RA test mode, no UE sync check for the moment.
# To be removed later?
if [ $LOC_RA_TEST -eq 1 ] # RA test
then
sleep 30
NR_UE_SYNC=1
return 0
fi
local i="0" local i="0"
echo "egrep -c \"Initial sync: pbch decoded sucessfully\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1 echo "egrep -c \"Initial sync: pbch decoded sucessfully\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1
while [ $i -lt 10 ] while [ $i -lt 10 ]
...@@ -1372,7 +1377,9 @@ function start_rf_sim_nr_ue { ...@@ -1372,7 +1377,9 @@ function start_rf_sim_nr_ue {
else else
echo "RF-SIM NR-UE is sync'ed w/ gNB" echo "RF-SIM NR-UE is sync'ed w/ gNB"
fi fi
# Checking oaitun_ue1 interface has now an IP address # Checking oaitun_ue1 interface has now an IP address (only outside RA test)
if [ $LOC_RA_TEST -eq 0 ]
then
i="0" i="0"
echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1 echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1
while [ $i -lt 10 ] while [ $i -lt 10 ]
...@@ -1398,8 +1405,7 @@ function start_rf_sim_nr_ue { ...@@ -1398,8 +1405,7 @@ function start_rf_sim_nr_ue {
echo "RF-SIM NR-UE oaitun_ue1 is UP and CONFIGURED" echo "RF-SIM NR-UE oaitun_ue1 is UP and CONFIGURED"
fi fi
sleep 10 sleep 10
fi
} }
...@@ -2196,10 +2202,11 @@ function run_test_on_vm { ...@@ -2196,10 +2202,11 @@ function run_test_on_vm {
NR_STATUS=0 NR_STATUS=0
######### start of RA TEST loop ######### start of RA TEST loop
while [ $try_cnt -lt 1 ] while [ $try_cnt -lt 10 ] #10 because it hardly succeed within CI
do do
SYNC_STATUS=0 SYNC_STATUS=0
RA_STATUS=0
echo "############################################################" echo "############################################################"
echo "${CN_CONFIG} : Starting the gNB" echo "${CN_CONFIG} : Starting the gNB"
...@@ -2241,71 +2248,25 @@ function run_test_on_vm { ...@@ -2241,71 +2248,25 @@ function run_test_on_vm {
echo "############################################################" echo "############################################################"
# Proper check to be done when RA test is working! # Proper check to be done when RA test is working!
#check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE
if [ $RA_STATUS -ne 0 ]
try_cnt=$[$try_cnt+1]
########### end RA test
done
sleep 10
try_cnt="0"
######### start of PHY TEST loop
while [ $try_cnt -lt 4 ]
do
#start RA test
SYNC_STATUS=0
PING_STATUS=0
IPERF_STATUS=0
echo "############################################################"
echo "${CN_CONFIG} : Starting the gNB"
echo "############################################################"
CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log
#last argument = 1 is to enable --do-ra for RA test
start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1
echo "############################################################"
echo "${CN_CONFIG} : Starting the NR-UE"
echo "############################################################"
CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log
#last argument = 1 is to enable --do-ra for RA test
start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1
if [ $NR_UE_SYNC -eq 0 ]
then then
echo "Problem w/ gNB and NR-UE not syncing" echo "RA test NOT OK"
terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2
terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1
scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC
scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC
SYNC_STATUS=-1
try_cnt=$[$try_cnt+1] try_cnt=$[$try_cnt+1]
continue else
try_cnt=$[$try_cnt+10]
fi fi
done
########### end RA test
echo "############################################################" sleep 30
echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators"
echo "############################################################"
sleep 20
terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2
terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1
scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC
scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC
#check RA markers in gNB and NR UE log files
echo "############################################################"
echo "${CN_CONFIG} : Checking RA on gNB / NR-UE"
echo "############################################################"
mv $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE
mv $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE
# Proper check to be done when RA test is working!
#check_ra_result $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE
######### start of PHY TEST loop
try_cnt="0"
while [ $try_cnt -lt 4 ]
do
#end RA test
sleep 30
SYNC_STATUS=0 SYNC_STATUS=0
PING_STATUS=0 PING_STATUS=0
...@@ -2409,6 +2370,7 @@ function run_test_on_vm { ...@@ -2409,6 +2370,7 @@ function run_test_on_vm {
echo "Checking run status" echo "Checking run status"
echo "############################################################" echo "############################################################"
if [ $RA_STATUS -ne 0 ]; then NR_STATUS=-1; fi
if [ $SYNC_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $SYNC_STATUS -ne 0 ]; then NR_STATUS=-1; fi
if [ $PING_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $PING_STATUS -ne 0 ]; then NR_STATUS=-1; fi
if [ $IPERF_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $IPERF_STATUS -ne 0 ]; then NR_STATUS=-1; fi
......
...@@ -85,6 +85,10 @@ ID = ENB_PHY_MIB ...@@ -85,6 +85,10 @@ ID = ENB_PHY_MIB
DESC = MIB data DESC = MIB data
GROUP = ALL:PHY:ENB:WIRESHARK GROUP = ALL:PHY:ENB:WIRESHARK
FORMAT = int,eNB_ID : int,frame : int,subframe : buffer,data FORMAT = int,eNB_ID : int,frame : int,subframe : buffer,data
ID = GNB_PHY_MIB
DESC = NR MIB data
GROUP = ALL:PHY:GNB:WIRESHARK
FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data
#MAC logs #MAC logs
ID = ENB_MAC_UE_DL_SDU ID = ENB_MAC_UE_DL_SDU
...@@ -131,6 +135,18 @@ ID = ENB_MAC_UE_DL_RAR_PDU_WITH_DATA ...@@ -131,6 +135,18 @@ ID = ENB_MAC_UE_DL_RAR_PDU_WITH_DATA
DESC = MAC downlink PDU for an UE DESC = MAC downlink PDU for an UE
GROUP = ALL:MAC:ENB:WIRESHARK GROUP = ALL:MAC:ENB:WIRESHARK
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data
ID = GNB_MAC_DL_PDU_WITH_DATA
DESC = NR MAC downlink PDU for an UE
GROUP = ALL:MAC:GNB:WIRESHARK
FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
ID = GNB_MAC_UL_PDU_WITH_DATA
DESC = NR MAC uplink PDU for an UE
GROUP = ALL:MAC:GNB:WIRESHARK
FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
ID = GNB_MAC_DL_RAR_PDU_WITH_DATA
DESC = NR MAC downlink PDU for RAR
GROUP = ALL:MAC:GNB:WIRESHARK
FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
#RLC logs #RLC logs
ID = ENB_RLC_DL ID = ENB_RLC_DL
......
...@@ -23,6 +23,8 @@ typedef struct { ...@@ -23,6 +23,8 @@ typedef struct {
int socket; int socket;
struct sockaddr_in to; struct sockaddr_in to;
OBUF buf; OBUF buf;
/* LTE traces */
/* ul */ /* ul */
int ul_rnti; int ul_rnti;
int ul_frame; int ul_frame;
...@@ -46,6 +48,28 @@ typedef struct { ...@@ -46,6 +48,28 @@ typedef struct {
int rar_frame; int rar_frame;
int rar_subframe; int rar_subframe;
int rar_data; int rar_data;
/* NR traces */
/* NR ul */
int nr_ul_rnti;
int nr_ul_frame;
int nr_ul_slot;
int nr_ul_data;
/* NR dl */
int nr_dl_rnti;
int nr_dl_frame;
int nr_dl_slot;
int nr_dl_data;
/* NR mib */
int nr_mib_frame;
int nr_mib_slot;
int nr_mib_data;
/* NR RAR */
int nr_rar_rnti;
int nr_rar_frame;
int nr_rar_slot;
int nr_rar_data;
/* config */ /* config */
int no_mib; int no_mib;
int no_sib; int no_sib;
...@@ -58,8 +82,13 @@ typedef struct { ...@@ -58,8 +82,13 @@ typedef struct {
int cur_sib; int cur_sib;
} ev_data; } ev_data;
void trace(ev_data *d, int direction, int rnti_type, int rnti, /****************************************************************************/
int frame, int subframe, void *buf, int bufsize, int preamble) { /* LTE */
/****************************************************************************/
void trace_lte(ev_data *d, int direction, int rnti_type, int rnti,
int frame, int subframe, void *buf, int bufsize, int preamble)
{
ssize_t ret; ssize_t ret;
int fsf; int fsf;
int i; int i;
...@@ -100,15 +129,17 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti, ...@@ -100,15 +129,17 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti,
if (ret != d->buf.osize) abort(); if (ret != d->buf.osize) abort();
} }
void ul(void *_d, event e) { void ul(void *_d, event e)
{
ev_data *d = _d; ev_data *d = _d;
trace(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i, trace_lte(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i,
e.e[d->ul_frame].i, e.e[d->ul_subframe].i, e.e[d->ul_frame].i, e.e[d->ul_subframe].i,
e.e[d->ul_data].b, e.e[d->ul_data].bsize, e.e[d->ul_data].b, e.e[d->ul_data].bsize,
NO_PREAMBLE); NO_PREAMBLE);
} }
void dl(void *_d, event e) { void dl(void *_d, event e)
{
ev_data *d = _d; ev_data *d = _d;
if (e.e[d->dl_rnti].i == 0xffff) { if (e.e[d->dl_rnti].i == 0xffff) {
...@@ -119,14 +150,15 @@ void dl(void *_d, event e) { ...@@ -119,14 +150,15 @@ void dl(void *_d, event e) {
d->cur_sib++; d->cur_sib++;
} }
trace(d, DIRECTION_DOWNLINK, trace_lte(d, DIRECTION_DOWNLINK,
e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i, e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i,
e.e[d->dl_frame].i, e.e[d->dl_subframe].i, e.e[d->dl_frame].i, e.e[d->dl_subframe].i,
e.e[d->dl_data].b, e.e[d->dl_data].bsize, e.e[d->dl_data].b, e.e[d->dl_data].bsize,
NO_PREAMBLE); NO_PREAMBLE);
} }
void mib(void *_d, event e) { void mib(void *_d, event e)
{
ev_data *d = _d; ev_data *d = _d;
if (d->no_mib) return; if (d->no_mib) return;
...@@ -134,30 +166,141 @@ void mib(void *_d, event e) { ...@@ -134,30 +166,141 @@ void mib(void *_d, event e) {
if (d->max_mib && d->cur_mib == d->max_mib) return; if (d->max_mib && d->cur_mib == d->max_mib) return;
d->cur_mib++; d->cur_mib++;
trace(d, DIRECTION_DOWNLINK, NO_RNTI, 0, trace_lte(d, DIRECTION_DOWNLINK, NO_RNTI, 0,
e.e[d->mib_frame].i, e.e[d->mib_subframe].i, e.e[d->mib_frame].i, e.e[d->mib_subframe].i,
e.e[d->mib_data].b, e.e[d->mib_data].bsize, e.e[d->mib_data].b, e.e[d->mib_data].bsize,
NO_PREAMBLE); NO_PREAMBLE);
} }
void preamble(void *_d, event e) { void preamble(void *_d, event e)
{
ev_data *d = _d; ev_data *d = _d;
trace(d, DIRECTION_UPLINK, NO_RNTI, 0, trace_lte(d, DIRECTION_UPLINK, NO_RNTI, 0,
e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i, e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i,
NULL, 0, NULL, 0,
e.e[d->preamble_preamble].i); e.e[d->preamble_preamble].i);
} }
void rar(void *_d, event e) { void rar(void *_d, event e)
{
ev_data *d = _d; ev_data *d = _d;
trace(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i, trace_lte(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i,
e.e[d->rar_frame].i, e.e[d->rar_subframe].i, e.e[d->rar_frame].i, e.e[d->rar_subframe].i,
e.e[d->rar_data].b, e.e[d->rar_data].bsize, e.e[d->rar_data].b, e.e[d->rar_data].bsize,
NO_PREAMBLE); NO_PREAMBLE);
} }
/****************************************************************************/
/* NR */
/****************************************************************************/
#define MAC_NR_START_STRING "mac-nr"
#define MAC_NR_PAYLOAD_TAG 0x01
#define MAC_NR_RNTI_TAG 0x02
#define MAC_NR_FRAME_SLOT_TAG 0x07
#define NR_FDD_RADIO 1
#define NR_TDD_RADIO 2
#define NR_DIRECTION_UPLINK 0
#define NR_DIRECTION_DOWNLINK 1
#define NR_NO_RNTI 0
#define NR_RA_RNTI 2
#define NR_C_RNTI 3
void trace_nr(ev_data *d, int direction, int rnti_type, int rnti,
int frame, int slot, void *buf, int bufsize, int preamble)
{
ssize_t ret;
int i;
d->buf.osize = 0;
PUTS(&d->buf, MAC_NR_START_STRING);
PUTC(&d->buf, NR_TDD_RADIO);
PUTC(&d->buf, direction);
PUTC(&d->buf, rnti_type);
if (rnti_type == NR_C_RNTI || rnti_type == NR_RA_RNTI) {
PUTC(&d->buf, MAC_NR_RNTI_TAG);
PUTC(&d->buf, (rnti>>8) & 255);
PUTC(&d->buf, rnti & 255);
}
#if 0
/* for old versions of wireshark; not sure if correct */
int fsf = (frame << 4) + slot;
PUTC(&d->buf, 4 /* MAC_NR_FRAME_SUBFRAME_TAG */);
PUTC(&d->buf, (fsf>>8) & 255);
PUTC(&d->buf, fsf & 255);
#else
PUTC(&d->buf, MAC_NR_FRAME_SLOT_TAG);
PUTC(&d->buf, (frame>>8) & 255);
PUTC(&d->buf, frame & 255);
PUTC(&d->buf, (slot>>8) & 255);
PUTC(&d->buf, slot & 255);
#endif
PUTC(&d->buf, MAC_NR_PAYLOAD_TAG);
for (i = 0; i < bufsize; i++)
PUTC(&d->buf, ((char *)buf)[i]);
ret = sendto(d->socket, d->buf.obuf, d->buf.osize, 0,
(struct sockaddr *)&d->to, sizeof(struct sockaddr_in));
if (ret != d->buf.osize) abort();
}
void nr_ul(void *_d, event e)
{
ev_data *d = _d;
trace_nr(d, NR_DIRECTION_UPLINK, NR_C_RNTI, e.e[d->nr_ul_rnti].i,
e.e[d->nr_ul_frame].i, e.e[d->nr_ul_slot].i,
e.e[d->nr_ul_data].b, e.e[d->nr_ul_data].bsize, NO_PREAMBLE);
}
void nr_dl(void *_d, event e)
{
ev_data *d = _d;
trace_nr(d, NR_DIRECTION_DOWNLINK, NR_C_RNTI, e.e[d->nr_dl_rnti].i,
e.e[d->nr_dl_frame].i, e.e[d->nr_dl_slot].i,
e.e[d->nr_dl_data].b, e.e[d->nr_dl_data].bsize, NO_PREAMBLE);
}
void nr_mib(void *_d, event e)
{
ev_data *d = _d;
if (d->no_mib) return;
if (d->max_mib && d->cur_mib == d->max_mib) return;
d->cur_mib++;
trace_nr(d, NR_DIRECTION_DOWNLINK, NR_NO_RNTI, 0,
e.e[d->nr_mib_frame].i, e.e[d->nr_mib_slot].i,
e.e[d->nr_mib_data].b, e.e[d->nr_mib_data].bsize, NO_PREAMBLE);
}
void nr_rar(void *_d, event e)
{
ev_data *d = _d;
trace_nr(d, NR_DIRECTION_DOWNLINK, NR_RA_RNTI, e.e[d->nr_rar_rnti].i,
e.e[d->nr_rar_frame].i, e.e[d->nr_rar_slot].i,
e.e[d->nr_rar_data].b, e.e[d->nr_rar_data].bsize, NO_PREAMBLE);
}
/****************************************************************************/
/****************************************************************************/
void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
int preamble_id, int rar_id) { int preamble_id, int rar_id,
int nr_ul_id, int nr_dl_id, int nr_mib_id, int nr_rar_id)
{
database_event_format f; database_event_format f;
int i; int i;
d->ul_rnti = -1; d->ul_rnti = -1;
...@@ -178,6 +321,23 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, ...@@ -178,6 +321,23 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
d->rar_frame = -1; d->rar_frame = -1;
d->rar_subframe = -1; d->rar_subframe = -1;
d->rar_data = -1; d->rar_data = -1;
d->nr_ul_rnti = -1;
d->nr_ul_frame = -1;
d->nr_ul_slot = -1;
d->nr_ul_data = -1;
d->nr_dl_rnti = -1;
d->nr_dl_frame = -1;
d->nr_dl_slot = -1;
d->nr_dl_data = -1;
d->nr_mib_frame = -1;
d->nr_mib_slot = -1;
d->nr_mib_data = -1;
d->nr_rar_rnti = -1;
d->nr_rar_frame = -1;
d->nr_rar_slot = -1;
d->nr_rar_data = -1;
#define G(var_name, var_type, var) \ #define G(var_name, var_type, var) \
if (!strcmp(f.name[i], var_name)) { \ if (!strcmp(f.name[i], var_name)) { \
if (strcmp(f.type[i], var_type)) goto error; \ if (strcmp(f.type[i], var_type)) goto error; \
...@@ -247,6 +407,60 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id, ...@@ -247,6 +407,60 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
if (d->rar_rnti == -1 || d->rar_frame == -1 || d->rar_subframe == -1 || if (d->rar_rnti == -1 || d->rar_frame == -1 || d->rar_subframe == -1 ||
d->rar_data == -1) goto error; d->rar_data == -1) goto error;
/* NR ul: rnti, frame, slot, data */
f = get_format(database, nr_ul_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->nr_ul_rnti);
G("frame", "int", d->nr_ul_frame);
G("slot", "int", d->nr_ul_slot);
G("data", "buffer", d->nr_ul_data);
}
if (d->nr_ul_rnti == -1 || d->nr_ul_frame == -1 || d->nr_ul_slot == -1 ||
d->nr_ul_data == -1)
goto error;
/* NR dl: rnti, frame, slot, data */
f = get_format(database, nr_dl_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->nr_dl_rnti);
G("frame", "int", d->nr_dl_frame);
G("slot", "int", d->nr_dl_slot);
G("data", "buffer", d->nr_dl_data);
}
if (d->nr_dl_rnti == -1 || d->nr_dl_frame == -1 || d->nr_dl_slot == -1 ||
d->nr_dl_data == -1)
goto error;
/* NR MIB: frame, slot, data */
f = get_format(database, nr_mib_id);
for (i = 0; i < f.count; i++) {
G("frame", "int", d->nr_mib_frame);
G("slot", "int", d->nr_mib_slot);
G("data", "buffer", d->nr_mib_data);
}
if (d->nr_mib_frame == -1 || d->nr_mib_slot== -1 || d->nr_mib_data == -1)
goto error;
/* NR RAR: rnti, frame, slot, data */
f = get_format(database, nr_rar_id);
for (i = 0; i < f.count; i++) {
G("rnti", "int", d->nr_rar_rnti);
G("frame", "int", d->nr_rar_frame);
G("slot", "int", d->nr_rar_slot);
G("data", "buffer", d->nr_rar_data);
}
if (d->nr_rar_rnti == -1 || d->nr_rar_frame == -1 || d->nr_rar_slot == -1 ||
d->nr_rar_data == -1)
goto error;
#undef G #undef G
return; return;
error: error:
...@@ -254,7 +468,8 @@ error: ...@@ -254,7 +468,8 @@ error:
abort(); abort();
} }
void *receiver(void *_d) { void *receiver(void *_d)
{
ev_data *d = _d; ev_data *d = _d;
int s; int s;
char buf[100000]; char buf[100000];
...@@ -279,7 +494,8 @@ void *receiver(void *_d) { ...@@ -279,7 +494,8 @@ void *receiver(void *_d) {
return 0; return 0;
} }
void usage(void) { void usage(void)
{
printf( printf(
"options:\n" "options:\n"
" -d <database file> this option is mandatory\n" " -d <database file> this option is mandatory\n"
...@@ -304,14 +520,16 @@ void usage(void) { ...@@ -304,14 +520,16 @@ void usage(void) {
exit(1); exit(1);
} }
int main(int n, char **v) { int main(int n, char **v)
{
char *database_filename = NULL; char *database_filename = NULL;
char *input_filename = NULL; char *input_filename = NULL;
void *database; void *database;
event_handler *h; event_handler *h;
int in; int in;
int i; int i;
int ul_id, dl_id, mib_id = -1, preamble_id, rar_id; int ul_id, dl_id, mib_id, preamble_id, rar_id;
int nr_ul_id, nr_dl_id, nr_mib_id, nr_rar_id;
ev_data d; ev_data d;
char *ip = DEFAULT_IP; char *ip = DEFAULT_IP;
int port = DEFAULT_PORT; int port = DEFAULT_PORT;
...@@ -382,6 +600,11 @@ int main(int n, char **v) { ...@@ -382,6 +600,11 @@ int main(int n, char **v) {
on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1); on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1);
on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1); on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1);
on_off(database, "GNB_MAC_UL_PDU_WITH_DATA", is_on, 1);
on_off(database, "GNB_MAC_DL_PDU_WITH_DATA", is_on, 1);
on_off(database, "GNB_PHY_MIB", is_on, 1);
on_off(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1);
/* activate selected traces */ /* activate selected traces */
if (socket_send(in, &mt, 1) == -1 || if (socket_send(in, &mt, 1) == -1 ||
socket_send(in, &number_of_events, sizeof(int)) == -1 || socket_send(in, &number_of_events, sizeof(int)) == -1 ||
...@@ -398,12 +621,26 @@ int main(int n, char **v) { ...@@ -398,12 +621,26 @@ int main(int n, char **v) {
mib_id = event_id_from_name(database, "ENB_PHY_MIB"); mib_id = event_id_from_name(database, "ENB_PHY_MIB");
preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE"); preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE");
rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA"); rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA");
setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id);
nr_ul_id = event_id_from_name(database, "GNB_MAC_UL_PDU_WITH_DATA");
nr_dl_id = event_id_from_name(database, "GNB_MAC_DL_PDU_WITH_DATA");
nr_mib_id = event_id_from_name(database, "GNB_PHY_MIB");
nr_rar_id = event_id_from_name(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA");
setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id,
nr_ul_id, nr_dl_id, nr_mib_id, nr_rar_id);
register_handler_function(h, ul_id, ul, &d); register_handler_function(h, ul_id, ul, &d);
register_handler_function(h, dl_id, dl, &d); register_handler_function(h, dl_id, dl, &d);
register_handler_function(h, mib_id, mib, &d); register_handler_function(h, mib_id, mib, &d);
register_handler_function(h, preamble_id, preamble, &d); register_handler_function(h, preamble_id, preamble, &d);
register_handler_function(h, rar_id, rar, &d); register_handler_function(h, rar_id, rar, &d);
register_handler_function(h, nr_ul_id, nr_ul, &d);
register_handler_function(h, nr_dl_id, nr_dl, &d);
register_handler_function(h, nr_mib_id, nr_mib, &d);
register_handler_function(h, nr_rar_id, nr_rar, &d);
d.socket = socket(AF_INET, SOCK_DGRAM, 0); d.socket = socket(AF_INET, SOCK_DGRAM, 0);
if (d.socket == -1) { if (d.socket == -1) {
...@@ -425,7 +662,9 @@ int main(int n, char **v) { ...@@ -425,7 +662,9 @@ int main(int n, char **v) {
if (e.type == -1) break; if (e.type == -1) break;
if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id || if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id ||
e.type == preamble_id || e.type == rar_id)) continue; e.type == preamble_id || e.type == rar_id ||
e.type == nr_ul_id || e.type == nr_dl_id ||
e.type == nr_mib_id || e.type == nr_rar_id)) continue;
handle_event(h, e); handle_event(h, e);
} }
......
...@@ -101,11 +101,11 @@ static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) { ...@@ -101,11 +101,11 @@ static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) {
shift = ((asn->size - 1) * 8) - asn->bits_unused; shift = ((asn->size - 1) * 8) - asn->bits_unused;
for (index = 0; index < (asn->size - 1); index++) { for (index = 0; index < (asn->size - 1); index++) {
result |= asn->buf[index] << shift; result |= ((uint64_t)asn->buf[index]) << shift;
shift -= 8; shift -= 8;
} }
result |= asn->buf[index] >> asn->bits_unused; result |= ((uint64_t)asn->buf[index]) >> asn->bits_unused;
return result; return result;
} }
......
...@@ -121,9 +121,11 @@ char toksep[2]; ...@@ -121,9 +121,11 @@ char toksep[2];
case SCHED_RR: case SCHED_RR:
lptr+=sprintf(lptr,"%s ","rt: rr"); lptr+=sprintf(lptr,"%s ","rt: rr");
break; break;
#ifdef SCHED_DEADLINE
case SCHED_DEADLINE: case SCHED_DEADLINE:
lptr+=sprintf(lptr,"%s ","rt: deadline"); lptr+=sprintf(lptr,"%s ","rt: deadline");
break; break;
#endif
default: default:
lptr+=sprintf(lptr,"%s ","????"); lptr+=sprintf(lptr,"%s ","????");
break; break;
......
...@@ -170,6 +170,7 @@ typedef struct { ...@@ -170,6 +170,7 @@ typedef struct {
uint8_t prach_format; uint8_t prach_format;
/// Num RA /// Num RA
uint8_t num_ra; uint8_t num_ra;
uint8_t prach_slot;
uint8_t prach_start_symbol; uint8_t prach_start_symbol;
/// 38.211 (NCS 38.211 6.3.3.1). /// 38.211 (NCS 38.211 6.3.3.1).
uint16_t num_cs; uint16_t num_cs;
...@@ -179,6 +180,8 @@ typedef struct { ...@@ -179,6 +180,8 @@ typedef struct {
uint8_t restricted_set; uint8_t restricted_set;
/// see TS 38.211 (6.3.3.2). /// see TS 38.211 (6.3.3.2).
uint16_t freq_msg1; uint16_t freq_msg1;
// When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble
uint8_t ssb_nb_in_ro;
// nfapi_nr_ul_beamforming_t beamforming; // nfapi_nr_ul_beamforming_t beamforming;
} fapi_nr_ul_config_prach_pdu; } fapi_nr_ul_config_prach_pdu;
......
...@@ -385,7 +385,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, ...@@ -385,7 +385,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
fp->Lmax = 64; fp->Lmax = 64;
} }
fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[1].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
fp->N_ssb = 0; fp->N_ssb = 0;
for (int p=0; p<fp->Lmax; p++) for (int p=0; p<fp->Lmax; p++)
......
...@@ -479,6 +479,11 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -479,6 +479,11 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0]; NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[UE_id][0];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid];
if (!harq_process) {
LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n");
return 1;
}
t_nrLDPC_dec_params decParams; t_nrLDPC_dec_params decParams;
t_nrLDPC_dec_params* p_decParams = &decParams; t_nrLDPC_dec_params* p_decParams = &decParams;
...@@ -488,11 +493,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -488,11 +493,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
phy_vars_gNB->nbDecode = 0; phy_vars_gNB->nbDecode = 0;
harq_process->processedSegments = 0; harq_process->processedSegments = 0;
if (!harq_process) {
LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n");
return 1;
}
double Coderate = 0.0; double Coderate = 0.0;
// ------------------------------------------------------------------ // ------------------------------------------------------------------
......
...@@ -71,7 +71,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ ...@@ -71,7 +71,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
int16_t Ncp = 0, amp, *prach, *prach2, *prachF, *Xu; int16_t Ncp = 0, amp, *prach, *prach2, *prachF, *Xu;
int32_t Xu_re, Xu_im; int32_t Xu_re, Xu_im;
int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k; int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k, prachStartSymbol, sample_offset_slot;
//int restricted_Type; //int restricted_Type;
prach = prach_tmp; prach = prach_tmp;
...@@ -94,7 +94,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ ...@@ -94,7 +94,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
kbar = 1; kbar = 1;
K = 24; K = 24;
k = 12*n_ra_prb - 6*fp->N_RB_UL; k = 12*n_ra_prb - 6*fp->N_RB_UL;
//prachStartSymbol = prach_config_pdu->prach_start_symbol prachStartSymbol = prach_pdu->prach_start_symbol;
//restricted_Type = 0; //restricted_Type = 0;
compute_nr_prach_seq(nrUE_config->prach_config.prach_sequence_length, compute_nr_prach_seq(nrUE_config->prach_config.prach_sequence_length,
...@@ -102,7 +102,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ ...@@ -102,7 +102,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index, nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index,
ue->X_u); ue->X_u);
prach_start = fp->get_samples_slot_timestamp(slot, fp, 0); sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1));
prach_start = fp->get_samples_slot_timestamp(slot, fp, 0) + sample_offset_slot;
// First compute physical root sequence // First compute physical root sequence
/************************************************************************ /************************************************************************
......
...@@ -114,6 +114,14 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) { ...@@ -114,6 +114,14 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
else else
nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
if (T_ACTIVE(T_GNB_PHY_MIB)) {
unsigned char bch[3];
bch[0] = gNB->ssb_pdu.ssb_pdu_rel15.bchPayload & 0xff;
bch[1] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 8) & 0xff;
bch[2] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 16) & 0xff;
T(T_GNB_PHY_MIB, T_INT(0) /* module ID */, T_INT(frame), T_INT(slot), T_BUFFER(bch, 3));
}
nr_generate_pbch(&gNB->pbch, nr_generate_pbch(&gNB->pbch,
&gNB->ssb_pdu, &gNB->ssb_pdu,
gNB->nr_pbch_interleaver, gNB->nr_pbch_interleaver,
......
...@@ -218,7 +218,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, ...@@ -218,7 +218,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
/* RACH */ /* RACH */
if (get_softmodem_params()->do_ra==1) { if (get_softmodem_params()->do_ra==1) {
if ((ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { if ((ue->UE_mode[gNB_id] > NOT_SYNCHED && ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) {
nr_ue_prach_procedures(ue, proc, gNB_id, mode); nr_ue_prach_procedures(ue, proc, gNB_id, mode);
} }
} }
...@@ -896,6 +896,9 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -896,6 +896,9 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
int *dlsch_errors, int *dlsch_errors,
runmode_t mode) { runmode_t mode) {
if (dlsch0==NULL)
AssertFatal(0,"dlsch0 should be defined at this level \n");
int harq_pid = dlsch0->current_harq_pid; int harq_pid = dlsch0->current_harq_pid;
int frame_rx = proc->frame_rx; int frame_rx = proc->frame_rx;
int nr_tti_rx = proc->nr_tti_rx; int nr_tti_rx = proc->nr_tti_rx;
...@@ -923,9 +926,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -923,9 +926,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
uint16_t bw_scaling, start_symbol; uint16_t bw_scaling, start_symbol;
float tc_factor; float tc_factor;
if (dlsch0==NULL)
AssertFatal(0,"dlsch0 should be defined at this level \n");
is_cw0_active = dlsch0->harq_processes[harq_pid]->status; is_cw0_active = dlsch0->harq_processes[harq_pid]->status;
nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols;
start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol;
...@@ -1354,9 +1354,9 @@ void *UE_thread_slot1_dl_processing(void *arg) { ...@@ -1354,9 +1354,9 @@ void *UE_thread_slot1_dl_processing(void *arg) {
CPU_ZERO(&cpuset); CPU_ZERO(&cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.slot1_proc_one != -1 ) if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.slot1_proc_one != -1 )
CPU_SET(threads.slot1_proc_one, &cpuset); CPU_SET(threads.slot1_proc_one, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 ) if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 )
CPU_SET(threads.slot1_proc_two, &cpuset); CPU_SET(threads.slot1_proc_two, &cpuset);
if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 ) if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 )
CPU_SET(threads.slot1_proc_three, &cpuset); CPU_SET(threads.slot1_proc_three, &cpuset);
init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset, init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
...@@ -1829,10 +1829,22 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ...@@ -1829,10 +1829,22 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
ue->dlsch_SI[gNB_id], ue->dlsch_SI[gNB_id],
NULL); NULL);
nr_ue_dlsch_procedures(ue,
proc,
gNB_id,
SI_PDSCH,
ue->dlsch_SI[gNB_id],
NULL,
&ue->dlsch_SI_errors[gNB_id],
mode);
// deactivate dlsch once dlsch proc is done
ue->dlsch_SI[gNB_id]->active = 0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT);
} }
// do procedures for SI-RNTI // do procedures for P-RNTI
if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) { if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN);
nr_ue_pdsch_procedures(ue, nr_ue_pdsch_procedures(ue,
...@@ -1842,6 +1854,18 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ...@@ -1842,6 +1854,18 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
ue->dlsch_p[gNB_id], ue->dlsch_p[gNB_id],
NULL); NULL);
nr_ue_dlsch_procedures(ue,
proc,
gNB_id,
P_PDSCH,
ue->dlsch_p[gNB_id],
NULL,
&ue->dlsch_p_errors[gNB_id],
mode);
// deactivate dlsch once dlsch proc is done
ue->dlsch_p[gNB_id]->active = 0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT);
} }
...@@ -1855,10 +1879,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ...@@ -1855,10 +1879,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
ue->dlsch_ra[gNB_id], ue->dlsch_ra[gNB_id],
NULL); NULL);
// #if UE_TIMING_TRACE
// start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]);
// #endif
nr_ue_dlsch_procedures(ue, nr_ue_dlsch_procedures(ue,
proc, proc,
gNB_id, gNB_id,
...@@ -1868,16 +1888,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ...@@ -1868,16 +1888,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
&ue->dlsch_ra_errors[gNB_id], &ue->dlsch_ra_errors[gNB_id],
mode); mode);
// #if UE_TIMING_TRACE // deactivate dlsch once dlsch proc is done
// stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]); ue->dlsch_ra[gNB_id]->active = 0;
#if DISABLE_LOG_X
printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0));
printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0));
#else
LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0));
LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0));
#endif
// #endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT);
} }
...@@ -1946,71 +1958,8 @@ start_meas(&ue->generic_stat); ...@@ -1946,71 +1958,8 @@ start_meas(&ue->generic_stat);
} }
#endif #endif
// do procedures for SI-RNTI
if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) {
nr_ue_pdsch_procedures(ue,
proc,
gNB_id,
SI_PDSCH,
ue->dlsch_SI[gNB_id],
NULL);
/*ue_dlsch_procedures(ue,
proc,
gNB_id,
SI_PDSCH,
ue->dlsch_SI[gNB_id],
NULL,
&ue->dlsch_SI_errors[gNB_id],
mode,
abstraction_flag);
ue->dlsch_SI[gNB_id]->active = 0;*/
}
// do procedures for P-RNTI
if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
nr_ue_pdsch_procedures(ue,
proc,
gNB_id,
P_PDSCH,
ue->dlsch_p[gNB_id],
NULL);
/*ue_dlsch_procedures(ue,
proc,
gNB_id,
P_PDSCH,
ue->dlsch_p[gNB_id],
NULL,
&ue->dlsch_p_errors[gNB_id],
mode,
abstraction_flag);*/
ue->dlsch_p[gNB_id]->active = 0;
}
// do procedures for RA-RNTI
if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1)) {
nr_ue_pdsch_procedures(ue,
proc,
gNB_id,
RA_PDSCH,
ue->dlsch_ra[gNB_id],
NULL);
/*ue_dlsch_procedures(ue,
proc,
gNB_id,
RA_PDSCH,
ue->dlsch_ra[gNB_id],
NULL,
&ue->dlsch_ra_errors[gNB_id],
mode,
abstraction_flag);*/
ue->dlsch_ra[gNB_id]->active = 0;
}
// duplicate harq structure // duplicate harq structure
/* /*
uint8_t current_harq_pid = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->current_harq_pid; uint8_t current_harq_pid = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->current_harq_pid;
NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->harq_processes[current_harq_pid]; NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->harq_processes[current_harq_pid];
NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[next1_thread_id][gNB_id][0]->harq_processes[current_harq_pid]; NR_DL_UE_HARQ_t *harq_processes_dest = ue->dlsch[next1_thread_id][gNB_id][0]->harq_processes[current_harq_pid];
...@@ -2138,6 +2087,11 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ...@@ -2138,6 +2087,11 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN);
if (!prach_resources->init_msg1 && (frame_tx == (ue->prach_resources[gNB_id]->sync_frame + 150) % MAX_FRAME_NUMBER)){
ue->prach_cnt = 0;
prach_resources->init_msg1 = 1;
}
if (ue->mac_enabled == 0){ if (ue->mac_enabled == 0){
// prach_resources->ra_PreambleIndex = preamble_tx; // prach_resources->ra_PreambleIndex = preamble_tx;
prach_resources->ra_TDD_map_index = 0; prach_resources->ra_TDD_map_index = 0;
...@@ -2154,13 +2108,8 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ...@@ -2154,13 +2108,8 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
ue->ulsch_Msg3_active[i] = 0; ue->ulsch_Msg3_active[i] = 0;
} }
} }
nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx); nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], &ue->prach_vars[0]->prach_pdu, mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx);
}
} }
if (!prach_resources->init_msg1 && (frame_tx > ue->prach_resources[gNB_id]->sync_frame + 150)){
ue->prach_cnt = 0;
prach_resources->init_msg1 = 1;
} }
if (ue->prach_resources[gNB_id] != NULL && nr_prach == 1 && prach_resources->init_msg1) { if (ue->prach_resources[gNB_id] != NULL && nr_prach == 1 && prach_resources->init_msg1) {
......
...@@ -947,6 +947,24 @@ int get_format0(uint8_t index, ...@@ -947,6 +947,24 @@ int get_format0(uint8_t index,
return format; return format;
} }
int64_t *get_prach_config_info(uint32_t pointa,
uint8_t index,
uint8_t unpaired) {
int64_t *prach_config_info_p;
if (pointa > 2016666) { //FR2
prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index];
}
else { // FR1
if (unpaired)
prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index];
else
prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index];
} // FR2 / FR1
return prach_config_info_p;
}
void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
uint16_t *slot_period, uint16_t *slot_period,
uint16_t *offset) { uint16_t *offset) {
......
...@@ -36,6 +36,36 @@ ...@@ -36,6 +36,36 @@
#include "NR_CellGroupConfig.h" #include "NR_CellGroupConfig.h"
#include "nr_mac.h" #include "nr_mac.h"
// ===============================================
// SSB to RO mapping public defines and structures
// ===============================================
#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO
#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot
#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot
// PRACH occasion details
typedef struct prach_occasion_info {
uint8_t start_symbol; // 0 - 13 (14 symbols in a slot)
uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8)
uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz)
uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern)
uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs
uint8_t nb_mapped_ssb;
uint16_t format; // RO preamble format
} prach_occasion_info_t;
// PRACH occasion slot details
// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency
typedef struct prach_occasion_slot {
prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot
uint8_t nb_of_prach_occasion_in_time;
uint8_t nb_of_prach_occasion_in_freq;
} prach_occasion_slot_t;
// ========================================
typedef enum { typedef enum {
NR_DL_DCI_FORMAT_1_0 = 0, NR_DL_DCI_FORMAT_1_0 = 0,
NR_DL_DCI_FORMAT_1_1, NR_DL_DCI_FORMAT_1_1,
...@@ -133,6 +163,10 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPreco ...@@ -133,6 +163,10 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPreco
int get_format0(uint8_t index, uint8_t unpaired); int get_format0(uint8_t index, uint8_t unpaired);
int64_t *get_prach_config_info(uint32_t pointa,
uint8_t index,
uint8_t unpaired);
uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config);
int get_num_dmrs(uint16_t dmrs_mask ); int get_num_dmrs(uint16_t dmrs_mask );
......
...@@ -204,7 +204,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, ...@@ -204,7 +204,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
uint16_t band; uint16_t band;
int32_t offset; int32_t offset;
get_band((cfg->carrier_config.dl_frequency)*1000, get_band((uint64_t)(cfg->carrier_config.dl_frequency)*1000,
&band, &band,
&offset, &offset,
&frame_type); &frame_type);
...@@ -243,8 +243,8 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, ...@@ -243,8 +243,8 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0; cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0;
cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0;
for (i=0; i<4; i++) { for (i=0; i<4; i++) {
cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8); cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8);
cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8); cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8);
} }
break; break;
default: default:
...@@ -433,6 +433,9 @@ int nr_rrc_mac_config_req_ue( ...@@ -433,6 +433,9 @@ int nr_rrc_mac_config_req_ue(
LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti);
} }
// Setup the SSB to Rach Occasions mapping according to the config
build_ssb_to_ro_map(mac->scc, mac->phy_config.config_req.cell_config.frame_duplex_type);
/* /*
if(mac_cell_group_configP != NULL){ if(mac_cell_group_configP != NULL){
if(mac_cell_group_configP->drx_Config != NULL ){ if(mac_cell_group_configP->drx_Config != NULL ){
......
...@@ -267,6 +267,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 ...@@ -267,6 +267,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4
@param nr_tti_tx slot for PRACH transmission @param nr_tti_tx slot for PRACH transmission
@returns indication to generate PRACH to phy */ @returns indication to generate PRACH to phy */
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
module_id_t mod_id, module_id_t mod_id,
int CC_id, int CC_id,
UE_MODE_t UE_mode, UE_MODE_t UE_mode,
...@@ -278,15 +279,14 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -278,15 +279,14 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
@param module_idP Index of UE instance @param module_idP Index of UE instance
@param CC_id Component Carrier Index @param CC_id Component Carrier Index
@param gNB_index gNB index @param gNB_index gNB index
@param t_id
@param rach_ConfigDedicated @param rach_ConfigDedicated
@returns void */ @returns void */
void nr_get_prach_resources(module_id_t mod_id, void nr_get_prach_resources(module_id_t mod_id,
int CC_id, int CC_id,
uint8_t gNB_id, uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3, uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources, NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); NR_RACH_ConfigDedicated_t * rach_ConfigDedicated);
void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id);
...@@ -305,5 +305,8 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, ...@@ -305,5 +305,8 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
uint8_t *nb_dmrs_re_per_rb, uint8_t *nb_dmrs_re_per_rb,
uint16_t *number_dmrs_symbols); uint16_t *number_dmrs_symbols);
void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired);
#endif #endif
/** @}*/ /** @}*/
...@@ -75,9 +75,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac); ...@@ -75,9 +75,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac);
void nr_get_prach_resources(module_id_t mod_id, void nr_get_prach_resources(module_id_t mod_id,
int CC_id, int CC_id,
uint8_t gNB_id, uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3, uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources, NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
...@@ -87,8 +87,8 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -87,8 +87,8 @@ void nr_get_prach_resources(module_id_t mod_id,
// NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo
int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, i, deltaPreamble_Msg3 = 0; int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, deltaPreamble_Msg3 = 0;
uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size; uint8_t noGroupB = 0, s_id, t_id, f_id, ul_carrier_id, Msg3_size;
AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id);
nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
...@@ -100,6 +100,7 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -100,6 +100,7 @@ void nr_get_prach_resources(module_id_t mod_id,
//////////* UE Random Access Resource Selection *////////// //////////* UE Random Access Resource Selection *//////////
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// todo: // todo:
// - switch initialisation cases // - switch initialisation cases
// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321)
...@@ -129,12 +130,81 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -129,12 +130,81 @@ void nr_get_prach_resources(module_id_t mod_id,
// rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB; // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
// Determine the SSB to RACH mapping ratio
// =======================================
NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
long cb_preambles_per_ssb; // Nb of preambles per SSB
int total_preambles_per_ssb;
int starting_preamble_nb = 0;
uint8_t ssb_nb_in_ro;
switch (ssb_perRACH_config){
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 1;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 16;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
break;
default:
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
break;
}
Msg3_size = mac->RA_Msg3_size; Msg3_size = mac->RA_Msg3_size;
numberOfRA_Preambles = 64; numberOfRA_Preambles = 64;
if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL) if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles); numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
// Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration
if ((true == multiple_ssb_per_ro) &&
(ssb_rach_ratio > 1)) {
total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio;
ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro;
starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro;
}
else {
total_preambles_per_ssb = numberOfRA_Preambles;
starting_preamble_nb = 0;
}
if (!nr_rach_ConfigCommon->groupBconfigured) { if (!nr_rach_ConfigCommon->groupBconfigured) {
noGroupB = 1; noGroupB = 1;
} else { } else {
...@@ -220,29 +290,30 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -220,29 +290,30 @@ void nr_get_prach_resources(module_id_t mod_id,
if (first_Msg3 == 1) { if (first_Msg3 == 1) {
if (noGroupB == 1) { if (noGroupB == 1) {
// use Group A preamble // use Group A preamble
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
mac->RA_usedGroupA = 1; mac->RA_usedGroupA = 1;
} else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) { } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) {
// Group B is configured and RA preamble Group A is used // Group B is configured and RA preamble Group A is used
// - todo add condition on CCCH_sdu_size for initiation by CCCH // - todo add condition on CCCH_sdu_size for initiation by CCCH
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
mac->RA_usedGroupA = 1; mac->RA_usedGroupA = 1;
} else { } else {
// Group B preamble is configured and used // Group B preamble is configured and used
// the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A
// the remaining belong to RA Preambles Group B // the remaining belong to RA Preambles Group B
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
mac->RA_usedGroupA = 0; mac->RA_usedGroupA = 0;
} }
} else { // Msg3 is being retransmitted } else { // Msg3 is being retransmitted
if (mac->RA_usedGroupA == 1 && noGroupB == 1) { if (mac->RA_usedGroupA == 1 && noGroupB == 1) {
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
} else if (mac->RA_usedGroupA == 1 && noGroupB == 0){ } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
} else { } else {
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
} }
} }
LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex); LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex);
} }
...@@ -268,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id, ...@@ -268,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id,
// 1) this does not apply to contention-free RA Preamble for beam failure recovery request // 1) this does not apply to contention-free RA Preamble for beam failure recovery request
// 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) // 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario)
prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex;
// ra_RNTI computation // ra_RNTI computation
// - todo: this is for TDD FR1 only
// - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier // - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier
// - f_id: index of the PRACH occasion in the frequency domain // - f_id: index of the PRACH occasion in the frequency domain
// - s_id is starting symbol of the PRACH occasion [0...14] // - s_id is starting symbol of the PRACH occasion [0...14]
// - t_id is the first slot of the PRACH occasion in a system frame [0...80] // - t_id is the first slot of the PRACH occasion in a system frame [0...80]
ul_carrier_id = 0; // NUL ul_carrier_id = 0; // NUL
f_id = rach_ConfigGeneric->msg1_FrequencyStart; f_id = prach_pdu->num_ra;
SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4]; t_id = prach_pdu->prach_slot;
s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5]; s_id = prach_pdu->prach_start_symbol;
// Pick the first slot of the PRACH occasion in a system frame
for (i = 0; i < 10; i++){
if (((SFN_nbr & (1 << i)) >> i) == 1){
t_id = 2*i;
break;
}
}
prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
mac->ra_rnti = prach_resources->ra_RNTI; mac->ra_rnti = prach_resources->ra_RNTI;
...@@ -335,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint ...@@ -335,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint
// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) // - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
module_id_t mod_id, module_id_t mod_id,
int CC_id, int CC_id,
UE_MODE_t UE_mode, UE_MODE_t UE_mode,
...@@ -363,7 +424,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -363,7 +424,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n"); AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n");
if (UE_mode < PUSCH && prach_resources->init_msg1) { if (prach_resources->init_msg1) {
LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active); LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active);
...@@ -449,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -449,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources // Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1) if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated); nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer
(uint8_t *) payload, // UL MAC pdu pointer (uint8_t *) payload, // UL MAC pdu pointer
...@@ -576,7 +637,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -576,7 +637,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources // Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1) if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
} else { } else {
...@@ -590,7 +651,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, ...@@ -590,7 +651,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources // Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1) if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
} }
} }
......
...@@ -64,6 +64,10 @@ ...@@ -64,6 +64,10 @@
/* utils */ /* utils */
#include "assertions.h" #include "assertions.h"
/* Tools */
#include "asn1_conversions.h"
#include "SIMULATION/TOOLS/sim.h" // for taus
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "SIMULATION/TOOLS/sim.h" // for taus #include "SIMULATION/TOOLS/sim.h" // for taus
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h"
...@@ -72,12 +76,73 @@ ...@@ -72,12 +76,73 @@
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
// ================================================
// SSB to RO mapping private defines and structures
// ================================================
#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16
#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms
#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms
#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms
#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160)
#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period
#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes
#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config
// Maximum number of ROs that can be mapped to an SSB in an association pattern
// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB
// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot
#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD)
// The PRACH Config period is a series of selected slots in one or multiple frames
typedef struct prach_conf_period {
prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME];
uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period
uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames
uint8_t nb_of_slot; // Nb of slots in each frame
} prach_conf_period_t;
// The association period is a series of PRACH Config periods
typedef struct prach_association_period {
prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD];
uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period
uint8_t nb_of_frame; // Total number of frames included in the association period
} prach_association_period_t;
// The association pattern is a series of Association periods
typedef struct prach_association_pattern {
prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD];
prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD];
uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern
uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH
uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length)
} prach_association_pattern_t;
// SSB details
typedef struct ssb_info {
boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration
prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index
uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index
} ssb_info_t;
// List of all the possible SSBs and their details
typedef struct ssb_list_info {
ssb_info_t tx_ssb[MAX_NB_SSB];
uint8_t nb_tx_ssb;
} ssb_list_info_t;
static prach_association_pattern_t prach_assoc_pattern;
static ssb_list_info_t ssb_list;
// ===============================================
// ===============================================
//#define ENABLE_MAC_PAYLOAD_DEBUG 1 //#define ENABLE_MAC_PAYLOAD_DEBUG 1
#define DEBUG_EXTRACT_DCI 1 #define DEBUG_EXTRACT_DCI 1
extern int bwp_id; extern int bwp_id;
extern dci_pdu_rel15_t *def_dci_pdu_rel15; extern dci_pdu_rel15_t *def_dci_pdu_rel15;
extern const uint16_t nr_slots_per_frame[5]; extern const uint8_t nr_slots_per_frame[5];
extern void mac_rlc_data_ind ( extern void mac_rlc_data_ind (
const module_id_t module_idP, const module_id_t module_idP,
...@@ -92,6 +157,617 @@ extern void mac_rlc_data_ind ( ...@@ -92,6 +157,617 @@ extern void mac_rlc_data_ind (
num_tb_t num_tbP, num_tb_t num_tbP,
crc_t *crcs_pP); crc_t *crcs_pP);
// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config
static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) {
int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers
int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers
uint8_t slot_shift_for_map;
uint8_t map_shift;
boolean_t even_slot_invalid;
int64_t s_map;
uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot
uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot
uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols)
uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD
uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz
uint16_t format = 0xffff;
uint8_t format2 = 0xff;
int nb_fdm;
uint8_t config_index, mu;
uint32_t pointa;
int msg1_FDM;
uint8_t prach_conf_period_idx;
uint8_t nb_of_frames_per_prach_conf_period;
uint8_t prach_conf_period_frame_idx;
int64_t *prach_config_info_p;
NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
if (setup->msg1_SubcarrierSpacing)
mu = *setup->msg1_SubcarrierSpacing;
else
mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
pointa = frequencyInfoDL->absoluteFrequencyPointA;
msg1_FDM = rach_ConfigGeneric->msg1_FDM;
switch (msg1_FDM){
case 0:
case 1:
case 2:
case 3:
nb_fdm = 1 << msg1_FDM;
break;
default:
AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM);
}
// Create the PRACH occasions map
// ==============================
// WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule
// Identify the proper PRACH Configuration Index table according to the operating frequency
LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired);
prach_config_info_p = get_prach_config_info(pointa, config_index, unpaired);
if (pointa > 2016666) { //FR2
x = prach_config_info_p[2];
y = prach_config_info_p[3];
y2 = prach_config_info_p[4];
s_map = prach_config_info_p[5];
prach_conf_start_symbol = prach_config_info_p[6];
N_t_slot = prach_config_info_p[8];
N_dur = prach_config_info_p[9];
if (prach_config_info_p[1] != -1)
format2 = (uint8_t) prach_config_info_p[1];
format = ((uint8_t) prach_config_info_p[0]) | (format2<<8);
slot_shift_for_map = mu-2;
if ( (mu == 3) && (prach_config_info_p[7] == 1) )
even_slot_invalid = true;
else
even_slot_invalid = false;
}
else { // FR1
x = prach_config_info_p[2];
y = prach_config_info_p[3];
y2 = y;
s_map = prach_config_info_p[4];
prach_conf_start_symbol = prach_config_info_p[5];
N_t_slot = prach_config_info_p[7];
N_dur = prach_config_info_p[8];
if (prach_config_info_p[1] != -1)
format2 = (uint8_t) prach_config_info_p[1];
format = ((uint8_t) prach_config_info_p[0]) | (format2<<8);
slot_shift_for_map = mu;
if ( (mu == 1) && (prach_config_info_p[6] <= 1) )
// no prach in even slots @ 30kHz for 1 prach per subframe
even_slot_invalid = true;
else
even_slot_invalid = false;
} // FR2 / FR1
prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x;
nb_of_frames_per_prach_conf_period = x;
LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period);
// Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period
// ----------------------------------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------------------------------------
// For every PRACH configuration periods
// -------------------------------------
for (prach_conf_period_idx=0; prach_conf_period_idx<prach_assoc_pattern.nb_of_prach_conf_period_in_max_period; prach_conf_period_idx++) {
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion = 0;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_frame = nb_of_frames_per_prach_conf_period;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_slot = nr_slots_per_frame[mu];
LOG_D(MAC,"PRACH Conf Period Idx %d\n", prach_conf_period_idx);
// For every frames in a PRACH configuration period
// ------------------------------------------------
for (prach_conf_period_frame_idx=0; prach_conf_period_frame_idx<nb_of_frames_per_prach_conf_period; prach_conf_period_frame_idx++) {
frame = (prach_conf_period_idx * nb_of_frames_per_prach_conf_period) + prach_conf_period_frame_idx;
LOG_D(MAC,"PRACH Conf Period Frame Idx %d - Frame %d\n", prach_conf_period_frame_idx, frame);
// Is it a valid frame for this PRACH configuration index? (n_sfn mod x = y)
if ( (frame%x)==y || (frame%x)==y2 ) {
// For every slot in a frame
// -------------------------
for (slot=0; slot<nr_slots_per_frame[mu]; slot++) {
// Is it a valid slot?
map_shift = slot >> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz
if ( (s_map>>map_shift)&0x01 ) {
// Valid slot
// Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also
if ( even_slot_invalid && (slot%2 == 0) )
continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe
// We're good: valid frame and valid slot
// Compute all the PRACH occasions in the slot
uint8_t n_prach_occ_in_time;
uint8_t n_prach_occ_in_freq;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm;
for (n_prach_occ_in_time=0; n_prach_occ_in_time<N_t_slot; n_prach_occ_in_time++) {
uint8_t start_symbol = prach_conf_start_symbol + n_prach_occ_in_time * N_dur;
LOG_D(MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time);
for (n_prach_occ_in_freq=0; n_prach_occ_in_freq<nb_fdm; n_prach_occ_in_freq++) {
prach_occasion_info_t *prach_occasion_p = &prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].prach_occasion[n_prach_occ_in_time][n_prach_occ_in_freq];
prach_occasion_p->start_symbol = start_symbol;
prach_occasion_p->fdm = n_prach_occ_in_freq;
prach_occasion_p->frame = frame;
prach_occasion_p->slot = slot;
prach_occasion_p->format = format;
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++;
LOG_D(MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n",
frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion,
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time,
prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq);
} // For every freq in the slot
} // For every time occasions in the slot
} // Valid slot?
} // For every slots in a frame
} // Valid frame?
} // For every frames in a prach configuration period
} // For every prach configuration periods in the maximum association pattern period (160ms)
}
// Build the list of all the valid/transmitted SSBs according to the config
static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) {
// Create the list of transmitted SSBs
// ===================================
BIT_STRING_t *ssb_bitmap;
uint64_t ssb_positionsInBurst;
uint8_t ssb_idx = 0;
switch (scc->ssb_PositionsInBurst->present) {
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap:
ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap;
ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap);
LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) {
// If SSB is transmitted
if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
ssb_list.nb_tx_ssb++;
ssb_list.tx_ssb[ssb_idx].transmitted = true;
LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
}
ssb_idx++;
}
break;
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap:
ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap;
ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap);
LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) {
// If SSB is transmitted
if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
ssb_list.nb_tx_ssb++;
ssb_list.tx_ssb[ssb_idx].transmitted = true;
LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
}
ssb_idx++;
}
break;
case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap:
ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap;
ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap);
LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) {
// If SSB is transmitted
if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
ssb_list.nb_tx_ssb++;
ssb_list.tx_ssb[ssb_idx].transmitted = true;
LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
}
ssb_idx++;
}
break;
default:
AssertFatal(false,"ssb_PositionsInBurst not present\n");
break;
}
}
// Map the transmitted SSBs to the ROs and create the association pattern according to the config
static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
// Map SSBs to PRACH occasions
// ===========================
// WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule
NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs
uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs
// Determine the SSB to RACH mapping ratio
// =======================================
switch (ssb_perRACH_config){
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 8;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 4;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 2;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 1;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 2;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 4;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 8;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 16;
break;
default:
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
break;
}
LOG_D(MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro);
// Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period
// ==============================================================================================================
// WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions
// (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule)
// There is only one possible association period which can contain up to 16 PRACH configuration periods
LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n");
if (true == multiple_ssb_per_ro) {
required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio;
}
else {
required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio;
}
required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion;
if (required_nb_of_prach_conf_period == 1) {
prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1;
}
else if (required_nb_of_prach_conf_period == 2) {
prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2;
}
else if (required_nb_of_prach_conf_period <= 4) {
prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4;
}
else if (required_nb_of_prach_conf_period <= 8) {
prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8;
}
else if (required_nb_of_prach_conf_period <= 16) {
prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16;
}
else {
AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period);
}
prach_assoc_pattern.nb_of_assoc_period = 1; // WIP: only one possible association period
prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame;
prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame;
LOG_D(MAC,"Assoc period %d, Nb of frames in assoc period %d\n",
prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period,
prach_assoc_pattern.prach_association_period_list[0].nb_of_frame);
// Proceed to the SSB to RO mapping
// ================================
uint8_t association_period_idx; // Association period index within the association pattern
uint8_t ssb_idx = 0;
uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern
prach_conf_period_t *prach_conf_period_p;
// Map all the association periods within the association pattern period
LOG_D(MAC,"Proceed to the SSB to RO mapping\n");
for (association_period_idx=0; association_period_idx<prach_assoc_pattern.nb_of_assoc_period; association_period_idx++) {
uint8_t n_prach_conf=0; // PRACH Configuration period index within the association period
uint8_t frame=0;
uint8_t slot=0;
uint8_t ro_in_time=0;
uint8_t ro_in_freq=0;
// Set the starting PRACH Configuration period index in the association_pattern map for this particular association period
prach_configuration_period_idx = 0; // WIP: only one possible association period so the starting PRACH configuration period is automatically 0
// Check if we need to map multiple SSBs per RO or multiple ROs per SSB
if (true == multiple_ssb_per_ro) {
// --------------------
// --------------------
// Multiple SSBs per RO
// --------------------
// --------------------
// WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
ssb_idx = 0;
// Go through the list of PRACH config periods within this association period
for (n_prach_conf=0; n_prach_conf<prach_assoc_pattern.prach_association_period_list[association_period_idx].nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) {
// Build the association period with its association PRACH Configuration indexes
prach_conf_period_p = &prach_assoc_pattern.prach_conf_period_list[prach_configuration_period_idx];
prach_assoc_pattern.prach_association_period_list[association_period_idx].prach_conf_period_list[n_prach_conf] = prach_conf_period_p;
// Go through all the ROs within the PRACH config period
for (frame=0; frame<prach_conf_period_p->nb_of_frame; frame++) {
for (slot=0; slot<prach_conf_period_p->nb_of_slot; slot++) {
for (ro_in_time=0; ro_in_time<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) {
for (ro_in_freq=0; ro_in_freq<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq];
// Go through the list of transmitted SSBs and map the required amount of SSBs to this RO
// WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
for (; ssb_idx<MAX_NB_SSB; ssb_idx++) {
// Map only the transmitted ssb_idx
if (true == ssb_list.tx_ssb[ssb_idx].transmitted) {
ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx;
ro_p->nb_mapped_ssb++;
ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p;
ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++;
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq);
LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
// If all the required SSBs are mapped to this RO, exit the loop of SSBs
if (ro_p->nb_mapped_ssb == ssb_rach_ratio) {
ssb_idx++;
break;
}
} // if ssb_idx is transmitted
} // for ssb_idx
// Exit the loop of ROs if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for ro_in_freq
// Exit the loop of ROs if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for ro_in_time
// Exit the loop of slots if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for slot
// Exit the loop frames if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for frame
// Exit the loop of PRACH configurations if there is no more SSB to map
if (MAX_NB_SSB == ssb_idx) break;
} // for n_prach_conf
// WIP: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation
} // if multiple_ssbs_per_ro
else {
// --------------------
// --------------------
// Multiple ROs per SSB
// --------------------
// --------------------
n_prach_conf = 0;
// Go through the list of transmitted SSBs
for (ssb_idx=0; ssb_idx<MAX_NB_SSB; ssb_idx++) {
uint8_t nb_mapped_ro_in_association_period=0; // Reset the nb of mapped ROs for the new SSB index
// Map only the transmitted ssb_idx
if (true == ssb_list.tx_ssb[ssb_idx].transmitted) {
// Map all the required ROs to this SSB
// Go through the list of PRACH config periods within this association period
for (; n_prach_conf<prach_assoc_pattern.prach_association_period_list[association_period_idx].nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) {
// Build the association period with its association PRACH Configuration indexes
prach_conf_period_p = &prach_assoc_pattern.prach_conf_period_list[prach_configuration_period_idx];
prach_assoc_pattern.prach_association_period_list[association_period_idx].prach_conf_period_list[n_prach_conf] = prach_conf_period_p;
for (; frame<prach_conf_period_p->nb_of_frame; frame++) {
for (; slot<prach_conf_period_p->nb_of_slot; slot++) {
for (; ro_in_time<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) {
for (; ro_in_freq<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq];
ro_p->mapped_ssb_idx[0] = ssb_idx;
ro_p->nb_mapped_ssb = 1;
ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p;
ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++;
AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
nb_mapped_ro_in_association_period++;
LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq);
LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period);
// Exit the loop if this SSB has been mapped to all the required ROs
// WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period:
// this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
ro_in_freq++;
break;
}
} // for ro_in_freq
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
}
else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index
} // for ro_in_time
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
}
else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index
} // for slot
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
}
else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index
} // for frame
// Exit the loop if this SSB has been mapped to all the required ROs
if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
break;
}
else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index
} // for n_prach_conf
} // if ssb_idx is transmitted
} // for ssb_idx
} // else if multiple_ssbs_per_ro
} // for association_period_index
}
// Returns a RACH occasion if any matches the SSB idx, the frame and the slot
static int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx,
int frame,
int slot,
prach_occasion_info_t **prach_occasion_info_pp) {
ssb_info_t *ssb_info_p;
prach_occasion_slot_t *prach_occasion_slot_p = NULL;
*prach_occasion_info_pp = NULL;
// Search for a matching RO slot in the SSB_to_RO map
// A valid RO slot will match:
// - ssb_idx mapped to one of the ROs in that RO slot
// - exact slot number
// - frame offset
ssb_info_p = &ssb_list.tx_ssb[ssb_idx];
for (uint8_t n_mapped_ro=0; n_mapped_ro<ssb_info_p->nb_mapped_ro; n_mapped_ro++) {
if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) &&
(ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern.nb_of_frame))) {
uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame;
uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame;
prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot];
}
}
// If there is a matching RO slot in the SSB_to_RO map
if (NULL != prach_occasion_slot_p)
{
// A random RO mapped to the SSB index should be selected in the slot
// First count the number of times the SSB index is found in that RO
uint8_t nb_mapped_ssb = 0;
for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq];
for (uint8_t ssb_nb=0; ssb_nb<prach_occasion_info_p->nb_mapped_ssb; ssb_nb++) {
if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
nb_mapped_ssb++;
}
}
}
}
// Choose a random SSB nb
uint8_t random_ssb_nb = 0;
random_ssb_nb = ((taus()) % nb_mapped_ssb);
// Select the RO according to the chosen random SSB nb
nb_mapped_ssb=0;
for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq];
for (uint8_t ssb_nb=0; ssb_nb<prach_occasion_info_p->nb_mapped_ssb; ssb_nb++) {
if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
if (nb_mapped_ssb == random_ssb_nb) {
*prach_occasion_info_pp = prach_occasion_info_p;
return 1;
}
else {
nb_mapped_ssb++;
}
}
}
}
}
}
return 0;
}
// Build the SSB to RO mapping upon RRC configuration update
void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){
// Clear all the lists and maps
memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t));
memset(&ssb_list, 0, sizeof(ssb_list_info_t));
// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config
LOG_D(MAC,"Build RO list\n");
build_ro_list(scc, unpaired);
// Build the list of all the valid/transmitted SSBs according to the config
LOG_D(MAC,"Build SSB list\n");
build_ssb_list(scc);
// Map the transmitted SSBs to the ROs and create the association pattern according to the config
LOG_D(MAC,"Map SSB to RO\n");
map_ssb_to_ro(scc);
LOG_D(MAC,"Map SSB to RO done\n");
}
void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
fapi_nr_dl_config_request_t *dl_config, fapi_nr_dl_config_request_t *dl_config,
fapi_nr_ul_config_request_t *ul_config, fapi_nr_ul_config_request_t *ul_config,
...@@ -498,8 +1174,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, ...@@ -498,8 +1174,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
SFN_C_TYPE sfn_c=SFN_C_IMPOSSIBLE; // only valid for mux=1 SFN_C_TYPE sfn_c=SFN_C_IMPOSSIBLE; // only valid for mux=1
uint32_t n_c=UINT_MAX; uint32_t n_c=UINT_MAX;
uint32_t number_of_search_space_per_slot=UINT_MAX; uint32_t number_of_search_space_per_slot=UINT_MAX;
uint32_t first_symbol_index=UINT_MAX; // uint32_t first_symbol_index=UINT_MAX;
uint32_t search_space_duration; // element of search space // uint32_t search_space_duration; // element of search space
// 38.213 table 10.1-1 // 38.213 table 10.1-1
/// MUX PATTERN 1 /// MUX PATTERN 1
...@@ -516,13 +1192,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id, ...@@ -516,13 +1192,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
sfn_c = SFN_C_MOD_2_EQ_0; sfn_c = SFN_C_MOD_2_EQ_0;
} }
if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (ssb_index&1)){ // if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (ssb_index&1)){
first_symbol_index = num_symbols; // first_symbol_index = num_symbols;
}else{ // }else{
first_symbol_index = table_38213_13_11_c4[index_4lsb]; // first_symbol_index = table_38213_13_11_c4[index_4lsb];
} // }
// 38.213 chapter 13: over two consecutive slots // 38.213 chapter 13: over two consecutive slots
search_space_duration = 2; // search_space_duration = 2;
} }
if(mac->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){ if(mac->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){
...@@ -530,13 +1206,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id, ...@@ -530,13 +1206,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb]; number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb];
big_m = table_38213_13_12_c3[index_4lsb]; big_m = table_38213_13_12_c3[index_4lsb];
if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (ssb_index&1)){ // if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (ssb_index&1)){
first_symbol_index = 7; // first_symbol_index = 7;
}else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (ssb_index&1)){ // }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (ssb_index&1)){
first_symbol_index = num_symbols; // first_symbol_index = num_symbols;
}else{ // }else{
first_symbol_index = 0; // first_symbol_index = 0;
} // }
// 38.213 chapter 13: over two consecutive slots // 38.213 chapter 13: over two consecutive slots
//search_space_duration = 2; //search_space_duration = 2;
} }
...@@ -550,21 +1226,21 @@ int8_t nr_ue_decode_mib(module_id_t module_id, ...@@ -550,21 +1226,21 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
// PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot
// sfn_c = SFN_C_EQ_SFN_SSB; // sfn_c = SFN_C_EQ_SFN_SSB;
n_c = get_ssb_slot(ssb_index); n_c = get_ssb_slot(ssb_index);
switch(ssb_index & 0x3){ // ssb_index(i) mod 4 // switch(ssb_index & 0x3){ // ssb_index(i) mod 4
case 0: // case 0:
first_symbol_index = 0; // first_symbol_index = 0;
break; // break;
case 1: // case 1:
first_symbol_index = 1; // first_symbol_index = 1;
break; // break;
case 2: // case 2:
first_symbol_index = 6; // first_symbol_index = 6;
break; // break;
case 3: // case 3:
first_symbol_index = 7; // first_symbol_index = 7;
break; // break;
default: break; // default: break;
} // }
}else if((scs_ssb == scs_240kHz) && (scs_pdcch == scs_120kHz)){ }else if((scs_ssb == scs_240kHz) && (scs_pdcch == scs_120kHz)){
// 38.213 Table 13-14 // 38.213 Table 13-14
...@@ -574,36 +1250,36 @@ int8_t nr_ue_decode_mib(module_id_t module_id, ...@@ -574,36 +1250,36 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
n_c = get_ssb_slot(ssb_index); n_c = get_ssb_slot(ssb_index);
switch(ssb_index & 0x7){ // ssb_index(i) mod 8 switch(ssb_index & 0x7){ // ssb_index(i) mod 8
case 0: case 0:
first_symbol_index = 0; // first_symbol_index = 0;
break; break;
case 1: case 1:
first_symbol_index = 1; // first_symbol_index = 1;
break; break;
case 2: case 2:
first_symbol_index = 2; // first_symbol_index = 2;
break; break;
case 3: case 3:
first_symbol_index = 3; // first_symbol_index = 3;
break; break;
case 4: case 4:
first_symbol_index = 12; // first_symbol_index = 12;
n_c = get_ssb_slot(ssb_index) - 1; n_c = get_ssb_slot(ssb_index) - 1;
break; break;
case 5: case 5:
first_symbol_index = 13; // first_symbol_index = 13;
n_c = get_ssb_slot(ssb_index) - 1; n_c = get_ssb_slot(ssb_index) - 1;
break; break;
case 6: case 6:
first_symbol_index = 0; // first_symbol_index = 0;
break; break;
case 7: case 7:
first_symbol_index = 1; // first_symbol_index = 1;
break; break;
default: break; default: break;
} }
}else{ ; } }else{ ; }
// 38.213 chapter 13: over one slot // 38.213 chapter 13: over one slot
search_space_duration = 1; // search_space_duration = 1;
} }
/// MUX PATTERN 3 /// MUX PATTERN 3
...@@ -614,24 +1290,24 @@ int8_t nr_ue_decode_mib(module_id_t module_id, ...@@ -614,24 +1290,24 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
// PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot
// sfn_c = SFN_C_EQ_SFN_SSB; // sfn_c = SFN_C_EQ_SFN_SSB;
n_c = get_ssb_slot(ssb_index); n_c = get_ssb_slot(ssb_index);
switch(ssb_index & 0x3){ // ssb_index(i) mod 4 // switch(ssb_index & 0x3){ // ssb_index(i) mod 4
case 0: // case 0:
first_symbol_index = 4; // first_symbol_index = 4;
break; // break;
case 1: // case 1:
first_symbol_index = 8; // first_symbol_index = 8;
break; // break;
case 2: // case 2:
first_symbol_index = 2; // first_symbol_index = 2;
break; // break;
case 3: // case 3:
first_symbol_index = 6; // first_symbol_index = 6;
break; // break;
default: break; // default: break;
} // }
}else{ ; } }else{ ; }
// 38.213 chapter 13: over one slot // 38.213 chapter 13: over one slot
search_space_duration = 1; // search_space_duration = 1;
} }
AssertFatal(number_of_search_space_per_slot!=UINT_MAX,""); AssertFatal(number_of_search_space_per_slot!=UINT_MAX,"");
...@@ -1066,18 +1742,14 @@ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, ...@@ -1066,18 +1742,14 @@ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac,
} }
// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
// It fills the PRACH PDU per each FD occasion.
// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
// - todo: // - todo:
// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config // - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config
void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {
uint8_t config_index, mu, N_dur, N_t_slot, start_symbol;
uint16_t RA_sfn_index;
uint8_t N_RA_slot;
uint8_t config_period;
uint16_t format, format0, format1, ncs; uint16_t format, format0, format1, ncs;
int msg1_FDM, is_nr_prach_slot, fdm; int is_nr_prach_slot;
prach_occasion_info_t *prach_occasion_info_p;
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
...@@ -1089,59 +1761,35 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ...@@ -1089,59 +1761,35 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
NR_ServingCellConfigCommon_t *scc = mac->scc; NR_ServingCellConfigCommon_t *scc = mac->scc;
NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
mac->RA_offset = 2; // to compensate the rx frame offset at the gNB mac->RA_offset = 2; // to compensate the rx frame offset at the gNB
mac->generate_nr_prach = 0; // Reset flag for PRACH generation mac->generate_nr_prach = 0; // Reset flag for PRACH generation
if (is_nr_UL_slot(scc, slotP)) { if (is_nr_UL_slot(scc, slotP)) {
if (setup->msg1_SubcarrierSpacing) // WIP Need to get the proper selected ssb_idx
mu = *setup->msg1_SubcarrierSpacing; // Initial beam selection functionality is not available yet
else uint8_t selected_gnb_ssb_idx = 0;
mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
is_nr_prach_slot = get_nr_prach_info_from_index(config_index, // Get any valid PRACH occasion in the current slot for the selected SSB index
is_nr_prach_slot = get_nr_prach_info_from_ssb_index(selected_gnb_ssb_idx,
(int)frameP, (int)frameP,
(int)slotP, (int)slotP,
frequencyInfoDL->absoluteFrequencyPointA, &prach_occasion_info_p);
mu,
cfg->cell_config.frame_duplex_type,
&format,
&start_symbol,
&N_t_slot,
&N_dur,
&RA_sfn_index,
&N_RA_slot,
&config_period);
if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) { if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) {
AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n");
mac->generate_nr_prach = 1; mac->generate_nr_prach = 1;
fdm = rach_ConfigGeneric->msg1_FDM; format = prach_occasion_info_p->format;
switch (fdm){
case 0:
case 1:
case 2:
case 3:
msg1_FDM = 1 << fdm;
break;
default:
AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", fdm);
}
format0 = format & 0xff; // single PRACH format format0 = format & 0xff; // single PRACH format
format1 = (format >> 8) & 0xff; // dual PRACH format format1 = (format >> 8) & 0xff; // dual PRACH format
ul_config->sfn = frameP; ul_config->sfn = frameP;
ul_config->slot = slotP; ul_config->slot = slotP;
for (int n = 0; n < msg1_FDM; n++) { // one structure per frequency domain occasion
ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH;
prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu;
memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu));
...@@ -1149,15 +1797,25 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ...@@ -1149,15 +1797,25 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig);
// filling PRACH PDU for FAPI config request
prach_config_pdu->phys_cell_id = *scc->physCellId; prach_config_pdu->phys_cell_id = *scc->physCellId;
prach_config_pdu->num_prach_ocas = N_t_slot; prach_config_pdu->num_prach_ocas = 1;
prach_config_pdu->prach_start_symbol = start_symbol; prach_config_pdu->prach_slot = prach_occasion_info_p->slot;
prach_config_pdu->num_ra = n; prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol;
prach_config_pdu->num_ra = prach_occasion_info_p->fdm;
prach_config_pdu->num_cs = ncs; prach_config_pdu->num_cs = ncs;
prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index; prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index;
prach_config_pdu->restricted_set = prach_config->restricted_set_config; prach_config_pdu->restricted_set = prach_config->restricted_set_config;
prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1; prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1;
LOG_D(MAC,"Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", frameP, prach_config_pdu->prach_slot, prach_config_pdu->prach_start_symbol, prach_config_pdu->num_ra);
// Search which SSB is mapped in the RO (among all the SSBs mapped to this RO)
for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) {
if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx)
break;
}
AssertFatal(prach_config_pdu->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx);
if (format1 != 0xff) { if (format1 != 0xff) {
switch(format0) { // dual PRACH format switch(format0) { // dual PRACH format
...@@ -1211,14 +1869,13 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ...@@ -1211,14 +1869,13 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
default: default:
AssertFatal(1 == 0, "Invalid PRACH format"); AssertFatal(1 == 0, "Invalid PRACH format");
} }
} } // if format1
} } // is_nr_prach_slot
}
fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP); fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP);
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
} } // if is_nr_UL_slot
} }
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
...@@ -2233,7 +2890,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, ...@@ -2233,7 +2890,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
uint8_t time_domain_ind uint8_t time_domain_ind
){ ){
int dmrs_typeA_pos = mac->scc->dmrs_TypeA_Position; int dmrs_typeA_pos = mac->scc->dmrs_TypeA_Position;
uint8_t k_offset=0; // uint8_t k_offset=0;
uint8_t sliv_S=0; uint8_t sliv_S=0;
uint8_t sliv_L=0; uint8_t sliv_L=0;
uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1
...@@ -2374,7 +3031,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, ...@@ -2374,7 +3031,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
dlsch_config_pdu->number_symbols=L; dlsch_config_pdu->number_symbols=L;
} }
else {// Default configuration from tables else {// Default configuration from tables
k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; // k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0];
sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1];
sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2];
// k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
...@@ -2417,7 +3074,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, ...@@ -2417,7 +3074,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->nr_of_symbols=L; pusch_config_pdu->nr_of_symbols=L;
} }
else { else {
k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; // k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0];
sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1];
sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2];
// k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; // k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
......
...@@ -274,15 +274,22 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, ...@@ -274,15 +274,22 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
if (ue_mac->RA_RAPID_found) { if (ue_mac->RA_RAPID_found) {
uint8_t freq_hopping, mcs, Msg3_t_alloc, Msg3_f_alloc; uint8_t freq_hopping, mcs, Msg3_t_alloc, Msg3_f_alloc;
unsigned char tpc_command, csi_req; unsigned char tpc_command;
#ifdef DEBUG_RAR
unsigned char csi_req;
#endif
// TC-RNTI // TC-RNTI
*t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
ue_mac->t_crnti = *t_crnti; ue_mac->t_crnti = *t_crnti;
// TA command // TA command
ta_command = rar->TA2 + (rar->TA1 << 5); ta_command = rar->TA2 + (rar->TA1 << 5);
#ifdef DEBUG_RAR
// CSI // CSI
csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01);
#endif
// TPC // TPC
tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07);
switch (tpc_command){ switch (tpc_command){
......
...@@ -128,7 +128,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm ...@@ -128,7 +128,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
uint16_t band; uint16_t band;
int32_t offset; int32_t offset;
get_band((cfg->carrier_config.dl_frequency.value)*1000, get_band((uint64_t)(cfg->carrier_config.dl_frequency.value)*1000,
&band, &band,
&offset, &offset,
&frame_type); &frame_type);
......
...@@ -921,6 +921,10 @@ void nr_generate_Msg2(module_id_t module_idP, ...@@ -921,6 +921,10 @@ void nr_generate_Msg2(module_id_t module_idP,
nr_mac->TX_req[CC_id].Slot = slotP; nr_mac->TX_req[CC_id].Slot = slotP;
memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length); memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length);
T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id),
T_INT(RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0) /* harq pid, meaningful? */,
T_BUFFER(&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length));
/* mark the corresponding RBs as used */ /* mark the corresponding RBs as used */
uint8_t *vrb_map = cc[CC_id].vrb_map; uint8_t *vrb_map = cc[CC_id].vrb_map;
for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++) for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++)
......
...@@ -840,6 +840,9 @@ void nr_schedule_ue_spec(module_id_t module_id, ...@@ -840,6 +840,9 @@ void nr_schedule_ue_spec(module_id_t module_id,
retInfo->mcs = sched_ctrl->mcs; retInfo->mcs = sched_ctrl->mcs;
retInfo->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData; retInfo->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(buf, TBS));
#if defined(ENABLE_MAC_PAYLOAD_DEBUG) #if defined(ENABLE_MAC_PAYLOAD_DEBUG)
if (frame%100 == 0) { if (frame%100 == 0) {
LOG_I(MAC, LOG_I(MAC,
......
...@@ -324,6 +324,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, ...@@ -324,6 +324,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0]; NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0];
if (sduP != NULL) {
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
T_BUFFER(sduP, sdu_lenP));
}
// random access pusch with TC-RNTI // random access pusch with TC-RNTI
if (ra->state == WAIT_Msg3) { if (ra->state == WAIT_Msg3) {
if (sduP != NULL) { // if the CRC passed if (sduP != NULL) { // if the CRC passed
......
...@@ -922,6 +922,7 @@ static missing_data_t next_missing(nr_rlc_entity_am_t *entity, ...@@ -922,6 +922,7 @@ static missing_data_t next_missing(nr_rlc_entity_am_t *entity,
*/ */
ret.sn_start = entity->rx_next; ret.sn_start = entity->rx_next;
ret.so_start = 0; ret.so_start = 0;
ret.next = cur;
goto set_end_different_sdu; goto set_end_different_sdu;
} }
} }
......
...@@ -45,7 +45,7 @@ gNBs = ...@@ -45,7 +45,7 @@ gNBs =
dl_carrierBandwidth = 106; dl_carrierBandwidth = 106;
#initialDownlinkBWP #initialDownlinkBWP
#genericParameters #genericParameters
# this is RBstart=0,L=50 (275*(L-1))+RBstart # this is RBstart=41,L=24 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 6366; initialDLBWPlocationAndBandwidth = 6366;
# subcarrierSpacing # subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
...@@ -74,7 +74,7 @@ gNBs = ...@@ -74,7 +74,7 @@ gNBs =
initialDLBWPk0_3 = 0; initialDLBWPk0_3 = 0;
initialDLBWPmappingType_3 = 0; initialDLBWPmappingType_3 = 0;
#this is SS=1,L=4 #this is SS=1,L=5
initialDLBWPstartSymbolAndLength_3 = 57; initialDLBWPstartSymbolAndLength_3 = 57;
#uplinkConfigCommon #uplinkConfigCommon
...@@ -126,10 +126,10 @@ gNBs = ...@@ -126,10 +126,10 @@ gNBs =
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
# #
msg1_SubcarrierSpacing = 1, msg1_SubcarrierSpacing = 1,
# restrictedSetConfig # restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B # 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0, restrictedSetConfig = 0,
# pusch-ConfigCommon (up to 16 elements) # pusch-ConfigCommon (up to 16 elements)
initialULBWPk2_0 = 6; initialULBWPk2_0 = 6;
initialULBWPmappingType_0 = 1 initialULBWPmappingType_0 = 1
...@@ -146,7 +146,6 @@ gNBs = ...@@ -146,7 +146,6 @@ gNBs =
# this is SS=10 L=4 # this is SS=10 L=4
initialULBWPstartSymbolAndLength_2 = 52; initialULBWPstartSymbolAndLength_2 = 52;
msg3_DeltaPreamble = 1; msg3_DeltaPreamble = 1;
p0_NominalWithGrant =-90; p0_NominalWithGrant =-90;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment