Commit cf1822be authored by Remi Hardy's avatar Remi Hardy
Browse files

Integration 2021 wk18 a

MR !1145 NR_FR2_initsync_fixes
-bug fixes that caused failure in PBCH detection after initial sync in FR2

MR !1100 NR_scheduling_request
-per-UE PUCCH F0 resource, CSI, Preamble 
-Scheduling Request 
-MAC scheduler fixes

MR !1150  rh_ci_phy_test_improve
-beautified HTML report for 5G NR phy test

MR !1113 hack-exit-gnb-when-no-enb-nsa
-Exit gNB if connection to eNB failed - to be modified if needed. We may want to try to connect over and over again until we succeed but the modifications to the code to get this behavior are complex
parents 158c0639 c2acb9e9
#!/bin/bash
while true
do
echo "gNB will be started automatically..."
sleep 1
sudo .././cmake_targets/ran_build/build/nr-softmodem -E -O ../targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
done
......@@ -230,6 +230,7 @@ MACRLCs = (
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
ulsch_max_slots_inactivity = 1;
}
);
......
......@@ -211,6 +211,7 @@ MACRLCs = (
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
ulsch_max_slots_inactivity = 1;
}
);
......
#this is a configuration file
#used to build real time processing statistics
#for 5G NR phy test (gNB terminate)
Title : Processing Time (us)
ColNames :
- Metric
- Average
- Max
- Average vs Reference Deviation (Reference Value ; Acceptability Threshold)
Ref :
feprx : 60.0
feptx_prec : 8.0
feptx_ofdm : 85.0
feptx_total : 75.0
L1 Tx processing : 300.0
DLSCH encoding : 230.0
L1 Rx processing : 175.0
PUSCH inner-receiver : 100.0
PUSCH decoding : 140.0
DL & UL scheduling timing stats : 15.0
UL Indication : 20.0
Threshold :
feprx : 1.25
feptx_prec : 1.25
feptx_ofdm : 1.25
feptx_total : 1.25
L1 Tx processing : 1.25
DLSCH encoding : 1.25
L1 Rx processing : 1.25
PUSCH inner-receiver : 1.25
PUSCH decoding : 1.25
DL & UL scheduling timing stats : 1.25
UL Indication : 1.25
......@@ -453,6 +453,37 @@ class HTMLManagement():
self.htmlFile.write(' </tr>\n')
self.htmlFile.close()
#for the moment it is limited to 4 columns, to be made generic later
def CreateHtmlDataLogTable(self, DataLog):
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
return
self.htmlFile = open('test_results.html', 'a')
# TabHeader
self.htmlFile.write(' <tr bgcolor = "#F0F0F0" >\n')
self.htmlFile.write(' <td colspan=' + str(5+self.htmlUEConnected) + '><b> ---- ' + DataLog['Title'] + ' ---- </b></td>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.write(' <tr bgcolor = "#33CCFF" >\n')
self.htmlFile.write(' <th colspan="3">'+ DataLog['ColNames'][0] +'</th>\n')
self.htmlFile.write(' <th>' + DataLog['ColNames'][1] + '</th>\n')
self.htmlFile.write(' <th>' + DataLog['ColNames'][2] + '</th>\n')
self.htmlFile.write(' <th colspan=' + str(1+self.htmlUEConnected) + '>'+ DataLog['ColNames'][3] +'</th>\n')
self.htmlFile.write(' </tr>\n')
for k in DataLog['Data']:
# TestRow
self.htmlFile.write(' <tr>\n')
self.htmlFile.write(' <td colspan="3" bgcolor = "lightcyan" >' + k + ' </td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + DataLog['Data'][k][0] + ' </td>\n')
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + DataLog['Data'][k][1] + ' </td>\n')
if float(DataLog['Data'][k][2])> DataLog['Threshold'][k]:
self.htmlFile.write(' <th bgcolor = "red" >' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
else:
self.htmlFile.write(' <th bgcolor = "green" ><font color="white">' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
self.htmlFile.write(' </tr>\n')
self.htmlFile.close()
def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
self.htmlFile = open('test_results.html', 'a')
......
......@@ -37,6 +37,8 @@ import logging
import os
import time
from multiprocessing import Process, Lock, SimpleQueue
import yaml
#-----------------------------------------------------------
# OAI Testing modules
......@@ -90,6 +92,7 @@ class RANManagement():
self.testCase_id = ''
self.epcPcapFile = ''
self.runtime_stats= ''
self.datalog_rt_stats={}
......@@ -633,6 +636,8 @@ class RANManagement():
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
else:
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
if len(self.datalog_rt_stats)!=0:
HTML.CreateHtmlDataLogTable(self.datalog_rt_stats)
self.eNBmbmsEnables[int(self.eNB_instance)] = False
self.eNBstatuses[int(self.eNB_instance)] = -1
......@@ -699,6 +704,21 @@ class RANManagement():
#count "problem receiving samples" msg
pb_receiving_samples_cnt = 0
#the datalog config file has to be loaded
datalog_rt_stats_file='datalog_rt_stats.yaml'
if (os.path.isfile(datalog_rt_stats_file)):
yaml_file=datalog_rt_stats_file
elif (os.path.isfile('ci-scripts/'+datalog_rt_stats_file)):
yaml_file='ci-scripts/'+datalog_rt_stats_file
else:
logging.error("Datalog RT stats yaml file cannot be found")
sys.exit("Datalog RT stats yaml file cannot be found")
with open(yaml_file,'r') as f:
datalog_rt_stats = yaml.load(f,Loader=yaml.FullLoader)
rt_keys = datalog_rt_stats['Ref'] #we use the keys from the Ref field
for line in enb_log_file.readlines():
# Runtime statistics
result = re.search('Run time:' ,str(line))
......@@ -857,21 +877,21 @@ class RANManagement():
#keys below are the markers we are loooking for, loop over this keys list
#everytime these markers are found in the log file, the previous ones are overwritten in the dict
#eventually we record and print only the last occurence
keys = {'UE ID','dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled', 'scheduling timing stats'}
keys = {'UE ID','dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled'}
for k in keys:
result = re.search(k, line)
if result is not None:
#remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char
dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip())
#real time statistics
#same method as above
keys = {'feprx','feptx_prec','feptx_ofdm','feptx_total','L1 Tx processing','DLSCH encoding','L1 Rx processing','PUSCH inner-receiver','PUSCH decoding'}
for k in keys:
#real time statistics for gNB
for k in rt_keys:
result = re.search(k, line)
if result is not None:
#remove 1- all useless char before relevant info 2- trailing char
line=line.replace('[0m','')
tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex
real_time_stats[k]=tmp.group(1)
#count "problem receiving samples" msg
result = re.search('\[PHY\]\s+problem receiving samples', str(line))
if result is not None:
......@@ -920,13 +940,23 @@ class RANManagement():
logging.debug(dlsch_ulsch_stats[key])
htmleNBFailureMsg += statMsg
#real time statistics statistics
#real time statistics
datalog_rt_stats['Data']={}
if len(real_time_stats)!=0: #check if dictionary is not empty
statMsg=''
for key in real_time_stats: #for each dictionary key
statMsg += real_time_stats[key] + '\n'
logging.debug(real_time_stats[key])
htmleNBFailureMsg += statMsg
for k in real_time_stats:
tmp=re.match(r'^(?P<metric>.*):\s+(?P<avg>\d+\.\d+) us;\s+\d+;\s+(?P<max>\d+\.\d+) us;',real_time_stats[k])
if tmp is not None:
metric=tmp.group('metric')
avg=float(tmp.group('avg'))
max=float(tmp.group('max'))
datalog_rt_stats['Data'][metric]=["{:.0f}".format(avg),"{:.0f}".format(max),"{:.2f}".format(avg/datalog_rt_stats['Ref'][metric])]
#once all metrics are collected, store the data as a class attribute to build a dedicated HTML table afterward
self.datalog_rt_stats=datalog_rt_stats
#check if there is a fail => will render the test as failed
for k in datalog_rt_stats['Data']:
if float(datalog_rt_stats['Data'][k][2])> datalog_rt_stats['Threshold'][k]: #condition for fail : avg/ref is greater than the fixed threshold
#setting prematureExit is ok although not the best option
self.prematureExit=True
else:
statMsg = 'No real time stats found in the log file\n'
logging.debug('No real time stats found in the log file')
......
......@@ -24,7 +24,7 @@
<htmlTabRef>gNB-PHY-Test</htmlTabRef>
<htmlTabName>Run-gNB-PHY-Test</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<repeatCount>2</repeatCount>
<repeatCount>3</repeatCount>
<TestCaseRequestedList>
090101 000001 090109
</TestCaseRequestedList>
......@@ -40,7 +40,7 @@
<testCase id="000001">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>180</idle_sleep_time_in_sec>
<idle_sleep_time_in_sec>300</idle_sleep_time_in_sec>
</testCase>
......
......@@ -552,7 +552,7 @@ void *UE_thread(void *arg) {
if (UE->is_synchronized) {
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
decoded_frame_rx=(decoded_frame_rx + (!UE->init_sync_frame) + trashed_frames) % MAX_FRAME_NUMBER;
decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER;
}
delNotifiedFIFO_elt(res);
start_rx_stream=0;
......@@ -692,9 +692,9 @@ void *UE_thread(void *arg) {
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
}
if ( decoded_frame_rx>0 && decoded_frame_rx != curMsg->proc.frame_rx)
if (decoded_frame_rx>0 && decoded_frame_rx != curMsg->proc.frame_rx)
LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
decoded_frame_rx, curMsg->proc.frame_rx );
decoded_frame_rx, curMsg->proc.frame_rx);
// use previous timing_advance value to compute writeTimestamp
writeTimestamp = timestamp+
......
......@@ -308,12 +308,15 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames)
// every 7*(1<<mu) symbols there is a different prefix length (38.211 5.3.1)
int n_symb_prefix0 = (ue->symbol_offset/(7*(1<<mu)))+1;
sync_pos_frame = n_symb_prefix0*(fp->ofdm_symbol_size + fp->nb_prefix_samples0)+(ue->symbol_offset-n_symb_prefix0)*(fp->ofdm_symbol_size + fp->nb_prefix_samples);
if (ue->ssb_offset < sync_pos_frame)
// for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of the n_frames we got sync
ue->init_sync_frame = n_frames - 1 - is;
// we also need to take into account the shift by samples_per_frame in case the if is true
if (ue->ssb_offset < sync_pos_frame){
ue->rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset;
ue->init_sync_frame += 1;
}
else
ue->rx_offset = ue->ssb_offset - sync_pos_frame;
ue->init_sync_frame = is;
}
/*
......
......@@ -589,7 +589,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
frame_parms->ssb_index += (((nr_ue_pbch_vars->xtra_byte>>(7-i))&0x01)<<(3+i));
}
ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,i_ssb);
ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,frame_parms->ssb_index);
if (frame_parms->half_frame_bit)
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
......
......@@ -142,7 +142,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
case FAPI_NR_RX_PDU_TYPE_MIB:
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_index = frame_parms->ssb_index;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_index = (frame_parms->ssb_index)&0x7;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_length = frame_parms->Lmax;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.cell_id = frame_parms->Nid_cell;
break;
......@@ -350,7 +350,7 @@ void nr_ue_pbch_procedures(uint8_t gNB_id,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN);
LOG_D(PHY,"[UE %d] Frame %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,ue->frame_parms.Nid_cell,gNB_id);
LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,nr_slot_rx,ue->frame_parms.Nid_cell,gNB_id);
ret = nr_rx_pbch(ue, proc,
ue->pbch_vars[gNB_id],
......
......@@ -733,13 +733,7 @@ int main(int argc, char **argv)
prepare_scd(scd);
fill_default_secondaryCellGroup(scc,
scd,
secondaryCellGroup,
0,
1,
n_tx,
0);
fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0);
/* RRC parameter validation for secondaryCellGroup */
fix_scd(scd);
......
......@@ -676,13 +676,7 @@ int main(int argc, char **argv)
prepare_scd(scd);
fill_default_secondaryCellGroup(scc,
scd,
secondaryCellGroup,
0,
1,
n_tx,
0);
fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0);
// xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
......
......@@ -55,7 +55,7 @@
#define CONFIG_STRING_MACRLC_REMOTE_S_PORTC "remote_s_portc"
#define CONFIG_STRING_MACRLC_LOCAL_S_PORTD "local_s_portd"
#define CONFIG_STRING_MACRLC_REMOTE_S_PORTD "remote_s_portd"
#define CONFIG_STRING_MACRLC_ULSCH_MAX_SLOTS_INACTIVITY "ulsch_max_slots_inactivity"
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* MacRLC configuration parameters */
......@@ -79,6 +79,7 @@
{CONFIG_STRING_MACRLC_REMOTE_S_PORTC, NULL, 0, uptr:NULL, defintval:50020, TYPE_UINT, 0}, \
{CONFIG_STRING_MACRLC_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \
{CONFIG_STRING_MACRLC_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \
{CONFIG_STRING_MACRLC_ULSCH_MAX_SLOTS_INACTIVITY, "Maximum number of slots before a UE is scheduled ULSCH due to inactivity", 0, uptr:NULL, defintval:200, TYPE_UINT, 0}, \
}
#define MACRLC_CC_IDX 0
#define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1
......@@ -97,5 +98,6 @@
#define MACRLC_REMOTE_S_PORTC_IDX 14
#define MACRLC_LOCAL_S_PORTD_IDX 15
#define MACRLC_REMOTE_S_PORTD_IDX 16
#define MACRLC_ULSCH_MAX_SLOTS_INACTIVITY 17
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif
......@@ -53,7 +53,7 @@
//#include "L1_paramdef.h"
#include "L1_nr_paramdef.h"
#include "MACRLC_paramdef.h"
#include "MACRLC_nr_paramdef.h"
#include "common/config/config_userapi.h"
//#include "RRC_config_tools.h"
#include "gnb_paramdef.h"
......@@ -698,6 +698,7 @@ void RCconfig_nr_macrlc() {
}else { // other midhaul
AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
}
RC.nrmac[j]->ulsch_max_slots_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_SLOTS_INACTIVITY].uptr);
}// for (j=0;j<RC.nb_nr_macrlc_inst;j++)
}else {// MacRLC_ParamList.numelt > 0
AssertFatal (0,"No " CONFIG_STRING_MACRLC_LIST " configuration found");
......
......@@ -372,14 +372,6 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL,
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
for (int i = 0; i < MAX_NUM_BWP; ++i) {
RC.nrmac[Mod_idP]->pucch_index_used[i] =
calloc(n, sizeof(*RC.nrmac[Mod_idP]->pucch_index_used));
AssertFatal(RC.nrmac[Mod_idP]->pucch_index_used[i],
"could not allocate memory for RC.nrmac[]->pucch_index_used[%d]\n",
i);
}
LOG_I(MAC,"Configuring common parameters from NR ServingCellConfig\n");
config_common(Mod_idP,
......
......@@ -402,7 +402,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
}
// This schedule SR
// TODO
nr_sr_reporting(module_idP, frame, slot);
// Schedule CSI measurement reporting: check in slot 0 for the whole frame
if (slot == 0)
......
......@@ -253,8 +253,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
case 3:
// long bitmap FR2 max 64 SSBs
num_ssb = 0;
for (int i_ssb=0; i_ssb<63; i_ssb++) {
if ((longBitmap->buf[i_ssb/8]>>(7-i_ssb))&0x01) {
for (int i_ssb=0; i_ssb<64; i_ssb++) {
if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) {
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
if ((ssb_start_symbol/14) == rel_slot){
......
......@@ -118,8 +118,13 @@ int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = {
void nr_schedule_pucch(int Mod_idP,
frame_t frameP,
sub_frame_t slotP) {
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
sub_frame_t slotP)
{
gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP];
if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP))
return;
NR_UE_info_t *UE_info = &nrmac->UE_info;
const NR_list_t *UE_list = &UE_info->list;
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
......@@ -504,11 +509,11 @@ void nr_csi_meas_reporting(int Mod_idP,
// find free PUCCH that is in order with possibly existing PUCCH
// schedulings (other CSI, SR)
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2];
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1];
AssertFatal(curr_pucch->csi_bits == 0
&& !curr_pucch->sr_flag
&& curr_pucch->dai_c == 0,
"PUCCH not free at index 2 for UE %04x\n",
"PUCCH not free at index 1 for UE %04x\n",
UE_info->rnti[UE_id]);
curr_pucch->frame = frame;
curr_pucch->ul_slot = sched_slot;
......@@ -1007,14 +1012,6 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
// tpc (power control)
sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10,
uci_01->ul_cqi,
30);
sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640;
NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
if (((uci_01->pduBitmap >> 1) & 0x01)) {
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
......@@ -1029,6 +1026,20 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
}
}
// check scheduling request result, confidence_level == 0 is good
if (uci_01->pduBitmap & 0x1 && uci_01->sr->sr_indication && uci_01->sr->sr_confidence_level == 0 && uci_01->ul_cqi >= 148) {
// SR detected with SNR >= 10dB
sched_ctrl->SR |= true;
LOG_D(MAC, "SR UE %04x ul_cqi %d\n", uci_01->rnti, uci_01->ul_cqi);
}
// tpc (power control) only if we received AckNack or positive SR. For a
// negative SR, the UE won't have sent anything, and the SNR is not valid
if (((uci_01->pduBitmap >> 1) & 0x1) || sched_ctrl->SR) {
sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_01->ul_cqi, 30);
sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640;
}
}
void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
......@@ -1051,8 +1062,6 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
30);
sched_ctrl->pucch_snrx10 = uci_234->ul_cqi * 5 - 640;
NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
if ((uci_234->pduBitmap >> 1) & 0x01) {
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
......@@ -1104,10 +1113,7 @@ bool nr_acknack_scheduling(int mod_id,
* * we do not multiplex with CSI, which is always in pucch_sched[2]
* * SR uses format 0 and is allocated in the first UL (mixed) slot (and not
* later)
* * that the PUCCH resource set 0 (for up to 2 bits) points to the first N
* PUCCH resources, where N is the number of resources in the PUCCH
* resource set. This is used in pucch_index_used, which counts the used
* resources by index, and not by their ID! */
* * each UE has dedicated PUCCH Format 0 resources, and we use index 0! */
NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id];
NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
AssertFatal(pucch->csi_bits == 0,
......@@ -1115,12 +1121,8 @@ bool nr_acknack_scheduling(int mod_id,
__func__,
pucch->csi_bits);
const int max_acknacks = 2;
AssertFatal(pucch->dai_c + pucch->sr_flag <= max_acknacks,
"illegal number of bits in PUCCH of UE %d\n",
UE_id);
/* if the currently allocated PUCCH of this UE is full, allocate it */
if (pucch->sr_flag + pucch->dai_c == max_acknacks) {
if (pucch->dai_c == 2) {
/* advance the UL slot information in PUCCH by one so we won't schedule in
* the same slot again */
const int f = pucch->frame;
......@@ -1130,7 +1132,7 @@ bool nr_acknack_scheduling(int mod_id,
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
pucch->ul_slot = (s + 1) % n_slots_frame;
// we assume that only two indices over the array sched_pucch exist
const NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[2];
NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1];
// skip the CSI PUCCH if it is present and if in the next frame/slot
if (csi_pucch->csi_bits > 0
&& csi_pucch->frame == pucch->frame
......@@ -1142,6 +1144,7 @@ bool nr_acknack_scheduling(int mod_id,
pucch->ul_slot,
UE_id);
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
memset(csi_pucch, 0, sizeof(*csi_pucch));
pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f;
pucch->ul_slot = (s + 2) % n_slots_frame;
}
......@@ -1160,9 +1163,8 @@ bool nr_acknack_scheduling(int mod_id,
uint8_t pdsch_to_harq_feedback[8];
get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback);
/* there is a scheduled SR or HARQ. Check whether we can use it for this
* ACKNACK */
if (pucch->sr_flag + pucch->dai_c > 0) {
/* there is a HARQ. Check whether we can use it for this ACKNACK */
if (pucch->dai_c > 0) {
/* this UE already has a PUCCH occasion */
DevAssert(pucch->frame == frame);
......@@ -1193,18 +1195,14 @@ bool nr_acknack_scheduling(int mod_id,
/* we need to find a new PUCCH occasion */
NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
DevAssert(pucch_Config->resourceToAddModList->list.count > 0);
DevAssert(pucch_Config->resourceSetToAddModList->list.count > 0);
const int n_res = pucch_Config->resourceSetToAddModList->list.array[0]->resourceList.list.count;
int *pucch_index_used = RC.nrmac[mod_id]->pucch_index_used[sched_ctrl->active_ubwp->bwp_Id];
/* if time information is outdated (e.g., last PUCCH occasion in last frame),
* set to first possible UL occasion in this frame. Note that if such UE is
* scheduled a lot and used all AckNacks, pucch->frame might have been
* wrapped around to next frame */
if (frame != pucch->frame || pucch->ul_slot < first_ul_slot_tdd) {
DevAssert(pucch->sr_flag + pucch->dai_c == 0);
AssertFatal(pucch->sr_flag + pucch->dai_c == 0,
"expected no SR/AckNack for UE %d in %4d.%2d, but has %d/%d for %4d.%2d\n",
UE_id, frame, slot, pucch->sr_flag, pucch->dai_c, pucch->frame, pucch->ul_slot);
AssertFatal(frame + 1 != pucch->frame,
"frame wrap around not handled in %s() yet\n",
__func__);
......@@ -1212,27 +1210,11 @@ bool nr_acknack_scheduling(int mod_id,
pucch->ul_slot = first_ul_slot_tdd;
}
// increase to first slot in which PUCCH resources are available
while (pucch_index_used[pucch->ul_slot] >= n_res) {
pucch->ul_slot++;
/* if there is no free resource anymore, abort search */
if ((pucch->frame == frame
&& pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)
|| (pucch->frame == frame + 1)) {
LOG_E(MAC,
"%4d.%2d no free PUCCH resources anymore while searching for UE %d\n",
frame,
slot,
UE_id);
return false;
}
}
// advance ul_slot if it is not reachable by UE
pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]);
// is there already CSI in this slot?
const NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[2];
NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1];
// skip the CSI PUCCH if it is present and if in the next frame/slot
if (csi_pucch->csi_bits > 0
&& csi_pucch->frame == pucch->frame
......@@ -1244,6 +1226,7 @@ bool nr_acknack_scheduling(int mod_id,
pucch->ul_slot,
UE_id);
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
memset(csi_pucch, 0, sizeof(*csi_pucch));
/* advance the UL slot information in PUCCH by one so we won't schedule in
* the same slot again */
const int f = pucch->frame;
......@@ -1274,29 +1257,19 @@ bool nr_acknack_scheduling(int mod_id,
pucch->timing_indicator = i; // index in the list of timing indicators
pucch->dai_c++;
const int pucch_res = pucch_index_used[pucch->ul_slot];