diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
index 259a2466ad..258618e7f0 100644
--- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
@@ -1,7 +1,6 @@
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
-Num_Threads_PUSCH = 8
gNBs =
@@ -251,6 +250,7 @@ L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
+ pusch_proc_threads = 8;
}
);
diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml
index ed134f478c..b1e9697be2 100644
--- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml
+++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml
@@ -52,7 +52,7 @@
Initialize_OAI_UE
Initialize NR UE USRP
- --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 75 --rrc_config_path . --dlsch-parallel 4
+ --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 50 --rrc_config_path . --dlsch-parallel 4
NR
diff --git a/doc/SW_archi.md b/doc/SW_archi.md
index 412dad402d..d92f802148 100644
--- a/doc/SW_archi.md
+++ b/doc/SW_archi.md
@@ -186,7 +186,7 @@ development], for FR2 does not exist yet.
3) allocate a CCE for the UE (and return if it is not possible)
4) Calculate DMRS stuff (nr_save_pusch_fields()) and the TBS.
5) Mark used resources in vrb_map_UL.
-* loop through all users: get a free HARQ PID using select_ul_harq_pid() and
+* loop through all users: get a free HARQ PID and
update statistics. Fill nFAPI structures directly for PUSCH, and call
config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH messages.
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index be9261a117..4a655dfc57 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -873,10 +873,7 @@ void init_gNB_proc(int inst) {
gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
- uint32_t num_threads_pusch;
- paramdef_t PUSCHThreads[] = NUM_THREADS_DESC;
- config_get( PUSCHThreads,sizeof(PUSCHThreads)/sizeof(paramdef_t),NULL);
- int threadCnt = min(numCPU, num_threads_pusch);
+ int threadCnt = min(numCPU, gNB->pusch_proc_threads);
char ul_pool[80];
sprintf(ul_pool,"-1");
int s_offset = 0;
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index ac77ff810b..be5b44b86a 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -716,14 +716,14 @@ void *UE_thread(void *arg) {
else if (slot_tx_usrp%tdd_period>first_tx_slot)
flags = 1;
- if (flags || IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1)
- AssertFatal( writeBlockSize ==
- UE->rfdevice.trx_write_func(&UE->rfdevice,
- writeTimestamp,
- txp,
- writeBlockSize,
- UE->frame_parms.nb_antennas_tx,
- flags),"");
+ if (flags || IS_SOFTMODEM_RFSIM)
+ AssertFatal(writeBlockSize ==
+ UE->rfdevice.trx_write_func(&UE->rfdevice,
+ writeTimestamp,
+ txp,
+ writeBlockSize,
+ UE->frame_parms.nb_antennas_tx,
+ flags),"");
for (int i=0; iframe_parms.nb_antennas_tx; i++)
memset(txp[i], 0, writeBlockSize);
@@ -732,7 +732,7 @@ void *UE_thread(void *arg) {
msgToPush->key=slot_nr;
pushTpool(&(get_nrUE_params()->Tpool), msgToPush);
- if ( IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) { //getenv("RFSIMULATOR")
+ if (IS_SOFTMODEM_RFSIM) { //getenv("RFSIMULATOR")
// FixMe: Wait previous thread is done, because race conditions seems too bad
// in case of actual RF board, the overlap between threads mitigate the issue
// We must receive one message, that proves the slot processing is done
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
index 8594dbbd1b..4491c35029 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
@@ -619,30 +619,30 @@ typedef struct
typedef struct {
// The RNTI used for identifying the UE when receiving the PDU Value: 1 -> 65535.
- uint16_t RNTI[MAX_DCI_CORESET];
+ uint16_t RNTI;
// For a UE-specific search space it equals the higher-layer parameter PDCCH-DMRSScrambling-ID if configured,
// otherwise it should be set to the phy cell ID. [TS38.211, sec 7.3.2.3] Value: 0->65535
- uint16_t ScramblingId[MAX_DCI_CORESET];
+ uint16_t ScramblingId;
// For a UE-specific search space where PDCCH-DMRSScrambling- ID is configured This param equals the CRNTI.
// Otherwise, it should be set to 0. [TS38.211, sec 7.3.2.3] Value: 0 -> 65535
- uint16_t ScramblingRNTI[MAX_DCI_CORESET];
+ uint16_t ScramblingRNTI;
// CCE start Index used to send the DCI Value: 0->135
- uint8_t CceIndex[MAX_DCI_CORESET];
+ uint8_t CceIndex;
// Aggregation level used [TS38.211, sec 7.3.2.1] Value: 1,2,4,8,16
- uint8_t AggregationLevel[MAX_DCI_CORESET];
+ uint8_t AggregationLevel;
// Precoding and Beamforming structure See Table 3-43
- nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming[MAX_DCI_CORESET];
+ nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming;
// PDCCH power value used for PDCCH Format 1_0 with CRC scrambled by SI-RNTI, PI-RNTI or RA-RNTI.
// This is ratio of SSB/PBCH EPRE to PDCCH and PDCCH DMRS EPRE [TS38.213, sec 4.1]
// Value :0->17 Report title: 5G FAPI: PHY API Specification Issue date: 29 June 2019 Version: 222.10.17 68 Field Type Description representing -8 to 8 dB in 1dB steps
- uint8_t beta_PDCCH_1_0[MAX_DCI_CORESET];
+ uint8_t beta_PDCCH_1_0;
// PDCCH power value used for all other PDCCH Formats.
// This is ratio of SSB/PBCH block EPRE to PDCCH and PDCCH DMRS EPRE [TS38.214, sec 4.1] Values: 0: -3dB,1: 0dB,2: 3dB,3: 6dB
- uint8_t powerControlOffsetSS[MAX_DCI_CORESET];
+ uint8_t powerControlOffsetSS;
// The total DCI length (in bits) including padding bits [TS38.212 sec 7.3.1] Range 0->DCI_PAYLOAD_BYTE_LEN*8
- uint16_t PayloadSizeBits[MAX_DCI_CORESET];
+ uint16_t PayloadSizeBits;
// DCI payload, where the actual size is defined by PayloadSizeBits. The bit order is as following bit0-bit7 are mapped to first byte of MSB - LSB
- uint8_t Payload[MAX_DCI_CORESET][DCI_PAYLOAD_BYTE_LEN];
+ uint8_t Payload[DCI_PAYLOAD_BYTE_LEN];
} nfapi_nr_dl_dci_pdu_t;
@@ -677,7 +677,7 @@ typedef struct {
///Number of DCIs in this CORESET.Value: 0->MaxDciPerSlot
uint16_t numDlDci;
///DL DCI PDU
- nfapi_nr_dl_dci_pdu_t dci_pdu;
+ nfapi_nr_dl_dci_pdu_t dci_pdu[MAX_DCI_CORESET];
} nfapi_nr_dl_tti_pdcch_pdu_rel15_t;
typedef struct {
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index 8d7a8a3127..7f4698cdbc 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -254,9 +254,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value;
- printf("Before ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]);
for (int ULSCH_id=0; ULSCH_iddlsch[0][0]->harq_processes[0]);
pusch_vars[ULSCH_id] = (NR_gNB_PUSCH *)malloc16_clear( sizeof(NR_gNB_PUSCH) );
pusch_vars[ULSCH_id]->rxdataF_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) );
pusch_vars[ULSCH_id]->rxdataF_ext2 = (int32_t **)malloc16(Prx*sizeof(int32_t *) );
@@ -273,7 +271,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(Prx*sizeof(int32_t *) );
pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(Prx*sizeof(int32_t*) );
- printf("ULSCH_id %d (before rx antenna alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]);
for (i=0; irxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot );
pusch_vars[ULSCH_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot );
@@ -290,16 +287,13 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
pusch_vars[ULSCH_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 );
pusch_vars[ULSCH_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(fp->N_RB_UL*12*7*2) );
}
- printf("ULSCH_id %d (before llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]);
pusch_vars[ULSCH_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear
- printf("ULSCH_id %d (after llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]);
pusch_vars[ULSCH_id]->ul_valid_re_per_slot = (int16_t *)malloc16_clear( sizeof(int16_t)*fp->symbols_per_slot);
} //ulsch_id
/*
for (ulsch_id=0; ulsch_idUE_stats_ptr[ulsch_id] = &gNB->UE_stats[ulsch_id];
*/
- printf("After ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]);
return (0);
}
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c
index 9dcd326743..7b0a0150d3 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dci.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c
@@ -95,6 +95,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
* in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0
* or the rb_offset for other coresets
* in time: by its first slot and its first symbol*/
+ const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d];
cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex;
cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
@@ -103,7 +104,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
LOG_D(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb);
// DMRS length is per OFDM symbol
uint32_t dmrs_length = n_rb*6; //2(QPSK)*3(per RB)*6(REG per CCE)
- uint32_t encoded_length = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*108; //2(QPSK)*9(per RB)*6(REG per CCE)
+ uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE)
LOG_D(PHY, "DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d)\n", dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType);
dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset
@@ -125,19 +126,19 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
// CRC attachment + Scrambling + Channel coding + Rate matching
uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD];
- uint16_t n_RNTI = pdcch_pdu_rel15->dci_pdu.RNTI[d];
- uint16_t Nid = pdcch_pdu_rel15->dci_pdu.ScramblingId[d];
- uint16_t scrambling_RNTI = pdcch_pdu_rel15->dci_pdu.ScramblingRNTI[d];
+ uint16_t n_RNTI = dci_pdu->RNTI;
+ uint16_t Nid = dci_pdu->ScramblingId;
+ uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI;
t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE,
- pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d],
- pdcch_pdu_rel15->dci_pdu.AggregationLevel[d],
+ dci_pdu->PayloadSizeBits,
+ dci_pdu->AggregationLevel,
0,NULL);
- polar_encoder_fast((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d], (void*)encoder_output, n_RNTI,1,currentPtr);
+ polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI,1,currentPtr);
#ifdef DEBUG_CHANNEL_CODING
- printf("polar rnti %x,length %d, L %d\n",n_RNTI, pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d],pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]);
+ printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]);
printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n",
- ((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[0], ((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[1]);
+ ((uint64_t*)dci_pdu->Payload)[0], ((uint64_t*)dci_pdu->Payload)[1]);
printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5);
for (int i=0; i>5; i++)
@@ -173,7 +174,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
int reg_list_index = 0;
int reg_list_order[NR_MAX_PDCCH_AGG_LEVEL] = {};
for (int p = 0; p < NR_MAX_PDCCH_AGG_LEVEL; p++) {
- for(int p2 = 0; p2 < pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; p2++) {
+ for(int p2 = 0; p2 < dci_pdu->AggregationLevel; p2++) {
if(gNB->cce_list[d][p2].reg_list[0].reg_idx == p * NR_NB_REG_PER_CCE) {
reg_list_order[reg_list_index] = p2;
reg_list_index++;
@@ -183,7 +184,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
}
/*Mapping the encoded DCI along with the DMRS */
- for (int cce_count = 0; cce_count < pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; cce_count ++) {
+ for (int cce_count = 0; cce_count < dci_pdu->AggregationLevel; cce_count ++) {
int8_t cce_idx = reg_list_order[cce_count];
@@ -240,9 +241,10 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
} // reg_in_cce_idx
} // cce_count
- LOG_D(PHY, "DCI: payloadSize = %d | payload = %llx\n",
- *pdcch_pdu_rel15->dci_pdu.PayloadSizeBits,*(unsigned long long*)pdcch_pdu_rel15->dci_pdu.Payload);
-
+ LOG_D(PHY,
+ "DCI: payloadSize = %d | payload = %llx\n",
+ dci_pdu->PayloadSizeBits,
+ *(unsigned long long *)dci_pdu->Payload);
} // for (int d=0;dnumDlDci;d++)
}
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
index 2b64a3062c..3814c78295 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c
@@ -142,7 +142,7 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r
AssertFatal(N_reg > 0,"N_reg cannot be 0\n");
for (int d=0;dnumDlDci;d++) {
- int L = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d];
+ int L = pdcch_pdu_rel15->dci_pdu[d].AggregationLevel;
if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_MIB_SIB1)
AssertFatal(L>=4, "Invalid aggregation level for SIB1 configured PDCCH %d\n", L);
@@ -153,10 +153,10 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r
C = N_reg/(bsize*R);
}
- LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu.CceIndex[d]);
+ LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu[d].CceIndex);
for (uint8_t cce_idx=0; cce_idxcce_list[d][cce_idx];
- cce->cce_idx = pdcch_pdu_rel15->dci_pdu.CceIndex[d] + cce_idx;
+ cce->cce_idx = pdcch_pdu_rel15->dci_pdu[d].CceIndex + cce_idx;
LOG_D(PHY, "cce_idx %d\n", cce->cce_idx);
if (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) {
@@ -236,25 +236,24 @@ void nr_fill_dci(PHY_VARS_gNB *gNB,
for (int i=0;inumDlDci;i++) {
- //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i];
+ //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
- int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu.RNTI[i],gNB,SEARCH_EXIST_OR_FREE);
+ int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu[i].RNTI,gNB,SEARCH_EXIST_OR_FREE);
if( (dlsch_id<0) || (dlsch_id>=NUMBER_OF_NR_DLSCH_MAX) ){
- LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu.RNTI[i],dlsch_id);
+ LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu[i].RNTI,dlsch_id);
return;
}
dlsch = gNB->dlsch[dlsch_id][0];
- int num_slots_tdd = (gNB->frame_parms.slots_per_frame)>>(7-gNB->gNB_config.tdd_table.tdd_period.value);
- int harq_pid = slot % num_slots_tdd;
+ int harq_pid = 0;
dlsch->slot_tx[slot] = 1;
- dlsch->harq_ids[frame%2][slot] = harq_pid;
+ dlsch->harq_ids[frame % 2][slot] = 0;
AssertFatal(harq_pid < 8 && harq_pid >= 0,
"illegal harq_pid %d\n",harq_pid);
dlsch->harq_mask |= (1<rnti = pdcch_pdu_rel15->dci_pdu.RNTI[i];
+ dlsch->rnti = pdcch_pdu_rel15->dci_pdu[i].RNTI;
// nr_fill_cce_list(gNB,0);
/*
@@ -300,7 +299,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB,
for (int i=0;inumDlDci;i++) {
- //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i];
+ //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload;
// if there's no DL DCI then generate CCE list
// nr_fill_cce_list(gNB,0);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index b1ac7efd80..5fa85fc13f 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -136,8 +136,7 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
dlsch = gNB->dlsch[dlsch_id][0];
if (dlsch->slot_tx[slot] == 0) continue;
- int harq_pid = dlsch->harq_ids[frame%2][slot];
- NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid];
+ NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5];
int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs;
@@ -439,15 +438,8 @@ void dump_pdsch_stats(PHY_VARS_gNB *gNB) {
for (int i=0;idlsch_stats[i].rnti > 0)
- LOG_I(PHY,"DLSCH RNTI %x: round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, current_Qm %d, current_RI %d, total_bytes TX %d\n",
+ LOG_D(PHY,"DLSCH RNTI %x: current_Qm %d, current_RI %d, total_bytes TX %d\n",
gNB->dlsch_stats[i].rnti,
- gNB->dlsch_stats[i].round_trials[0],
- (double)gNB->dlsch_stats[i].round_trials[1]/gNB->dlsch_stats[i].round_trials[0],
- gNB->dlsch_stats[i].round_trials[1],
- (double)gNB->dlsch_stats[i].round_trials[2]/gNB->dlsch_stats[i].round_trials[0],
- gNB->dlsch_stats[i].round_trials[2],
- (double)gNB->dlsch_stats[i].round_trials[3]/gNB->dlsch_stats[i].round_trials[0],
- gNB->dlsch_stats[i].round_trials[3],
gNB->dlsch_stats[i].current_Qm,
gNB->dlsch_stats[i].current_RI,
gNB->dlsch_stats[i].total_bytes_tx);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
index cb395ff4af..e6544bbe0c 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
@@ -51,7 +51,6 @@
void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB)
{
- int i;
int r;
NR_gNB_DLSCH_t *dlsch = *dlschptr;
@@ -63,76 +62,61 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB)
a_segments = a_segments*N_RB;
a_segments = a_segments/273 +1;
}
-
-
-
+
+
+
#ifdef DEBUG_DLSCH_FREE
LOG_D(PHY,"Freeing dlsch %p\n",dlsch);
#endif
-
- for (i=0; iMdlharq; i++) {
+ NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
+ if (harq->b) {
+ free16(harq->b, a_segments * 1056);
+ harq->b = NULL;
#ifdef DEBUG_DLSCH_FREE
- LOG_D(PHY,"Freeing dlsch process %d\n",i);
+ LOG_D(PHY, "Freeing harq->b (%p)\n", harq->b);
#endif
- if (dlsch->harq_processes[i]) {
+ if (harq->e) {
+ free16(harq->e, 14 * N_RB * 12 * 8);
+ harq->e = NULL;
#ifdef DEBUG_DLSCH_FREE
- LOG_D(PHY,"Freeing dlsch process %d (%p)\n",i,dlsch->harq_processes[i]);
+ printf("Freeing dlsch process %d e (%p)\n", i, harq->e);
#endif
-
- if (dlsch->harq_processes[i]->b) {
- free16(dlsch->harq_processes[i]->b,a_segments*1056);
- dlsch->harq_processes[i]->b = NULL;
-#ifdef DEBUG_DLSCH_FREE
- LOG_D(PHY,"Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b);
-#endif
- }
-
- if (dlsch->harq_processes[i]->e) {
- free16(dlsch->harq_processes[i]->e,14*N_RB*12*8);
- dlsch->harq_processes[i]->e = NULL;
-#ifdef DEBUG_DLSCH_FREE
- printf("Freeing dlsch process %d e (%p)\n",i,dlsch->harq_processes[i]->e);
-#endif
- }
-
- if (dlsch->harq_processes[i]->f) {
- free16(dlsch->harq_processes[i]->f,14*N_RB*12*8);
- dlsch->harq_processes[i]->f = NULL;
-#ifdef DEBUG_DLSCH_FREE
- printf("Freeing dlsch process %d f (%p)\n",i,dlsch->harq_processes[i]->f);
-#endif
- }
-
-#ifdef DEBUG_DLSCH_FREE
- LOG_D(PHY,"Freeing dlsch process %d c (%p)\n",i,dlsch->harq_processes[i]->c);
-#endif
-
- for (r=0; rharq_processes[i]->c[r]);
-#endif
-
- if (dlsch->harq_processes[i]->c[r]) {
- free16(dlsch->harq_processes[i]->c[r],1056);
- dlsch->harq_processes[i]->c[r] = NULL;
- }
- if (dlsch->harq_processes[i]->d[r]) {
- free16(dlsch->harq_processes[i]->d[r],3*8448);
- dlsch->harq_processes[i]->d[r] = NULL;
- }
-
- }
- free16(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t));
- dlsch->harq_processes[i] = NULL;
}
- }
- free16(dlsch,sizeof(NR_gNB_DLSCH_t));
- *dlschptr = NULL;
+ if (harq->f) {
+ free16(harq->f, 14 * N_RB * 12 * 8);
+ harq->f = NULL;
+#ifdef DEBUG_DLSCH_FREE
+ printf("Freeing dlsch process %d f (%p)\n", i, harq->f);
+#endif
+ }
+
+#ifdef DEBUG_DLSCH_FREE
+ LOG_D(PHY, "Freeing dlsch process %d c (%p)\n", i, harq->c);
+#endif
+
+ for (r = 0; r < a_segments; r++) {
+#ifdef DEBUG_DLSCH_FREE
+ LOG_D(PHY, "Freeing dlsch process %d c[%d] (%p)\n", i, r, harq->c[r]);
+#endif
+
+ if (harq->c[r]) {
+ free16(harq->c[r], 1056);
+ harq->c[r] = NULL;
+ }
+ if (harq->d[r]) {
+ free16(harq->d[r], 3 * 8448);
+ harq->d[r] = NULL;
+ }
+ }
+ free16(harq, sizeof(NR_DL_gNB_HARQ_t));
+ harq = NULL;
+ }
}
+ free16(dlsch, sizeof(NR_gNB_DLSCH_t));
+ *dlschptr = NULL;
}
NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
@@ -142,9 +126,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
uint8_t abstraction_flag,
uint16_t N_RB)
{
-
- NR_gNB_DLSCH_t *dlsch;
- unsigned char exit_flag = 0,i,r,aa,layer;
+ unsigned char i,r,aa,layer;
int re;
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated
@@ -155,127 +137,74 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
+ NR_gNB_DLSCH_t *dlsch = malloc16(sizeof(NR_gNB_DLSCH_t));
+ AssertFatal(dlsch, "cannot allocate dlsch\n");
+
+ bzero(dlsch,sizeof(NR_gNB_DLSCH_t));
+ dlsch->Kmimo = Kmimo;
+ dlsch->Mdlharq = Mdlharq;
+ dlsch->Mlimit = 4;
+ dlsch->Nsoft = Nsoft;
- dlsch = (NR_gNB_DLSCH_t *)malloc16(sizeof(NR_gNB_DLSCH_t));
+ for (layer=0; layerue_spec_bf_weights[layer] = (int32_t **)malloc16(64 * sizeof(int32_t *));
- if (dlsch) {
- bzero(dlsch,sizeof(NR_gNB_DLSCH_t));
- dlsch->Kmimo = Kmimo;
- dlsch->Mdlharq = Mdlharq;
- dlsch->Mlimit = 4;
- dlsch->Nsoft = Nsoft;
-
- for (layer=0; layerue_spec_bf_weights[layer] = (int32_t**)malloc16(64*sizeof(int32_t*));
-
- for (aa=0; aa<64; aa++) {
- dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
- for (re=0;reue_spec_bf_weights[layer][aa][re] = 0x00007fff;
- }
- }
-
- dlsch->txdataF[layer] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH/NR_MAX_NB_LAYERS)*sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH
- }
-
- for (int q=0; qmod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH*sizeof(int32_t));
-
- dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(64*sizeof(int32_t*));
- for (aa=0; aa<64; aa++) {
- dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
-
- }
-
- for (i=0; i<20; i++) {
- dlsch->harq_ids[0][i] = 0;
- dlsch->harq_ids[1][i] = 0;
- }
-
- for (i=0; iharq_processes[i] = (NR_DL_gNB_HARQ_t *)malloc16(sizeof(NR_DL_gNB_HARQ_t));
- LOG_T(PHY, "Required mem size %d dlsch->harq_processes[%d] %p\n",
- dlsch_bytes, i,dlsch->harq_processes[i]);
-
- if (dlsch->harq_processes[i]) {
- bzero(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t));
- // dlsch->harq_processes[i]->first_tx=1;
- dlsch->harq_processes[i]->b = (unsigned char*)malloc16(dlsch_bytes);
- dlsch->harq_processes[i]->pdu = (uint8_t*)malloc16(dlsch_bytes);
- if (dlsch->harq_processes[i]->pdu) {
- bzero(dlsch->harq_processes[i]->pdu,dlsch_bytes);
- nr_emulate_dlsch_payload(dlsch->harq_processes[i]->pdu, (dlsch_bytes)>>3);
- } else {
- LOG_D(PHY,"Can't allocate PDU\n");
- exit_flag=1;
- }
-
- if (dlsch->harq_processes[i]->b) {
- bzero(dlsch->harq_processes[i]->b,dlsch_bytes);
- } else {
- LOG_D(PHY,"Can't get b\n");
- exit_flag=1;
- }
-
- if (abstraction_flag==0) {
- for (r=0; rharq_processes[i]->c[r] = (uint8_t*)malloc16(8448);
- dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output
- if (dlsch->harq_processes[i]->c[r]) {
- bzero(dlsch->harq_processes[i]->c[r],8448);
- } else {
- LOG_D(PHY,"Can't get c\n");
- exit_flag=2;
- }
- if (dlsch->harq_processes[i]->d[r]) {
- bzero(dlsch->harq_processes[i]->d[r],(3*8448));
- } else {
- LOG_D(PHY,"Can't get d\n");
- exit_flag=2;
- }
- }
- dlsch->harq_processes[i]->e = (uint8_t*)malloc16(14*N_RB*12*8);
- if (dlsch->harq_processes[i]->e) {
- bzero(dlsch->harq_processes[i]->e,14*N_RB*12*8);
- } else {
- printf("Can't get e\n");
- exit_flag=1;
- }
- dlsch->harq_processes[i]->f = (uint8_t*)malloc16(14*N_RB*12*8);
- if (dlsch->harq_processes[i]->f) {
- bzero(dlsch->harq_processes[i]->f,14*N_RB*12*8);
- } else {
- printf("Can't get f\n");
- exit_flag=1;
- }
- }
- } else {
- LOG_D(PHY,"Can't get harq_p %d\n",i);
- exit_flag=3;
+ for (aa = 0; aa < 64; aa++) {
+ dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES * sizeof(int32_t));
+ for (re = 0; re < OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
+ dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
}
}
- if (exit_flag==0) {
- for (i=0; iharq_processes[i]->round=0;
- }
-
- return(dlsch);
- }
+ dlsch->txdataF[layer] =
+ (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH / NR_MAX_NB_LAYERS)
+ * sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH
}
- LOG_D(PHY,"new_gNB_dlsch exit flag %d, size of %ld\n",
- exit_flag, sizeof(NR_gNB_DLSCH_t));
+ for (int q = 0; q < NR_MAX_NB_CODEWORDS; q++)
+ dlsch->mod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH * sizeof(int32_t));
- free_gNB_dlsch(&dlsch,N_RB);
+ dlsch->calib_dl_ch_estimates = (int32_t **)malloc16(64 * sizeof(int32_t *));
+ for (aa = 0; aa < 64; aa++) {
+ dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES * sizeof(int32_t));
+ }
- return(NULL);
+ for (i = 0; i < 20; i++) {
+ dlsch->harq_ids[0][i] = 0;
+ dlsch->harq_ids[1][i] = 0;
+ }
+ NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
+ bzero(harq, sizeof(NR_DL_gNB_HARQ_t));
+ harq->b = malloc16(dlsch_bytes);
+ AssertFatal(harq->b, "cannot allocate memory for harq->b\n");
+ harq->pdu = malloc16(dlsch_bytes);
+ AssertFatal(harq->pdu, "cannot allocate memory for harq->pdu\n");
+ bzero(harq->pdu, dlsch_bytes);
+ nr_emulate_dlsch_payload(harq->pdu, (dlsch_bytes) >> 3);
+ bzero(harq->b, dlsch_bytes);
+
+ for (r = 0; r < a_segments; r++) {
+ // account for filler in first segment and CRCs for multiple segment case
+ // [hna] 8448 is the maximum CB size in NR
+ // 68*348 = 68*(maximum size of Zc)
+ // In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc)
+ harq->c[r] = malloc16(8448);
+ AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r);
+ harq->d[r] = malloc16(68 * 384);
+ AssertFatal(harq->d[r], "cannot allocate harq->d[%d]\n", r); // max size for coded output
+ bzero(harq->c[r], 8448);
+ bzero(harq->d[r], (3 * 8448));
+ harq->e = malloc16(14 * N_RB * 12 * 8);
+ AssertFatal(harq->e, "cannot allocate harq->e\n");
+ bzero(harq->e, 14 * N_RB * 12 * 8);
+ harq->f = malloc16(14 * N_RB * 12 * 8);
+ AssertFatal(harq->f, "cannot allocate harq->f\n");
+ bzero(harq->f, 14 * N_RB * 12 * 8);
+ }
+
+ return(dlsch);
}
void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch)
@@ -284,28 +213,21 @@ void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch)
unsigned char Mdlharq;
unsigned char i,j,r;
- if (dlsch) {
- Mdlharq = dlsch->Mdlharq;
- dlsch->rnti = 0;
- dlsch->active = 0;
+ AssertFatal(dlsch!=NULL,"dlsch is null\n");
+ Mdlharq = dlsch->Mdlharq;
+ dlsch->rnti = 0;
+ dlsch->active = 0;
+ NR_DL_gNB_HARQ_t *harq=&dlsch->harq_process;
- for (i=0; i<10; i++) {
- dlsch->harq_ids[0][i] = Mdlharq;
- dlsch->harq_ids[1][i] = Mdlharq;
- }
- for (i=0; iharq_processes[i]) {
- // dlsch->harq_processes[i]->Ndi = 0;
- //dlsch->harq_processes[i]->status = 0;
- dlsch->harq_processes[i]->round = 0;
-
- for (j=0; j<96; j++)
- for (r=0; rharq_processes[i]->d[r])
- dlsch->harq_processes[i]->d[r][j] = NR_NULL;
-
- }
- }
+ for (i=0; i<10; i++) {
+ dlsch->harq_ids[0][i] = Mdlharq;
+ dlsch->harq_ids[1][i] = Mdlharq;
+ }
+ for (i=0; id[r])
+ harq->d[r][j] = NR_NULL;
}
}
@@ -322,13 +244,12 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
unsigned int G;
unsigned int crc=1;
- uint8_t harq_pid = dlsch->harq_ids[frame%2][slot];
- AssertFatal(harq_pid<8 && harq_pid>=0,"illegal harq_pid %d\b",harq_pid);
- nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15;
+ NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
+ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
uint16_t nb_rb = rel15->rbSize;
uint8_t nb_symb_sch = rel15->NrOfSymbols;
uint32_t A, Kb, F=0;
- uint32_t *Zc = &dlsch->harq_processes[harq_pid]->Z;
+ uint32_t *Zc = &dlsch->harq_process.Z;
uint8_t mod_order = rel15->qamModOrder[0];
uint16_t Kr=0,r;
uint32_t r_offset=0;
@@ -347,8 +268,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
float Coderate = 0.0;
uint8_t Nl = 4;
- dlsch->harq_processes[harq_pid]->round = nr_rv_round_map[rel15->rvIndex[0]];
-
+
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
A = rel15->TBSize[0]<<3;
@@ -367,174 +287,157 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
}
if (stats) {
- stats->round_trials[dlsch->harq_processes[harq_pid]->round]++;
stats->rnti = dlsch->rnti;
- if (dlsch->harq_processes[harq_pid]->round == 0){
- stats->total_bytes_tx += rel15->TBSize[0];
- stats->current_RI = rel15->nrOfLayers;
- stats->current_Qm = rel15->qamModOrder[0];
- }
+ stats->total_bytes_tx += rel15->TBSize[0];
+ stats->current_RI = rel15->nrOfLayers;
+ stats->current_Qm = rel15->qamModOrder[0];
}
G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers);
LOG_D(PHY,"dlsch coding A %d G %d mod_order %d\n", A,G, mod_order);
- // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet
- if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet
-#ifdef DEBUG_DLSCH_CODING
- LOG_D(PHY,"encoding thinks this is a new packet \n");
-#endif
- /*
- int i;
- LOG_D(PHY,"dlsch (tx): \n");
- for (i=0;i<(A>>3);i++)
- LOG_D(PHY,"%02x\n",a[i]);
- LOG_D(PHY,"\n");
- */
+ if (A > 3824) {
+ // Add 24-bit crc (polynomial A) to payload
+ crc = crc24a(a,A)>>8;
+ a[A>>3] = ((uint8_t*)&crc)[2];
+ a[1+(A>>3)] = ((uint8_t*)&crc)[1];
+ a[2+(A>>3)] = ((uint8_t*)&crc)[0];
+ //printf("CRC %x (A %d)\n",crc,A);
+ //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
+
+ harq->B = A+24;
+ // harq->b = a;
- if (A > 3824) {
- // Add 24-bit crc (polynomial A) to payload
- crc = crc24a(a,A)>>8;
- a[A>>3] = ((uint8_t*)&crc)[2];
- a[1+(A>>3)] = ((uint8_t*)&crc)[1];
- a[2+(A>>3)] = ((uint8_t*)&crc)[0];
- //printf("CRC %x (A %d)\n",crc,A);
- //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
-
- dlsch->harq_processes[harq_pid]->B = A+24;
- // dlsch->harq_processes[harq_pid]->b = a;
-
- AssertFatal((A/8)+4 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,MAX_NR_DLSCH_PAYLOAD_BYTES);
-
- memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); // why is this +4 if the CRC is only 3 bytes?
- }
- else {
- // Add 16-bit crc (polynomial A) to payload
- crc = crc16(a,A)>>16;
- a[A>>3] = ((uint8_t*)&crc)[1];
- a[1+(A>>3)] = ((uint8_t*)&crc)[0];
- //printf("CRC %x (A %d)\n",crc,A);
- //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
-
- dlsch->harq_processes[harq_pid]->B = A+16;
- // dlsch->harq_processes[harq_pid]->b = a;
-
- AssertFatal((A/8)+3 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,MAX_NR_DLSCH_PAYLOAD_BYTES);
-
- memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+3); // using 3 bytes to mimic the case of 24 bit crc
- }
- if (R<1000)
- Coderate = (float) R /(float) 1024;
- else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools
- Coderate = (float) R /(float) 2048;
-
- if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25)
- dlsch->harq_processes[harq_pid]->BG = 2;
- else
- dlsch->harq_processes[harq_pid]->BG = 1;
-
- start_meas(dlsch_segmentation_stats);
- Kb = nr_segmentation(dlsch->harq_processes[harq_pid]->b,
- dlsch->harq_processes[harq_pid]->c,
- dlsch->harq_processes[harq_pid]->B,
- &dlsch->harq_processes[harq_pid]->C,
- &dlsch->harq_processes[harq_pid]->K,
- Zc,
- &dlsch->harq_processes[harq_pid]->F,
- dlsch->harq_processes[harq_pid]->BG);
- stop_meas(dlsch_segmentation_stats);
- F = dlsch->harq_processes[harq_pid]->F;
-
- Kr = dlsch->harq_processes[harq_pid]->K;
-#ifdef DEBUG_DLSCH_CODING
- uint16_t Kr_bytes;
- Kr_bytes = Kr>>3;
-#endif
-
- //printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,dlsch->harq_processes[harq_pid]->K,Kr,BG,dlsch->harq_processes[harq_pid]->C);
-
- for (r=0; rharq_processes[harq_pid]->C; r++) {
- //d_tmp[r] = &dlsch->harq_processes[harq_pid]->d[r][0];
- //channel_input[r] = &dlsch->harq_processes[harq_pid]->d[r][0];
-#ifdef DEBUG_DLSCH_CODING
- LOG_D(PHY,"Encoder: B %d F %d \n",dlsch->harq_processes[harq_pid]->B, dlsch->harq_processes[harq_pid]->F);
- LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,dlsch->harq_processes[harq_pid]->C);
- LOG_D(PHY,"input %d %d %d %d %d \n", dlsch->harq_processes[harq_pid]->c[r][0], dlsch->harq_processes[harq_pid]->c[r][1], dlsch->harq_processes[harq_pid]->c[r][2],dlsch->harq_processes[harq_pid]->c[r][3], dlsch->harq_processes[harq_pid]->c[r][4]);
- for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){
- LOG_D(PHY,"%d ", dlsch->harq_processes[harq_pid]->c[r][cnt]);
- }
- LOG_D(PHY,"\n");
-
-#endif
- //ldpc_encoder_orig((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],dlsch->harq_processes[harq_pid]->d[r],*Zc,Kb,Kr,BG,0);
- //ldpc_encoder_optim((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],(unsigned char*)&dlsch->harq_processes[harq_pid]->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL);
- }
- encoder_implemparams_t impp;
- impp.n_segments=dlsch->harq_processes[harq_pid]->C;
- impp.tprep = tprep;
- impp.tinput = tinput;
- impp.tparity = tparity;
- impp.toutput = toutput;
-
- for(int j=0;j<(dlsch->harq_processes[harq_pid]->C/8+1);j++) {
- impp.macro_num=j;
- nrLDPC_encoder(dlsch->harq_processes[harq_pid]->c,dlsch->harq_processes[harq_pid]->d,*Zc,Kb,Kr,dlsch->harq_processes[harq_pid]->BG,&impp);
- }
-
-
-#ifdef DEBUG_DLSCH_CODING
- write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4);
- write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[0][0],(3*8*Kr_bytes)+12,1,4);
-#endif
+ AssertFatal((A / 8) + 4 <= MAX_NR_DLSCH_PAYLOAD_BYTES,
+ "A %d is too big (A/8+4 = %d > %d)\n",
+ A,
+ (A / 8) + 4,
+ MAX_NR_DLSCH_PAYLOAD_BYTES);
+ memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
}
+ else {
+ // Add 16-bit crc (polynomial A) to payload
+ crc = crc16(a,A)>>16;
+ a[A>>3] = ((uint8_t*)&crc)[1];
+ a[1+(A>>3)] = ((uint8_t*)&crc)[0];
+ //printf("CRC %x (A %d)\n",crc,A);
+ //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
+
+ harq->B = A+16;
+ // harq->b = a;
- F = dlsch->harq_processes[harq_pid]->F;
+ AssertFatal((A / 8) + 3 <= MAX_NR_DLSCH_PAYLOAD_BYTES,
+ "A %d is too big (A/8+3 = %d > %d)\n",
+ A,
+ (A / 8) + 3,
+ MAX_NR_DLSCH_PAYLOAD_BYTES);
- Kr = dlsch->harq_processes[harq_pid]->K;
- for (r=0; rharq_processes[harq_pid]->C; r++) {
+ memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
+ }
+ if (R<1000)
+ Coderate = (float) R /(float) 1024;
+ else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools
+ Coderate = (float) R /(float) 2048;
+
+ if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25)
+ harq->BG = 2;
+ else
+ harq->BG = 1;
+
+ start_meas(dlsch_segmentation_stats);
+ Kb = nr_segmentation(harq->b, harq->c, harq->B, &harq->C, &harq->K, Zc, &harq->F, harq->BG);
+ stop_meas(dlsch_segmentation_stats);
+ F = harq->F;
+
+ Kr = harq->K;
+#ifdef DEBUG_DLSCH_CODING
+ uint16_t Kr_bytes;
+ Kr_bytes = Kr>>3;
+#endif
+ //printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,harq->K,Kr,BG,harq->C);
+
+ for (r=0; rC; r++) {
+ //d_tmp[r] = &harq->d[r][0];
+ //channel_input[r] = &harq->d[r][0];
+#ifdef DEBUG_DLSCH_CODING
+ LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, harq->F);
+ LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,harq->C);
+ LOG_D(PHY,"input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2],harq->c[r][3], harq->c[r][4]);
+ for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){
+ LOG_D(PHY,"%d ", harq->c[r][cnt]);
+ }
+ LOG_D(PHY,"\n");
+
+#endif
+ //ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0);
+ //ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL);
+ }
+ encoder_implemparams_t impp;
+ impp.n_segments=harq->C;
+ impp.tprep = tprep;
+ impp.tinput = tinput;
+ impp.tparity = tparity;
+ impp.toutput = toutput;
+
+ for(int j=0;j<(harq->C/8+1);j++) {
+ impp.macro_num=j;
+ nrLDPC_encoder(harq->c,harq->d,*Zc,Kb,Kr,harq->BG,&impp);
+ }
+
+
+#ifdef DEBUG_DLSCH_CODING
+ write_output("enc_input0.m","enc_in0",&harq->c[0][0],Kr_bytes,1,4);
+ write_output("enc_output0.m","enc0",&harq->d[0][0],(3*8*Kr_bytes)+12,1,4);
+#endif
+
+ F = harq->F;
+
+ Kr = harq->K;
+ for (r=0; rC; r++) {
+
if (F>0) {
for (int k=(Kr-F-2*(*Zc)); kharq_processes[harq_pid]->d[r][k] = NR_NULL;
+ harq->d[r][k] = NR_NULL;
//if (k<(Kr-F+8))
- //printf("r %d filler bits [%d] = %d \n", r,k, dlsch->harq_processes[harq_pid]->d[r][k]);
+ //printf("r %d filler bits [%d] = %d \n", r,k, harq->d[r][k]);
}
}
-
-
-
+
+
+
#ifdef DEBUG_DLSCH_CODING
- LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
+ LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
#endif
-
- E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15->nrOfLayers, r);
-
+
+ E = nr_get_E(G, harq->C, mod_order, rel15->nrOfLayers, r);
+
//#ifdef DEBUG_DLSCH_CODING
LOG_D(PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n",
r,
- dlsch->harq_processes[harq_pid]->C,
+ harq->C,
G,
E,
F,
Kr-F-2*(*Zc),
mod_order,nb_rb);
-
+
// for tbslbrm calculation according to 5.4.2.1 of 38.212
if (rel15->nrOfLayers < Nl)
Nl = rel15->nrOfLayers;
-
+
Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl);
-
+
start_meas(dlsch_rate_matching_stats);
nr_rate_matching_ldpc(Ilbrm,
Tbslbrm,
- dlsch->harq_processes[harq_pid]->BG,
+ harq->BG,
*Zc,
- dlsch->harq_processes[harq_pid]->d[r],
- dlsch->harq_processes[harq_pid]->e+r_offset,
- dlsch->harq_processes[harq_pid]->C,
+ harq->d[r],
+ harq->e+r_offset,
+ harq->C,
F,
Kr-F-2*(*Zc),
rel15->rvIndex[0],
@@ -542,22 +445,22 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
stop_meas(dlsch_rate_matching_stats);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
- printf("output ratematching e[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset);
+ printf("output ratematching e[%d]= %d r_offset %u\n", i,harq->e[i+r_offset], r_offset);
#endif
start_meas(dlsch_interleaving_stats);
nr_interleaving_ldpc(E,
mod_order,
- dlsch->harq_processes[harq_pid]->e+r_offset,
- dlsch->harq_processes[harq_pid]->f+r_offset);
+ harq->e+r_offset,
+ harq->f+r_offset);
stop_meas(dlsch_interleaving_stats);
#ifdef DEBUG_DLSCH_CODING
for (int i =0; i<16; i++)
- printf("output interleaving f[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset);
+ printf("output interleaving f[%d]= %d r_offset %u\n", i,harq->f[i+r_offset], r_offset);
- if (r==dlsch->harq_processes[harq_pid]->C-1)
- write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,G,1,4);
+ if (r==harq->C-1)
+ write_output("enc_output.m","enc",harq->f,G,1,4);
#endif
r_offset += E;
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
index 5ce2c45a7d..05d6c4c112 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
@@ -289,12 +289,12 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB,
AssertFatal( (dlsch_id>=0) && (dlsch_idrnti,dlsch_id);
NR_gNB_DLSCH_t *dlsch = gNB->dlsch[dlsch_id][0];
- NR_DL_gNB_HARQ_t **harq = dlsch->harq_processes;
+ NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
/// DLSCH struct
- memcpy((void*)&harq[dlsch->harq_ids[frame%2][slot]]->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
+ memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
gNB->num_pdsch_rnti[slot]++;
AssertFatal(sdu!=NULL,"sdu is null\n");
- harq[dlsch->harq_ids[frame%2][slot]]->pdu = sdu;
+ harq->pdu = sdu;
}
diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
index a1a9d4a200..40149757ac 100644
--- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c
+++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
@@ -394,7 +394,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
// first bit of bitmap for sr presence and second bit for acknack presence
uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq>0)<<1);
uci_pdu->pucch_format = 0; // format 0
- uci_pdu->rnti=pucch_pdu->rnti;
+ uci_pdu->rnti = pucch_pdu->rnti;
uci_pdu->ul_cqi = cqi;
uci_pdu->timing_advance = 0xffff; // currently not valid
uci_pdu->rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(signal_energy_nodc(&rxdataF[0][pucch_pdu->start_symbol_index*frame_parms->ofdm_symbol_size+re_offset],12)));
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index 6bdd5c1266..429bd9a836 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -203,7 +203,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint
return(dlsch);
}
- LOG_I(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag);
+ LOG_D(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag);
free_nr_ue_dlsch(&dlsch,N_RB_DL);
return(NULL);
@@ -617,13 +617,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break;
- LOG_I(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
+ LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
err_flag = 1;
}
}
if (err_flag == 1) {
- LOG_I(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n",
+ LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n",
phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round);
harq_process->harq_ack.ack = 0;
@@ -639,7 +639,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
if(is_crnti)
{
- LOG_I(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
+ LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS);
}
@@ -813,6 +813,9 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
nb_rb = harq_process->nb_rb;
harq_process->trials[harq_process->round]++;
+ // HARQ stats
+ phy_vars_ue->dl_stats[harq_process->round]++;
+
uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs
harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*length_dmrs, nb_rb_oh, 0, harq_process->Nl);
@@ -826,7 +829,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
G = harq_process->G;
- LOG_I(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
+ LOG_D(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
proc->decoder_main_available = 1;
proc->decoder_thread_available = 0;
@@ -905,7 +908,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
return((1+dlsch->max_ldpc_iterations));
}
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
- LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
+ LOG_D(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
notifiedFIFO_elt_t *res_dl;
@@ -1079,7 +1082,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
#if UE_TIMING_TRACE
start_meas(dlsch_turbo_decoding_stats);
#endif
- LOG_I(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
+ LOG_D(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
/*for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){
inv_d[cnt] = (1)*harq_process->d[r][cnt];
@@ -1119,7 +1122,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
ret = 2;
}
else {
- LOG_I(PHY,"CRC NOK\n");
+ LOG_D(PHY,"CRC NOK\n");
ret = 1+dlsch->max_ldpc_iterations;
}
@@ -1160,7 +1163,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break;
- LOG_I(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
+ LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1);
err_flag = 1;
}
//} //loop r
@@ -1181,7 +1184,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
}
if(is_crnti)
{
- LOG_I(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
+ LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mlimit,harq_process->TBS);
}
@@ -1332,7 +1335,7 @@ void nr_dlsch_decoding_process(void *arg)
p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[r];
nb_symb_sch = harq_process->nb_symbols;
- LOG_I(PHY,"dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_slot_rx, proc->num_seg, r, harq_process->nb_symbols);
+ LOG_D(PHY,"dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_slot_rx, proc->num_seg, r, harq_process->nb_symbols);
nb_rb = harq_process->nb_rb;
@@ -1351,7 +1354,7 @@ void nr_dlsch_decoding_process(void *arg)
harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl);
G = harq_process->G;
- LOG_I(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
+ LOG_D(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb);
if ((harq_process->R)<1024)
Coderate = (float) (harq_process->R) /(float) 1024;
@@ -1571,12 +1574,12 @@ void nr_dlsch_decoding_process(void *arg)
ret = 2;
}
else {
- LOG_I(PHY,"Segment %u CRC NOK\n",r);
+ LOG_D(PHY,"Segment %u CRC NOK\n",r);
ret = 1+dlsch->max_ldpc_iterations;
}
if (no_iteration_ldpc > 10)
- LOG_I(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc);
+ LOG_D(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc);
for (int m=0; m < Kr>>3; m ++)
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index 5876158476..5a1947eb00 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -94,8 +94,6 @@ typedef struct {
uint32_t frame;
/// Subframe where current HARQ round was sent
uint32_t subframe;
- /// Index of current HARQ round for this DLSCH
- uint8_t round;
/// MIMO mode for this DLSCH
MIMO_mode_t mimo_mode;
/// Concatenated sequences
@@ -138,8 +136,8 @@ typedef struct {
} NR_gNB_SCH_STATS_t;
typedef struct {
- /// Pointers to 16 HARQ processes for the DLSCH
- NR_DL_gNB_HARQ_t *harq_processes[NR_MAX_NB_HARQ_PROCESSES];
+ /// Pointers to variables related to DLSCH harq process
+ NR_DL_gNB_HARQ_t harq_process;
/// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
int32_t *txdataF[NR_MAX_NB_LAYERS];
/// Modulated symbols buffer
@@ -839,6 +837,7 @@ typedef struct PHY_VARS_gNB_s {
notifiedFIFO_t *respDecode;
tpool_t *threadPool;
int nbDecode;
+ uint8_t pusch_proc_threads;
} PHY_VARS_gNB;
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index e719e10e88..89fe8afdb4 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -213,10 +213,10 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot);
nr_generate_pdsch(gNB,frame, slot);
- if ((frame&127) == 0) dump_pdsch_stats(gNB);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
}
+ if ((frame&127) == 0) dump_pdsch_stats(gNB);
//apply the OFDM symbol rotation here
apply_nr_rotation(fp,(int16_t*) &gNB->common_vars.txdataF[0][txdataF_offset],slot,0,fp->Ncp==EXTENDED?12:14,fp->ofdm_symbol_size);
diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c
index b27d2c09ce..edb070f873 100644
--- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c
+++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c
@@ -804,6 +804,7 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t
number_harq_feedback++;
ack_data[code_word][dai_current - 1] = harq_status->ack;
dai[code_word][dai_current - 1] = dai_current;
+ harq_status->slot_for_feedback_ack = NR_MAX_SLOTS_PER_FRAME;
harq_status->send_harq_status = 0;
}
if (do_reset == TRUE) {
diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c
index c60bc8dd9f..061866b12c 100644
--- a/openair1/SIMULATION/NR_PHY/dlschsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlschsim.c
@@ -427,7 +427,7 @@ int main(int argc, char **argv)
UE->dlsch_ra[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0);
unsigned char harq_pid = 0; //dlsch->harq_ids[subframe];
NR_gNB_DLSCH_t *dlsch = gNB->dlsch[0][0];
- nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15;
+ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
//time_stats_t *rm_stats, *te_stats, *i_stats;
uint8_t is_crnti = 0, llr8_flag = 0;
unsigned int TBS = 8424;
@@ -519,7 +519,7 @@ int main(int argc, char **argv)
//if (i<16)
// printf("encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]);
- if (dlsch->harq_processes[0]->f[i] == 0)
+ if (dlsch->harq_process.f[i] == 0)
modulated_input[i] = 1.0; ///sqrt(2); //QPSK
else
modulated_input[i] = -1.0; ///sqrt(2);
@@ -547,7 +547,7 @@ int main(int argc, char **argv)
else
channel_output_uncoded[i] = 0;
- if (channel_output_uncoded[i] != dlsch->harq_processes[harq_pid]->f[i])
+ if (channel_output_uncoded[i] != dlsch->harq_process.f[i])
errors_bit_uncoded = errors_bit_uncoded + 1;
}
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index c6985f9f7a..ca2573e3bc 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -186,8 +186,7 @@ void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dm
int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1;
void nr_dlsim_preprocessor(module_id_t module_id,
frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd) {
+ sub_frame_t slot) {
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
AssertFatal(UE_info->num_UEs == 1, "can have only a single UE\n");
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[0];
@@ -203,15 +202,25 @@ void nr_dlsim_preprocessor(module_id_t module_id,
sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
sched_ctrl->cce_index = 0;
- /* set "any" value for PUCCH (simulator evaluates PDSCH only) */
- sched_ctrl->pucch_sched_idx = 0;
- sched_ctrl->pucch_occ_idx = 0;
-
sched_ctrl->rbStart = g_rbStart;
sched_ctrl->rbSize = g_rbSize;
sched_ctrl->mcs = g_mcsIndex;
sched_ctrl->time_domain_allocation = 2;
sched_ctrl->mcsTableIdx = g_mcsTableIdx;
+ /* the simulator assumes the HARQ PID is equal to the slot number */
+ sched_ctrl->dl_harq_pid = slot;
+ /* The scheduler uses lists to track whether a HARQ process is
+ * free/busy/awaiting retransmission, and updates the HARQ process states.
+ * However, in the simulation, we never get ack or nack for any HARQ process,
+ * thus the list and HARQ states don't match what the scheduler expects.
+ * Therefore, below lines just "repair" everything so that the scheduler
+ * won't remark that there is no HARQ feedback */
+ sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process
+ if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ...
+ add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available
+ else
+ add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot); // ... make PID retransmission
+ sched_ctrl->harq_processes[slot].is_waiting = false;
AssertFatal(sched_ctrl->rbStart >= 0, "invalid rbStart %d\n", sched_ctrl->rbStart);
AssertFatal(sched_ctrl->rbSize > 0, "invalid rbSize %d\n", sched_ctrl->rbSize);
AssertFatal(sched_ctrl->mcs >= 0, "invalid sched_ctrl->mcs %d\n", sched_ctrl->mcs);
@@ -671,6 +680,9 @@ int main(int argc, char **argv)
rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
phy_init_nr_gNB(gNB,0,0);
N_RB_DL = gNB->frame_parms.N_RB_DL;
+ NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
+ UE_info->num_UEs=1;
+
// stub to configure frame_parms
// nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
// call MAC to configure common parameters
@@ -836,10 +848,10 @@ int main(int argc, char **argv)
scheduled_response.thread_id = UE_proc.thread_id;
nr_ue_phy_config_request(&UE_mac->phy_config);
- NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
//NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels;
snrRun = 0;
+
for (SNR = snr0; SNR < snr1; SNR += .2) {
varArray_t *table_tx=initVarArray(1000,sizeof(double));
@@ -885,7 +897,7 @@ int main(int argc, char **argv)
NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid];
NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0];
- nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_processes[slot]->pdsch_pdu.pdsch_pdu_rel15;
+ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
UE_harq_process->harq_ack.ack = 0;
round = 0;
@@ -901,15 +913,11 @@ int main(int argc, char **argv)
UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round;
- gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round;
for (int i=0; iUE_info.num_pdcch_cand[0][i] = 0;
if (css_flag == 0) {
- const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160};
- const NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
- const int num_slots_per_tdd = slots_per_frame[*scc->ssbSubcarrierSpacing] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity);
- nr_schedule_ue_spec(0, frame, slot, num_slots_per_tdd);
+ nr_schedule_ue_spec(0, frame, slot);
} else {
nr_schedule_css_dlsch_phytest(0,frame,slot);
}
@@ -1053,8 +1061,8 @@ int main(int argc, char **argv)
for (i = 0; i < available_bits; i++) {
- if(((gNB_dlsch->harq_processes[harq_pid]->f[i] == 0) && (UE_llr[i] <= 0)) ||
- ((gNB_dlsch->harq_processes[harq_pid]->f[i] == 1) && (UE_llr[i] >= 0)))
+ if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) ||
+ ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0)))
{
if(errors_scrambling == 0) {
LOG_D(PHY,"\n");
@@ -1067,7 +1075,7 @@ int main(int argc, char **argv)
for (i = 0; i < TBS; i++) {
estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7);
- test_input_bit[i] = (gNB_dlsch->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
+ test_input_bit[i] = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
if (estimated_output_bit[i] != test_input_bit[i]) {
if(errors_bit == 0)
@@ -1107,9 +1115,9 @@ int main(int argc, char **argv)
if (print_perf==1) {
printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n",
1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex,
- gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
- gNB->dlsch[0][0]->harq_processes[0]->K,
- gNB->dlsch[0][0]->harq_processes[0]->K/((gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
+ gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3,
+ gNB->dlsch[0][0]->harq_process.K,
+ gNB->dlsch[0][0]->harq_process.K/((gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10));
printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time");
diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h
index a5a808c281..67be560778 100644
--- a/openair2/GNB_APP/L1_nr_paramdef.h
+++ b/openair2/GNB_APP/L1_nr_paramdef.h
@@ -46,6 +46,7 @@
#define CONFIG_STRING_L1_LOCAL_N_PORTD "local_n_portd"
#define CONFIG_STRING_L1_REMOTE_N_PORTD "remote_n_portd"
#define CONFIG_STRING_L1_TRANSPORT_N_PREFERENCE "tr_n_preference"
+#define CONFIG_STRING_L1_PUSCH_PROC_THREADS "pusch_proc_threads"
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* L1 configuration parameters */
@@ -61,6 +62,7 @@
{CONFIG_STRING_L1_REMOTE_N_PORTC, NULL, 0, uptr:NULL, defintval:50030, TYPE_UINT, 0}, \
{CONFIG_STRING_L1_LOCAL_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \
{CONFIG_STRING_L1_REMOTE_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \
+{CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:1, TYPE_UINT, 0} \
}
#define L1_CC_IDX 0
#define L1_TRANSPORT_N_PREFERENCE_IDX 1
@@ -71,6 +73,7 @@
#define L1_REMOTE_N_PORTC_IDX 6
#define L1_LOCAL_N_PORTD_IDX 7
#define L1_REMOTE_N_PORTD_IDX 8
+#define L1_PUSCH_PROC_THREADS 9
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index d830e51f4d..0c056d27b6 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -51,7 +51,8 @@
#include "nfapi_vnf.h"
#include "nfapi_pnf.h"
-#include "L1_paramdef.h"
+//#include "L1_paramdef.h"
+#include "L1_nr_paramdef.h"
#include "MACRLC_paramdef.h"
#include "common/config/config_userapi.h"
//#include "RRC_config_tools.h"
@@ -399,6 +400,8 @@ void RCconfig_NR_L1(void) {
RC.gNB[j]->Mod_id = j;
}
+ RC.gNB[j]->pusch_proc_threads = *(L1_ParamList.paramarray[j][L1_PUSCH_PROC_THREADS].uptr);
+
if(strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
//sf_ahead = 2; // Need 4 subframe gap between RX and TX
}else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index 981f2ba193..f1fe0c97c9 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -82,7 +82,6 @@ typedef enum {
/* global parameters, not under a specific section */
#define GNB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity"
#define GNB_CONFIG_STRING_ACTIVE_GNBS "Active_gNBs"
-#define GNB_CONFIG_PUSCH_THREADS "Num_Threads_PUSCH"
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* global configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
@@ -92,10 +91,6 @@ typedef enum {
{GNB_CONFIG_STRING_ACTIVE_GNBS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRINGLIST, 0} \
}
-#define NUM_THREADS_DESC { \
-{GNB_CONFIG_PUSCH_THREADS, NULL, 0, uptr:&num_threads_pusch, defuintval:1, TYPE_UINT, 0} \
-}
-
#define GNB_ASN1_VERBOSITY_IDX 0
#define GNB_ACTIVE_GNBS_IDX 1
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
index 1c8c510ec6..381dce11b2 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
@@ -119,22 +119,22 @@ typedef NR_BSR_SHORT NR_BSR_SHORT_TRUNCATED;
// Long BSR for all logical channel group ID
typedef struct {
- uint8_t Buffer_size7: 8;
- uint8_t Buffer_size6: 8;
- uint8_t Buffer_size5: 8;
- uint8_t Buffer_size4: 8;
- uint8_t Buffer_size3: 8;
- uint8_t Buffer_size2: 8;
- uint8_t Buffer_size1: 8;
- uint8_t Buffer_size0: 8;
- uint8_t LcgID0: 1;
- uint8_t LcgID1: 1;
- uint8_t LcgID2: 1;
- uint8_t LcgID3: 1;
- uint8_t LcgID4: 1;
- uint8_t LcgID5: 1;
- uint8_t LcgID6: 1;
- uint8_t LcgID7: 1;
+ uint8_t LcgID0: 1; // octet 1 [0]
+ uint8_t LcgID1: 1; // octet 1 [1]
+ uint8_t LcgID2: 1; // octet 1 [2]
+ uint8_t LcgID3: 1; // octet 1 [3]
+ uint8_t LcgID4: 1; // octet 1 [4]
+ uint8_t LcgID5: 1; // octet 1 [5]
+ uint8_t LcgID6: 1; // octet 1 [6]
+ uint8_t LcgID7: 1; // octet 1 [7]
+ uint8_t Buffer_size0: 8; // octet 2 [7:0]
+ uint8_t Buffer_size1: 8; // octet 3 [7:0]
+ uint8_t Buffer_size2: 8; // octet 4 [7:0]
+ uint8_t Buffer_size3: 8; // octet 5 [7:0]
+ uint8_t Buffer_size4: 8; // octet 6 [7:0]
+ uint8_t Buffer_size5: 8; // octet 7 [7:0]
+ uint8_t Buffer_size6: 8; // octet 8 [7:0]
+ uint8_t Buffer_size7: 8; // octet 9 [7:0]
} __attribute__ ((__packed__)) NR_BSR_LONG;
typedef NR_BSR_LONG NR_BSR_LONG_TRUNCATED;
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index c8bba7907a..8dc261df1d 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -2382,9 +2382,9 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) {
// Set the transform precoding status according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16:
// - "UE procedure for applying transform precoding on PUSCH"
-uint8_t get_transformPrecoding(NR_ServingCellConfigCommon_t *scc,
- NR_PUSCH_Config_t *pusch_config,
- NR_BWP_Uplink_t *ubwp,
+uint8_t get_transformPrecoding(const NR_ServingCellConfigCommon_t *scc,
+ const NR_PUSCH_Config_t *pusch_config,
+ const NR_BWP_Uplink_t *ubwp,
uint8_t *dci_format,
int rnti_type,
uint8_t configuredGrant){
@@ -2416,8 +2416,8 @@ uint8_t get_transformPrecoding(NR_ServingCellConfigCommon_t *scc,
return -1;
}
-uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc,
- NR_CellGroupConfig_t *secondaryCellGroup,
+uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc,
+ const NR_CellGroupConfig_t *secondaryCellGroup,
dci_pdu_rel15_t *dci_pdu,
nr_dci_format_t format,
nr_rnti_type_t rnti_type,
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index 7534035cdc..58ecd54733 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -53,8 +53,8 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP);
-uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc,
- NR_CellGroupConfig_t *secondaryCellGroup,
+uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc,
+ const NR_CellGroupConfig_t *secondaryCellGroup,
dci_pdu_rel15_t *dci_pdu,
nr_dci_format_t format,
nr_rnti_type_t rnti_type,
@@ -150,9 +150,9 @@ uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Posi
@param rnti_type rnti type
@param configuredGrant indicates whether a configured grant was received or not
@returns transformPrecoding value */
-uint8_t get_transformPrecoding(NR_ServingCellConfigCommon_t *scc,
- NR_PUSCH_Config_t *pusch_config,
- NR_BWP_Uplink_t *ubwp,
+uint8_t get_transformPrecoding(const NR_ServingCellConfigCommon_t *scc,
+ const NR_PUSCH_Config_t *pusch_config,
+ const NR_BWP_Uplink_t *ubwp,
uint8_t *dci_format,
int rnti_type,
uint8_t configuredGrant);
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index 3bd9f021c8..dd0aa15c52 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -350,6 +350,8 @@ typedef struct {
RA_config_t ra;
/// SSB index from MIB decoding
uint8_t mib_ssb;
+ /// Last NDI of UL HARQ processes
+ uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES];
//// FAPI-like interface message
fapi_nr_ul_config_request_t *ul_config_request;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 9759069340..8520715071 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -2046,7 +2046,7 @@ uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload,
if (crnti) {
// MAC CE fixed subheader
mac_pdu_ptr->R = 0;
- mac_pdu_ptr->LCID = CRNTI;
+ mac_pdu_ptr->LCID = UL_SCH_LCID_C_RNTI;
mac_pdu_ptr++;
// C-RNTI MAC CE (2 octets)
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index f4330de63c..0b2b7f9e7d 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -895,7 +895,8 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size;
- if (IS_SOFTMODEM_NOS1){
+ // Push data from MAC to PHY only when NDI toggles
+ if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){
// Getting IP traffic to be transmitted
data_existing = nr_ue_get_sdu(mod_id,
cc_id,
@@ -907,6 +908,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
&access_mode);
}
+ mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator;
//Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
if (!IS_SOFTMODEM_NOS1 || !data_existing) {
//Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index 6171c717b1..b676b1ec53 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -362,10 +362,18 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
}
RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL =
- calloc(n * 275, sizeof(uint16_t));
+ calloc(n * MAX_BWP_SIZE, sizeof(uint16_t));
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,
@@ -405,22 +413,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
if (add_ue == 1 && get_softmodem_params()->phy_test) {
- const int UE_id = add_new_nr_ue(Mod_idP,rnti);
- UE_info->secondaryCellGroup[UE_id] = secondaryCellGroup;
- compute_csi_bitlen (secondaryCellGroup, UE_info, UE_id);
- struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList =
- secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
- AssertFatal(bwpList->list.count == 1,
- "downlinkBWP_ToAddModList has %d BWP!\n",
- bwpList->list.count);
- const int bwp_id = 1;
- UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
- struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList =
- secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList;
- AssertFatal(ubwpList->list.count == 1,
- "uplinkBWP_ToAddModList has %d BWP!\n",
- ubwpList->list.count);
- UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1];
+ const int UE_id = add_new_nr_ue(Mod_idP, rnti, secondaryCellGroup);
LOG_I(PHY,"Added new UE_id %d/%x with initial secondaryCellGroup\n",UE_id,rnti);
} else if (add_ue == 1 && !get_softmodem_params()->phy_test) {
/* TODO: should check for free RA process */
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index c3a8d572ba..06be000b71 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -59,24 +59,31 @@ void clear_mac_stats(gNB_MAC_INST *gNB) {
memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t));
}
-void dump_mac_stats(gNB_MAC_INST *gNB) {
-
+void dump_mac_stats(gNB_MAC_INST *gNB)
+{
NR_UE_info_t *UE_info = &gNB->UE_info;
- NR_mac_stats_t *stats;
- int lc_id;
-
- for (int UE_id=0;UE_idactive[UE_id]) {
- LOG_I(MAC, "UE %x\n", UE_info->rnti[UE_id]);
- stats = &UE_info->mac_stats[UE_id];
- LOG_I(MAC,"dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",stats->dlsch_rounds[0],stats->dlsch_rounds[1],stats->dlsch_rounds[2],stats->dlsch_rounds[3],stats->dlsch_errors);
- LOG_I(MAC,"dlsch_total_bytes %d\n",stats->dlsch_total_bytes);
- LOG_I(MAC,"ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",stats->ulsch_rounds[0],stats->ulsch_rounds[1],stats->ulsch_rounds[2],stats->ulsch_rounds[3],stats->ulsch_errors);
- LOG_I(MAC,"ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",stats->ulsch_total_bytes_scheduled,stats->ulsch_total_bytes_rx);
- for (lc_id=0;lc_id<63;lc_id++) {
- if (stats->lc_bytes_tx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes TX\n",lc_id,stats->lc_bytes_tx[lc_id]);
- if (stats->lc_bytes_rx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes RX\n",lc_id,stats->lc_bytes_rx[lc_id]);
- }
+ int num = 1;
+ for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
+ LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs);
+ const NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
+ LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",
+ UE_id,
+ stats->dlsch_rounds[0], stats->dlsch_rounds[1],
+ stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors);
+ LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes);
+ LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",
+ UE_id,
+ stats->ulsch_rounds[0], stats->ulsch_rounds[1],
+ stats->ulsch_rounds[2], stats->ulsch_rounds[3], stats->ulsch_errors);
+ LOG_I(MAC,
+ "UE %d: ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",
+ UE_id,
+ stats->ulsch_total_bytes_scheduled, stats->ulsch_total_bytes_rx);
+ for (int lc_id = 0; lc_id < 63; lc_id++) {
+ if (stats->lc_bytes_tx[lc_id] > 0)
+ LOG_I(MAC, "UE %d: LCID %d: %d bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]);
+ if (stats->lc_bytes_rx[lc_id] > 0)
+ LOG_I(MAC, "UE %d: LCID %d: %d bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]);
}
}
}
@@ -89,6 +96,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0];
+ nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***)gNB->pdcch_pdu_idx[CC_idP];
nfapi_nr_ul_tti_request_t *future_ul_tti_req =
&gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots];
nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0];
@@ -103,6 +111,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
DL_req[CC_idP].dl_tti_request_body.nPDUs = 0;
DL_req[CC_idP].dl_tti_request_body.nGroup = 0;
//DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000;
+ memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET);
UL_dci_req[CC_idP].SFN = frameP;
UL_dci_req[CC_idP].Slot = slotP;
@@ -299,11 +308,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
int nb_periods_per_frame;
- const int UE_id = 0;
const int bwp_id = 1;
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
- NR_UE_info_t *UE_info = &gNB->UE_info;
NR_COMMON_channels_t *cc = gNB->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
@@ -366,23 +373,27 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
}
- const uint64_t dlsch_in_slot_bitmap = (1 << 1) | (1 << 3);
- const uint64_t ulsch_in_slot_bitmap = (1 << 8);
+#define BIT(x) (1 << (x))
+ const uint64_t dlsch_in_slot_bitmap = BIT( 1) | BIT( 2) | BIT( 3) | BIT( 4) | BIT( 5) | BIT( 6)
+ | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16);
+ const uint64_t ulsch_in_slot_bitmap = BIT( 8) | BIT(18);
memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0
memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1
- for (int i=0; iUE_info.num_pdcch_cand[UE_id][i] = 0;
+ NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
+ for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id])
+ for (int i=0; inum_pdcch_cand[UE_id][i] = 0;
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
//mbsfn_status[CC_id] = 0;
// clear vrb_maps
- memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * 275);
+ memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * MAX_BWP_SIZE);
// clear last scheduled slot's content (only)!
const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
const int last_slot = (slot + num_slots - 1) % num_slots;
uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL;
- memset(&vrb_map_UL[last_slot * 275], 0, sizeof(uint16_t) * 275);
+ memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE);
clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot);
}
@@ -416,9 +427,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
// This schedule SR
// TODO
- // This schedule CSI measurement reporting
- if (UE_info->active[UE_id])
- nr_csi_meas_reporting(module_idP, UE_id, frame, slot, num_slots_per_tdd, nr_ulmix_slots, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]);
+ // Schedule CSI measurement reporting: check in slot 0 for the whole frame
+ if (slot == 0)
+ nr_csi_meas_reporting(module_idP, frame, slot);
// This schedule RA procedure if not in phy_test mode
// Otherwise already consider 5G already connected
@@ -427,19 +438,16 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
}
// This schedules the DCI for Uplink and subsequently PUSCH
- if (slot < 10) {
+ {
nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap);
}
// This schedules the DCI for Downlink and PDSCH
- if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd)
- && slot < 10) {
- nr_schedule_ue_spec(module_idP, frame, slot, num_slots_per_tdd);
- }
+ if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot))
+ nr_schedule_ue_spec(module_idP, frame, slot);
- if (UE_info->active[UE_id])
- nr_schedule_pucch(module_idP, UE_id, nr_ulmix_slots, frame, slot);
+ nr_schedule_pucch(module_idP, frame, slot);
stop_meas(&RC.nrmac[module_idP]->eNB_scheduler);
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index 7cf68bb3f6..d3faa3d2a1 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -672,7 +672,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
}
uint16_t *vrb_map_UL =
- &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * 275];
+ &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE];
for (int i = 0; i < ra->msg3_nb_rb; ++i) {
AssertFatal(!vrb_map_UL[i + ra->msg3_first_rb],
"RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n",
@@ -793,7 +793,7 @@ void nr_generate_Msg2(module_id_t module_idP,
sub_frame_t slotP)
{
- int dci_formats[2], rnti_types[2], mcsIndex;
+ int mcsIndex;
int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0;
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
@@ -820,27 +820,55 @@ void nr_generate_Msg2(module_id_t module_idP,
if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) {
nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body;
- nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
-
- nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
- memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
- dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
- dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
-
- nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
- memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
- dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
- dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
-
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
- nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
-
// Checking if the DCI allocation is feasible in current subframe
- if (dl_req->nPDUs == NFAPI_NR_MAX_DL_TTI_PDUS) {
+ if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) {
LOG_I(MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, RA_rnti);
return;
}
+ uint8_t nr_of_candidates, aggregation_level;
+ find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
+ NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1];
+ NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */);
+ int CCEIndex = allocate_nr_CCEs(nr_mac,
+ bwp,
+ coreset,
+ aggregation_level,
+ 0, // Y
+ 0, // m
+ nr_of_candidates);
+
+ if (CCEIndex < 0) {
+ LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
+ return;
+ }
+
+ nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
+
+ /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not
+ * exist, create it. This is especially important if we have multiple RAs,
+ * and the DLSCH has to reuse them, so we need to mark them */
+ const int bwpid = bwp->bwp_Id;
+ const int coresetid = coreset->controlResourceSetId;
+ nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid];
+ if (!pdcch_pdu_rel15) {
+ nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
+ memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
+ dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
+ dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu));
+ dl_req->nPDUs += 1;
+ pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
+ nr_configure_pdcch(pdcch_pdu_rel15, ss, coreset, scc, bwp);
+ nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15;
+ }
+
+ nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
+ memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
+ dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
+ dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
+ dl_req->nPDUs+=1;
+ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
+
LOG_I(MAC,"[gNB %d] [RAPROC] CC_id %d Frame %d, slotP %d: Generating RAR DCI, state %d\n", module_idP, CC_id, frameP, slotP, ra->state);
// This code from this point on will not work on initialBWP or CORESET0
@@ -851,7 +879,6 @@ void nr_generate_Msg2(module_id_t module_idP,
ra->crnti);
AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n", ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
- NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1];
NR_BWP_Uplink_t *ubwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1];
LOG_I(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
@@ -864,7 +891,11 @@ void nr_generate_Msg2(module_id_t module_idP,
pdsch_pdu_rel15->pduBitmap = 0;
pdsch_pdu_rel15->rnti = RA_rnti;
- pdsch_pdu_rel15->pduIndex = 0;
+ /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control
+ * message. This is used to associate control information to data and is
+ * reset every slot. */
+ const int pduindex = nr_mac->pdu_index[CC_id]++;
+ pdsch_pdu_rel15->pduIndex = pduindex;
pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
@@ -920,65 +951,61 @@ void nr_generate_Msg2(module_id_t module_idP,
pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0;
pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id;
- dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
- dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
- pdsch_pdu_rel15->rbStart,dci10_bw);
- dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment;
- dci_pdu_rel15[0].vrb_to_prb_mapping.val = 0;
- dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0];
- dci_pdu_rel15[0].tb_scaling = 0;
+ /* Fill PDCCH DL DCI PDU */
+ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
+ pdcch_pdu_rel15->numDlDci++;
+ dci_pdu->RNTI = RA_rnti;
+ /* TODO: remove next line */
+ AssertFatal(ss->searchSpaceType->present != NR_SearchSpace__searchSpaceType_PR_ue_Specific,
+ "shouldn't the RA SS be common?\n");
+ dci_pdu->ScramblingId = *scc->physCellId;
+ dci_pdu->ScramblingRNTI = 0;
+ dci_pdu->AggregationLevel = aggregation_level;
+ dci_pdu->CceIndex = CCEIndex;
+ dci_pdu->beta_PDCCH_1_0 = 0;
+ dci_pdu->powerControlOffsetSS = 1;
- LOG_I(MAC, "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n",
- dci_pdu_rel15[0].frequency_domain_assignment.val,
- pdsch_pdu_rel15->rbStart,
- pdsch_pdu_rel15->rbSize,
- dci10_bw,
- dci_pdu_rel15[0].time_domain_assignment.val,
- dci_pdu_rel15[0].vrb_to_prb_mapping.val,
- dci_pdu_rel15[0].mcs,
- dci_pdu_rel15[0].tb_scaling);
+ dci_pdu_rel15_t dci_payload;
+ dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
+ pdsch_pdu_rel15->rbStart,dci10_bw);
+ dci_payload.time_domain_assignment.val = time_domain_assignment;
+ dci_payload.vrb_to_prb_mapping.val = 0;
+ dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0];
+ dci_payload.tb_scaling = 0;
- uint8_t nr_of_candidates, aggregation_level;
- find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
- NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */);
- int CCEIndex = allocate_nr_CCEs(nr_mac,
- bwp,
- coreset,
- aggregation_level,
- 0, // Y
- 0, // m
- nr_of_candidates);
-
- if (CCEIndex < 0) {
- LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
- return;
- }
- nr_configure_pdcch(nr_mac,
- pdcch_pdu_rel15,
- RA_rnti,
- ss,
- coreset,
- scc,
- bwp,
- aggregation_level,
- CCEIndex);
+ LOG_I(MAC,
+ "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n",
+ dci_payload.frequency_domain_assignment.val,
+ pdsch_pdu_rel15->rbStart,
+ pdsch_pdu_rel15->rbSize,
+ dci10_bw,
+ dci_payload.time_domain_assignment.val,
+ dci_payload.vrb_to_prb_mapping.val,
+ dci_payload.mcs,
+ dci_payload.tb_scaling);
LOG_I(MAC, "Frame %d: Subframe %d : Adding common DL DCI for RA_RNTI %x\n", frameP, slotP, RA_rnti);
- dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
- rnti_types[0] = NR_RNTI_RA;
+ const int dci_format = NR_DL_DCI_FORMAT_1_0;
+ const int rnti_type = NR_RNTI_RA;
- LOG_I(MAC, "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
- pdcch_pdu_rel15->dci_pdu.RNTI[0],
- rnti_types[0],
- dci_formats[0],
- (unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
- pdcch_pdu_rel15->StartSymbolIndex,
- pdcch_pdu_rel15->DurationSymbols);
+ LOG_I(MAC,
+ "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
+ pdcch_pdu_rel15->dci_pdu[0].RNTI,
+ rnti_type,
+ dci_format,
+ (unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
+ pdcch_pdu_rel15->StartSymbolIndex,
+ pdcch_pdu_rel15->DurationSymbols);
- fill_dci_pdu_rel15(scc,ra->secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id);
-
- dl_req->nPDUs+=2;
+ fill_dci_pdu_rel15(scc,
+ ra->secondaryCellGroup,
+ dci_pdu,
+ &dci_payload,
+ dci_format,
+ rnti_type,
+ dci10_bw,
+ ra->bwp_id);
// Program UL processing for Msg3
nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra, nr_mac->tdd_beam_association);
@@ -988,11 +1015,11 @@ void nr_generate_Msg2(module_id_t module_idP,
LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
x_Overhead = 0;
- nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_pdu_rel15[0].tb_scaling);
+ nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_payload.tb_scaling);
// DL TX request
tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0];
- tx_req->PDU_index = nr_mac->pdu_index[CC_id]++;
+ tx_req->PDU_index = pduindex;
tx_req->num_TLV = 1;
tx_req->TLVs[0].length = 8;
nr_mac->TX_req[CC_id].SFN = frameP;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index 65bf1bd775..0dc39bd1af 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -135,7 +135,12 @@ void schedule_nr_mib(module_id_t module_idP,
mib_sdu_length);
if ((frameP & 1023) < 80){
- LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length);
+ LOG_D(MAC,
+ "[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",
+ module_idP,
+ frameP,
+ CC_id,
+ mib_sdu_length);
}
dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
@@ -372,13 +377,19 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
+ dl_req->nPDUs += 1;
+ nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
+ nr_configure_pdcch(pdcch_pdu_rel15,
+ gNB_mac->sched_ctrlCommon->search_space,
+ gNB_mac->sched_ctrlCommon->coreset,
+ scc,
+ bwp);
- nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
+ nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
-
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
+ dl_req->nPDUs += 1;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
@@ -426,48 +437,50 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos);
- dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
- memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t) * MAX_DCI_CORESET);
+ /* Fill PDCCH DL DCI PDU */
+ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci];
+ pdcch_pdu_rel15->numDlDci++;
+ dci_pdu->RNTI = SI_RNTI;
+ dci_pdu->ScramblingId = *scc->physCellId;
+ dci_pdu->ScramblingRNTI = 0;
+ dci_pdu->AggregationLevel = gNB_mac->sched_ctrlCommon->aggregation_level;
+ dci_pdu->CceIndex = gNB_mac->sched_ctrlCommon->cce_index;
+ dci_pdu->beta_PDCCH_1_0 = 0;
+ dci_pdu->powerControlOffsetSS = 1;
- dci_pdu_rel15[0].bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id;
+ /* DCI payload */
+ dci_pdu_rel15_t dci_payload;
+ memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t));
+
+ dci_payload.bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id;
// frequency domain assignment
- dci_pdu_rel15[0].frequency_domain_assignment.val =
- PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
- pdsch_pdu_rel15->rbStart,
- gNB_mac->type0_PDCCH_CSS_config.num_rbs);
+ dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(
+ pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, gNB_mac->type0_PDCCH_CSS_config.num_rbs);
- dci_pdu_rel15[0].time_domain_assignment.val = gNB_mac->sched_ctrlCommon->time_domain_allocation;
- dci_pdu_rel15[0].mcs = gNB_mac->sched_ctrlCommon->mcs;
- dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0];
- dci_pdu_rel15[0].harq_pid = 0;
- dci_pdu_rel15[0].ndi = 0;
- dci_pdu_rel15[0].dai[0].val = 0;
- dci_pdu_rel15[0].tpc = 0; // table 7.2.1-1 in 38.213
- dci_pdu_rel15[0].pucch_resource_indicator = 0;
- dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = 0;
- dci_pdu_rel15[0].antenna_ports.val = 0;
- dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
+ dci_payload.time_domain_assignment.val = gNB_mac->sched_ctrlCommon->time_domain_allocation;
+ dci_payload.mcs = gNB_mac->sched_ctrlCommon->mcs;
+ dci_payload.rv = pdsch_pdu_rel15->rvIndex[0];
+ dci_payload.harq_pid = 0;
+ dci_payload.ndi = 0;
+ dci_payload.dai[0].val = 0;
+ dci_payload.tpc = 0; // table 7.2.1-1 in 38.213
+ dci_payload.pucch_resource_indicator = 0;
+ dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0;
+ dci_payload.antenna_ports.val = 0;
+ dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
- nr_configure_pdcch(gNB_mac,
- pdcch_pdu_rel15,
- SI_RNTI,
- gNB_mac->sched_ctrlCommon->search_space,
- gNB_mac->sched_ctrlCommon->coreset,
- scc,
- bwp,
- gNB_mac->sched_ctrlCommon->aggregation_level,
- gNB_mac->sched_ctrlCommon->cce_index);
+ int dci_format = NR_DL_DCI_FORMAT_1_0;
+ int rnti_type = NR_RNTI_SI;
- int dci_formats[2];
- int rnti_types[2];
-
- dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
- rnti_types[0] = NR_RNTI_SI;
-
- fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id);
-
- dl_req->nPDUs += 2;
+ fill_dci_pdu_rel15(scc,
+ secondaryCellGroup,
+ &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1],
+ &dci_payload,
+ dci_format,
+ rnti_type,
+ pdsch_pdu_rel15->BWPSize,
+ gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id);
LOG_D(MAC,"BWPSize: %i\n", pdcch_pdu_rel15->BWPSize);
LOG_D(MAC,"BWPStart: %i\n", pdcch_pdu_rel15->BWPStart);
@@ -545,4 +558,4 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
gNB_mac->TX_req[CC_id].SFN = frameP;
gNB_mac->TX_req[CC_id].Slot = slotP;
}
-}
\ No newline at end of file
+}
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 4110af07ed..4d491b2843 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -56,27 +56,22 @@
#define WORD 32
//#define SIZE_OF_POINTER sizeof (void *)
-int nr_generate_dlsch_pdu(module_id_t module_idP,
- NR_UE_sched_ctrl_t *ue_sched_ctl,
- unsigned char *sdus_payload,
+// Compute and write all MAC CEs and subheaders, and return number of written
+// bytes
+int nr_write_ce_dlsch_pdu(module_id_t module_idP,
+ const NR_UE_sched_ctrl_t *ue_sched_ctl,
unsigned char *mac_pdu,
- unsigned char num_sdus,
- unsigned short *sdu_lengths,
- unsigned char *sdu_lcids,
unsigned char drx_cmd,
- unsigned char *ue_cont_res_id,
- unsigned short post_padding) {
+ unsigned char *ue_cont_res_id)
+{
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) mac_pdu;
- unsigned char *dlsch_buffer_ptr = sdus_payload;
uint8_t last_size = 0;
int offset = 0, mac_ce_size, i, timing_advance_cmd, tag_id = 0;
// MAC CEs
uint8_t mac_header_control_elements[16], *ce_ptr;
ce_ptr = &mac_header_control_elements[0];
- // 1) Compute MAC CE and related subheaders
-
// DRX command subheader (MAC CE size 0)
if (drx_cmd != 255) {
mac_pdu_ptr->R = 0;
@@ -301,42 +296,6 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
}
}
- // 2) Generation of DLSCH MAC subPDUs including subheaders and MAC SDUs
- for (i = 0; i < num_sdus; i++) {
-
- if (sdu_lengths[i] < 256) {
- ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0;
- ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0;
- ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i];
- ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = (unsigned char) sdu_lengths[i];
- last_size = 2;
- } else {
- ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0;
- ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1;
- ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i];
- ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0xff;
- ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff;
- last_size = 3;
- }
-
- mac_pdu_ptr += last_size;
- // 3) cycle through SDUs, compute each relevant and place dlsch_buffer in
- memcpy((void *) mac_pdu_ptr, (void *) dlsch_buffer_ptr, sdu_lengths[i]);
- dlsch_buffer_ptr += sdu_lengths[i];
- mac_pdu_ptr += sdu_lengths[i];
- LOG_D(MAC, "Generate DLSCH header num sdu %d len header %d len sdu %d -> offset %ld\n", num_sdus, last_size, sdu_lengths[i], (unsigned char *)mac_pdu_ptr - mac_pdu);
- }
-
- // 4) Compute final offset for padding
- if (post_padding > 0) {
- ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0;
- ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = DL_SCH_LCID_PADDING;
- mac_pdu_ptr++;
- LOG_D(MAC, "Generate Padding -> offset %ld\n", (unsigned char *)mac_pdu_ptr - mac_pdu);
- } else {
- // no MAC subPDU with padding
- }
-
// compute final offset
offset = ((unsigned char *) mac_pdu_ptr - mac_pdu);
//printf("Offset %d \n", ((unsigned char *) mac_pdu_ptr - mac_pdu));
@@ -372,123 +331,236 @@ uint8_t getN_PRB_DMRS(NR_BWP_Downlink_t *bwp, int numDmrsCdmGrpsNoData) {
}
}
-void nr_simple_dlsch_preprocessor(module_id_t module_id,
- frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd) {
+void nr_store_dlsch_buffer(module_id_t module_id,
+ frame_t frame,
+ sub_frame_t slot) {
+
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
- AssertFatal(UE_info->num_UEs <= 1,
- "%s() cannot handle more than one UE, but found %d\n",
- __func__,
- UE_info->num_UEs);
- if (UE_info->num_UEs == 0)
- return;
+ for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
- const int UE_id = 0;
- const int CC_id = 0;
-
- NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
-
- /* Retrieve amount of data to send for this UE */
- sched_ctrl->num_total_bytes = 0;
- const int lcid = DL_SCH_LCID_DTCH;
- const rnti_t rnti = UE_info->rnti[UE_id];
- sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
- rnti,
- module_id,
- frame,
- slot,
- ENB_FLAG_YES,
- MBMS_FLAG_NO,
- lcid,
- 0,
- 0);
- sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
- if (sched_ctrl->num_total_bytes == 0
- && !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */
- return;
-
- LOG_D(MAC, "[%s][%d.%d], DTCH%d->DLSCH, RLC status %d bytes TA %d\n",
- __FUNCTION__,
- frame,
- slot,
- lcid,
- sched_ctrl->rlc_status[lcid].bytes_in_buffer,
- sched_ctrl->ta_apply);
-
- /* Find a free CCE */
- const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
- sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
- uint8_t nr_of_candidates;
- find_aggregation_candidates(&sched_ctrl->aggregation_level,
- &nr_of_candidates,
- sched_ctrl->search_space);
- sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /*dedicated*/);
- int cid = sched_ctrl->coreset->controlResourceSetId;
- const uint16_t Y = UE_info->Y[UE_id][cid][slot];
- const int m = UE_info->num_pdcch_cand[UE_id][cid];
- sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
- sched_ctrl->active_bwp,
- sched_ctrl->coreset,
- sched_ctrl->aggregation_level,
- Y,
- m,
- nr_of_candidates);
- if (sched_ctrl->cce_index < 0) {
- LOG_E(MAC, "%s(): could not find CCE for UE %d\n", __func__, UE_id);
- return;
+ sched_ctrl->num_total_bytes = 0;
+ const int lcid = DL_SCH_LCID_DTCH;
+ const uint16_t rnti = UE_info->rnti[UE_id];
+ sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
+ rnti,
+ module_id,
+ frame,
+ slot,
+ ENB_FLAG_YES,
+ MBMS_FLAG_NO,
+ lcid,
+ 0,
+ 0);
+ sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
+ LOG_D(MAC,
+ "[%s][%d.%d], DTCH%d->DLSCH, RLC status %d bytes TA %d\n",
+ __func__,
+ frame,
+ slot,
+ lcid,
+ sched_ctrl->rlc_status[lcid].bytes_in_buffer,
+ sched_ctrl->ta_apply);
}
- UE_info->num_pdcch_cand[UE_id][cid]++;
+}
- /* Find PUCCH occasion */
- nr_acknack_scheduling(module_id,
- UE_id,
- frame,
- slot,
- num_slots_per_tdd,
- &sched_ctrl->pucch_sched_idx,
- &sched_ctrl->pucch_occ_idx);
-
- AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n");
-
- uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
- // for now HARQ PID is fixed and should be the same as in post-processor
- const int current_harq_pid = slot % num_slots_per_tdd;
- NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
+bool allocate_retransmission(module_id_t module_id,
+ uint8_t *rballoc_mask,
+ int *n_rb_sched,
+ int UE_id,
+ int current_harq_pid){
+ NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id];
NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid];
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
- if (harq->round != 0) { /* retransmission */
- sched_ctrl->time_domain_allocation = retInfo->time_domain_allocation;
+ sched_ctrl->time_domain_allocation = retInfo->time_domain_allocation;
- /* ensure that there is a free place for RB allocation */
- int rbSize = 0;
- while (rbSize < retInfo->rbSize) {
- rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
- rbSize = 0;
- while (rbStart < bwpSize && vrb_map[rbStart]) rbStart++;
- if (rbStart >= bwpSize) {
- LOG_E(MAC,
- "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n",
+ /* ensure that there is a free place for RB allocation */
+ int rbSize = 0;
+ while (rbSize < retInfo->rbSize) {
+ rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
+ rbSize = 0;
+ while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
+ if (rbStart >= bwpSize) {
+ LOG_D(MAC,
+ "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n",
+ UE_id,
+ RC.nrmac[module_id]->UE_info.rnti[UE_id]);
+ return false;
+ }
+ while (rbStart + rbSize < bwpSize
+ && rballoc_mask[rbStart + rbSize]
+ && rbSize < retInfo->rbSize)
+ rbSize++;
+ }
+ sched_ctrl->rbSize = retInfo->rbSize;
+ sched_ctrl->rbStart = rbStart;
+
+ /* MCS etc: just reuse from previous scheduling opportunity */
+ sched_ctrl->mcsTableIdx = retInfo->mcsTableIdx;
+ sched_ctrl->mcs = retInfo->mcs;
+ sched_ctrl->numDmrsCdmGrpsNoData = retInfo->numDmrsCdmGrpsNoData;
+
+ /* retransmissions: directly allocate */
+ *n_rb_sched -= sched_ctrl->rbSize;
+ for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
+ rballoc_mask[rb+sched_ctrl->rbStart] = 0;
+ return true;
+}
+
+float thr_ue[MAX_MOBILES_PER_GNB];
+
+void pf_dl(module_id_t module_id,
+ frame_t frame,
+ sub_frame_t slot,
+ NR_list_t *UE_list,
+ int n_rb_sched,
+ uint8_t *rballoc_mask,
+ int max_num_ue) {
+
+ NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
+ float coeff_ue[MAX_MOBILES_PER_GNB];
+ // UEs that could be scheduled
+ int ue_array[MAX_MOBILES_PER_GNB];
+ NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB };
+
+ /* Loop UE_info->list to check retransmission */
+ for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, NR_SearchSpace__searchSpaceType_PR_ue_Specific);
+ sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
+ /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */
+ sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
+ const rnti_t rnti = UE_info->rnti[UE_id];
+
+ /* Calculate Throughput */
+ const float a = 0.0005f; // corresponds to 200ms window
+ const uint32_t b = UE_info->mac_stats[UE_id].dlsch_current_bytes;
+ thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b;
+
+ /* retransmission */
+ if (sched_ctrl->dl_harq_pid >= 0) {
+ /* Find a free CCE */
+ bool freeCCE = find_free_CCE(module_id, slot, UE_id);
+ if (!freeCCE){
+ LOG_D(MAC, "%4d.%2d could not find CCE for DL DCI retransmission UE %d/RNTI %04x\n", frame, slot, UE_id, rnti);
+ continue;
+ }
+ /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH
+ * allocation after CCE alloc fail would be more complex) */
+ const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot);
+ if (!alloc) {
+ LOG_W(MAC,
+ "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
+ __func__,
UE_id,
- rnti);
+ rnti,
+ frame,
+ slot);
+ int cid = sched_ctrl->coreset->controlResourceSetId;
+ UE_info->num_pdcch_cand[UE_id][cid]--;
+ int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid];
+ for (int i = 0; i < sched_ctrl->aggregation_level; i++)
+ cce_list[sched_ctrl->cce_index + i] = 0;
return;
}
- while (rbStart + rbSize < bwpSize
- && !vrb_map[rbStart + rbSize]
- && rbSize < retInfo->rbSize)
- rbSize++;
- }
- sched_ctrl->rbSize = retInfo->rbSize;
- sched_ctrl->rbStart = rbStart;
+ /* Allocate retransmission */
+ bool r = allocate_retransmission(module_id, rballoc_mask, &n_rb_sched, UE_id, sched_ctrl->dl_harq_pid);
+ if (!r) {
+ LOG_D(MAC, "%4d.%2d retransmission can NOT be allocated\n", frame, slot);
+ continue;
+ }
+ /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
+ max_num_ue--;
+ if (max_num_ue < 0) return;
+ } else {
+ /* Check DL buffer and skip this UE if no bytes and no TA necessary */
+ if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 10) % 1024)
+ continue;
- /* MCS etc: just reuse from previous scheduling opportunity */
- sched_ctrl->mcsTableIdx = retInfo->mcsTableIdx;
- sched_ctrl->mcs = retInfo->mcs;
- sched_ctrl->numDmrsCdmGrpsNoData = retInfo->numDmrsCdmGrpsNoData;
- } else {
+ /* Calculate coeff */
+ sched_ctrl->time_domain_allocation = 2;
+ sched_ctrl->mcsTableIdx = 0;
+ sched_ctrl->mcs = 9;
+ sched_ctrl->numDmrsCdmGrpsNoData = 1;
+ uint8_t N_PRB_DMRS =
+ getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData);
+ int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp,
+ sched_ctrl->time_domain_allocation);
+ uint32_t tbs = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
+ nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
+ 1, // rbSize
+ nrOfSymbols,
+ N_PRB_DMRS, // FIXME // This should be multiplied by the
+ // number of dmrs symbols
+ 0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */,
+ 1 /* nrOfLayers */)
+ >> 3;
+ coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id];
+ LOG_D(MAC,"b %d, thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n",
+ b, UE_id, thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]);
+ /* Create UE_sched list for UEs eligible for new transmission*/
+ add_tail_nr_list(&UE_sched, UE_id);
+ }
+ }
+
+ /* Loop UE_sched to find max coeff and allocate transmission */
+ while (max_num_ue > 0 && n_rb_sched > 0 && UE_sched.head >= 0) {
+
+ /* Find max coeff from UE_sched*/
+ int *max = &UE_sched.head; /* assume head is max */
+ int *p = &UE_sched.next[*max];
+ while (*p >= 0) {
+ /* if the current one has larger coeff, save for later */
+ if (coeff_ue[*p] > coeff_ue[*max])
+ max = p;
+ p = &UE_sched.next[*p];
+ }
+ /* remove the max one: do not use remove_nr_list() it goes through the
+ * whole list every time. Note that UE_sched.tail might not be set
+ * correctly anymore */
+ const int UE_id = *max;
+ p = &UE_sched.next[*max];
+ *max = UE_sched.next[*max];
+ *p = -1;
+
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ const uint16_t rnti = UE_info->rnti[UE_id];
+ const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+ int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+
+ /* Find a free CCE */
+ bool freeCCE = find_free_CCE(module_id, slot, UE_id);
+ if (!freeCCE) {
+ LOG_D(MAC, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, UE_id, rnti);
+ continue;
+ }
+ /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
+ max_num_ue--;
+ if (max_num_ue < 0) return;
+
+ /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH
+ * allocation after CCE alloc fail would be more complex) */
+ const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot);
+ if (!alloc) {
+ LOG_W(MAC,
+ "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
+ __func__,
+ UE_id,
+ rnti,
+ frame,
+ slot);
+ int cid = sched_ctrl->coreset->controlResourceSetId;
+ UE_info->num_pdcch_cand[UE_id][cid]--;
+ int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid];
+ for (int i = 0; i < sched_ctrl->aggregation_level; i++)
+ cce_list[sched_ctrl->cce_index + i] = 0;
+ return;
+ }
+
+ /* Allocate transmission */
// Time-domain allocation
sched_ctrl->time_domain_allocation = 2;
@@ -498,20 +570,22 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
sched_ctrl->numDmrsCdmGrpsNoData = 1;
// Freq-demain allocation
- while (rbStart < bwpSize && vrb_map[rbStart]) rbStart++;
+ while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
- uint8_t N_PRB_DMRS =
+ const uint8_t N_PRB_DMRS =
getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData);
- int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp,
- sched_ctrl->time_domain_allocation);
- uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup,
- RC.nrmac[module_id]->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position ,
- nrOfSymbols);
+ const int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp,
+ sched_ctrl->time_domain_allocation);
+ const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels->ServingCellConfigCommon;
+ const uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(
+ sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup,
+ scc->dmrs_TypeA_Position,
+ nrOfSymbols);
int rbSize = 0;
+ uint32_t TBS = 0;
const int oh = 2 + (sched_ctrl->num_total_bytes >= 256)
+ 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
- uint32_t TBS = 0;
do {
rbSize++;
TBS = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
@@ -523,31 +597,74 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
0 /* tb_scaling */,
1 /* nrOfLayers */)
>> 3;
- } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes + oh);
+ } while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes + oh);
sched_ctrl->rbSize = rbSize;
sched_ctrl->rbStart = rbStart;
+
+ /* transmissions: directly allocate */
+ n_rb_sched -= sched_ctrl->rbSize;
+ for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
+ rballoc_mask[rb+sched_ctrl->rbStart] = 0;
+ }
+}
+
+void nr_simple_dlsch_preprocessor(module_id_t module_id,
+ frame_t frame,
+ sub_frame_t slot) {
+ NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
+
+ if (UE_info->num_UEs == 0)
+ return;
+
+ const int CC_id = 0;
+
+
+ /* Get bwpSize from the first UE */
+ int UE_id = UE_info->list.head;
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+
+ uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
+ uint8_t rballoc_mask[bwpSize];
+ int n_rb_sched = 0;
+ for (int i = 0; i < bwpSize; i++) {
+ // calculate mask: init with "NOT" vrb_map:
+ // if any RB in vrb_map is blocked (1), the current RBG will be 0
+ rballoc_mask[i] = !vrb_map[i];
+ n_rb_sched += rballoc_mask[i];
}
- /* mark the corresponding RBs as used */
- for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
- vrb_map[rb + sched_ctrl->rbStart] = 1;
+ /* Retrieve amount of data to send for this UE */
+ nr_store_dlsch_buffer(module_id, frame, slot);
+
+ /* proportional fair scheduling algorithm */
+ pf_dl(module_id,
+ frame,
+ slot,
+ &UE_info->list,
+ n_rb_sched,
+ rballoc_mask,
+ 2);
}
void nr_schedule_ue_spec(module_id_t module_id,
frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd) {
+ sub_frame_t slot) {
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
/* PREPROCESSOR */
- gNB_mac->pre_processor_dl(module_id, frame, slot, num_slots_per_tdd);
-
- NR_UE_info_t *UE_info = &gNB_mac->UE_info;
+ gNB_mac->pre_processor_dl(module_id, frame, slot);
const int CC_id = 0;
- NR_UE_list_t *UE_list = &UE_info->list;
+ NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
+ NR_UE_info_t *UE_info = &gNB_mac->UE_info;
+
+ nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
+
+ 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]) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ UE_info->mac_stats[UE_id].dlsch_current_bytes = 0;
/* update TA and set ta_apply every 10 frames.
* Possible improvement: take the periodicity from input file.
@@ -578,10 +695,13 @@ void nr_schedule_ue_spec(module_id_t module_id,
uint8_t N_PRB_DMRS =
getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData);
-
uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup,
RC.nrmac[module_id]->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position ,
nrOfSymbols);
+ const nfapi_nr_dmrs_type_e dmrsConfigType = getDmrsConfigType(sched_ctrl->active_bwp);
+ const int nrOfLayers = 1;
+ const uint16_t R = nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx);
+ const uint8_t Qm = nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx);
const uint32_t TBS =
nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
@@ -590,36 +710,228 @@ void nr_schedule_ue_spec(module_id_t module_id,
N_PRB_DMRS * N_DMRS_SLOT,
0 /* N_PRB_oh, 0 for initialBWP */,
0 /* tb_scaling */,
- 1 /* nrOfLayers */)
+ nrOfLayers)
>> 3;
- const int current_harq_pid = slot % num_slots_per_tdd;
+ int8_t current_harq_pid = sched_ctrl->dl_harq_pid;
+ if (current_harq_pid < 0) {
+ /* PP has not selected a specific HARQ Process, get a new one */
+ current_harq_pid = sched_ctrl->available_dl_harq.head;
+ AssertFatal(current_harq_pid >= 0,
+ "no free HARQ process available for UE %d\n",
+ UE_id);
+ remove_front_nr_list(&sched_ctrl->available_dl_harq);
+ sched_ctrl->dl_harq_pid = current_harq_pid;
+ } else {
+ /* PP selected a specific HARQ process. Check whether it will be a new
+ * transmission or a retransmission, and remove from the corresponding
+ * list */
+ if (sched_ctrl->harq_processes[current_harq_pid].round == 0)
+ remove_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid);
+ else
+ remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid);
+ }
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
- NR_sched_pucch *pucch = &sched_ctrl->sched_pucch[sched_ctrl->pucch_sched_idx][sched_ctrl->pucch_occ_idx];
+ DevAssert(!harq->is_waiting);
+ add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid);
+ NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
harq->feedback_slot = pucch->ul_slot;
- harq->is_waiting = 1;
+ harq->is_waiting = true;
UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
- LOG_D(MAC, "%4d.%2d RNTI %04x start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
- frame, slot, rnti, sched_ctrl->rbStart, sched_ctrl->rbSize, sched_ctrl->mcs,
- TBS, current_harq_pid, harq->round, harq->ndi);
+ LOG_D(MAC,
+ "%4d.%2d RNTI %04x start %d RBs %d startSymbol %d nb_symbsol %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
+ frame,
+ slot,
+ rnti,
+ sched_ctrl->rbStart,
+ sched_ctrl->rbSize,
+ startSymbolIndex,
+ nrOfSymbols,
+ sched_ctrl->mcs,
+ TBS,
+ current_harq_pid,
+ harq->round,
+ harq->ndi);
- nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
- nr_fill_nfapi_dl_pdu(module_id,
- dl_req,
- rnti,
- UE_info->secondaryCellGroup[UE_id],
- sched_ctrl,
- pucch,
- getDmrsConfigType(sched_ctrl->active_bwp),
- nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
- nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
- TBS,
- startSymbolIndex,
- nrOfSymbols,
- current_harq_pid,
- harq->ndi,
- harq->round);
+ NR_BWP_Downlink_t *bwp = sched_ctrl->active_bwp;
+ AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList,
+ "searchSpacesToAddModList is null\n");
+ AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count > 0,
+ "searchSPacesToAddModList is empty\n");
+
+ /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not
+ * exist, create it */
+ const int bwpid = sched_ctrl->active_bwp->bwp_Id;
+ const int coresetid = sched_ctrl->coreset->controlResourceSetId;
+ nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid];
+ if (!pdcch_pdu) {
+ nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
+ memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
+ dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
+ dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
+ dl_req->nPDUs += 1;
+ pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
+ nr_configure_pdcch(pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, bwp);
+ gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu;
+ }
+
+ nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
+ memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t));
+ dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
+ dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
+ dl_req->nPDUs += 1;
+ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
+
+ pdsch_pdu->pduBitmap = 0;
+ pdsch_pdu->rnti = rnti;
+ /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control
+ * message. This is used to associate control information to data and is
+ * reset every slot. */
+ const int pduindex = gNB_mac->pdu_index[CC_id]++;
+ pdsch_pdu->pduIndex = pduindex;
+
+ // BWP
+ pdsch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+ pdsch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE);
+ pdsch_pdu->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
+ if (bwp->bwp_Common->genericParameters.cyclicPrefix)
+ pdsch_pdu->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix;
+ else
+ pdsch_pdu->CyclicPrefix = 0;
+
+ // Codeword information
+ pdsch_pdu->NrOfCodewords = 1;
+ pdsch_pdu->targetCodeRate[0] = R;
+ pdsch_pdu->qamModOrder[0] = Qm;
+ pdsch_pdu->mcsIndex[0] = sched_ctrl->mcs;
+ pdsch_pdu->mcsTable[0] = sched_ctrl->mcsTableIdx;
+ pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round];
+ pdsch_pdu->TBSize[0] = TBS;
+
+ pdsch_pdu->dataScramblingId = *scc->physCellId;
+ pdsch_pdu->nrOfLayers = nrOfLayers;
+ pdsch_pdu->transmissionScheme = 0;
+ pdsch_pdu->refPoint = 0; // Point A
+
+ // DMRS
+ pdsch_pdu->dlDmrsSymbPos =
+ fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup,
+ scc->dmrs_TypeA_Position,
+ nrOfSymbols);
+ pdsch_pdu->dmrsConfigType = dmrsConfigType;
+ pdsch_pdu->dlDmrsScramblingId = *scc->physCellId;
+ pdsch_pdu->SCID = 0;
+ pdsch_pdu->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
+ pdsch_pdu->dmrsPorts = 1;
+
+ // Pdsch Allocation in frequency domain
+ pdsch_pdu->resourceAlloc = 1;
+ pdsch_pdu->rbStart = sched_ctrl->rbStart;
+ pdsch_pdu->rbSize = sched_ctrl->rbSize;
+ pdsch_pdu->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
+
+ // Resource Allocation in time domain
+ pdsch_pdu->StartSymbolIndex = startSymbolIndex;
+ pdsch_pdu->NrOfSymbols = nrOfSymbols;
+
+ /* Check and validate PTRS values */
+ struct NR_SetupRelease_PTRS_DownlinkConfig *phaseTrackingRS =
+ bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS;
+ if (phaseTrackingRS) {
+ bool valid_ptrs_setup = set_dl_ptrs_values(phaseTrackingRS->choice.setup,
+ pdsch_pdu->rbSize,
+ pdsch_pdu->mcsIndex[0],
+ pdsch_pdu->mcsTable[0],
+ &pdsch_pdu->PTRSFreqDensity,
+ &pdsch_pdu->PTRSTimeDensity,
+ &pdsch_pdu->PTRSPortIndex,
+ &pdsch_pdu->nEpreRatioOfPDSCHToPTRS,
+ &pdsch_pdu->PTRSReOffset,
+ pdsch_pdu->NrOfSymbols);
+ if (valid_ptrs_setup)
+ pdsch_pdu->pduBitmap |= 0x1; // Bit 0: pdschPtrs - Indicates PTRS included (FR2)
+ }
+
+ /* Fill PDCCH DL DCI PDU */
+ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci];
+ pdcch_pdu->numDlDci++;
+ dci_pdu->RNTI = rnti;
+ if (sched_ctrl->coreset->pdcch_DMRS_ScramblingID &&
+ sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
+ dci_pdu->ScramblingId = *sched_ctrl->coreset->pdcch_DMRS_ScramblingID;
+ dci_pdu->ScramblingRNTI = rnti;
+ } else {
+ dci_pdu->ScramblingId = *scc->physCellId;
+ dci_pdu->ScramblingRNTI = 0;
+ }
+ dci_pdu->AggregationLevel = sched_ctrl->aggregation_level;
+ dci_pdu->CceIndex = sched_ctrl->cce_index;
+ dci_pdu->beta_PDCCH_1_0 = 0;
+ dci_pdu->powerControlOffsetSS = 1;
+
+ /* DCI payload */
+ dci_pdu_rel15_t dci_payload;
+ memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t));
+ // bwp indicator
+ const int n_dl_bwp = UE_info->secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count;
+ AssertFatal(n_dl_bwp == 1,
+ "downlinkBWP_ToAddModList has %d BWP!\n",
+ n_dl_bwp);
+ // as per table 7.3.1.1.2-1 in 38.212
+ dci_payload.bwp_indicator.val = n_dl_bwp < 4 ? bwp->bwp_Id : bwp->bwp_Id - 1;
+ AssertFatal(bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1,
+ "Only frequency resource allocation type 1 is currently supported\n");
+ dci_payload.frequency_domain_assignment.val =
+ PRBalloc_to_locationandbandwidth0(
+ pdsch_pdu->rbSize,
+ pdsch_pdu->rbStart,
+ pdsch_pdu->BWPSize);
+ dci_payload.time_domain_assignment.val = sched_ctrl->time_domain_allocation;
+ dci_payload.mcs = sched_ctrl->mcs;
+ dci_payload.rv = pdsch_pdu->rvIndex[0];
+ dci_payload.harq_pid = current_harq_pid;
+ dci_payload.ndi = harq->ndi;
+ dci_payload.dai[0].val = (pucch->dai_c-1)&3;
+ dci_payload.tpc = sched_ctrl->tpc1; // TPC for PUCCH: table 7.2.1-1 in 38.213
+ dci_payload.pucch_resource_indicator = pucch->resource_indicator;
+ dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch->timing_indicator; // PDSCH to HARQ TI
+ dci_payload.antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0
+ dci_payload.dmrs_sequence_initialization.val = pdsch_pdu->SCID;
+ LOG_D(MAC,
+ "%4d.%2d DCI type 1 payload: freq_alloc %d (%d,%d,%d), "
+ "time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n",
+ frame,
+ slot,
+ dci_payload.frequency_domain_assignment.val,
+ pdsch_pdu->rbStart,
+ pdsch_pdu->rbSize,
+ pdsch_pdu->BWPSize,
+ dci_payload.time_domain_assignment.val,
+ dci_payload.vrb_to_prb_mapping.val,
+ dci_payload.mcs,
+ dci_payload.tb_scaling,
+ dci_payload.ndi,
+ dci_payload.rv);
+
+ const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
+ const int dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0;
+ const int rnti_type = NR_RNTI_C;
+
+ fill_dci_pdu_rel15(scc,
+ UE_info->secondaryCellGroup[UE_id],
+ dci_pdu,
+ &dci_payload,
+ dci_format,
+ rnti_type,
+ pdsch_pdu->BWPSize,
+ bwp->bwp_Id);
+
+ LOG_D(MAC,
+ "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
+ (unsigned long long)pdcch_pdu->FreqDomainResource,
+ pdcch_pdu->StartSymbolIndex,
+ pdcch_pdu->DurationSymbols);
NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid];
if (harq->round != 0) { /* retransmission */
@@ -645,8 +957,9 @@ void nr_schedule_ue_spec(module_id_t module_id,
retInfo->mcs,
retInfo->numDmrsCdmGrpsNoData);
/* we do not have to do anything, since we do not require to get data
- * from RLC, encode MAC CEs, or copy data to FAPI structures */
- LOG_W(MAC,
+ * from RLC or encode MAC CEs. The TX_req structure is filled below
+ * or copy data to FAPI structures */
+ LOG_D(MAC,
"%d.%2d DL retransmission UE %d/RNTI %04x HARQ PID %d round %d NDI %d\n",
frame,
slot,
@@ -655,111 +968,121 @@ void nr_schedule_ue_spec(module_id_t module_id,
current_harq_pid,
harq->round,
harq->ndi);
+ AssertFatal(harq->tb_size == TBS,
+ "UE %d mismatch between scheduled TBS and buffered TB for HARQ PID %d\n",
+ UE_id,
+ current_harq_pid);
} else { /* initial transmission */
LOG_D(MAC, "[%s] Initial HARQ transmission in %d.%d\n", __FUNCTION__, frame, slot);
- /* reserve space for timing advance of UE if necessary,
- * nr_generate_dlsch_pdu() checks for ta_apply and add TA CE if necessary */
- const int ta_len = (sched_ctrl->ta_apply) ? 2 : 0;
- /* Get RLC data */
- int header_length_total = 0;
- int header_length_last = 0;
- int sdu_length_total = 0;
- int num_sdus = 0;
- uint16_t sdu_lengths[NB_RB_MAX] = {0};
- uint8_t mac_sdus[MAX_NR_DLSCH_PAYLOAD_BYTES];
- unsigned char sdu_lcids[NB_RB_MAX] = {0};
+ harq->tb_size = TBS;
+ uint8_t *buf = (uint8_t *) harq->tb;
+
+ /* first, write all CEs that might be there */
+ int written = nr_write_ce_dlsch_pdu(module_id,
+ sched_ctrl,
+ (unsigned char *)buf,
+ 255, // no drx
+ NULL); // contention res id
+ buf += written;
+ int size = TBS - written;
+ DevAssert(size >= 0);
+
+ /* next, get RLC data */
+
const int lcid = DL_SCH_LCID_DTCH;
+ int dlsch_total_bytes = 0;
if (sched_ctrl->num_total_bytes > 0) {
- /* this is the data from the RLC we would like to request (e.g., only
- * some bytes for first LC and some more from a second one */
- const rlc_buffer_occupancy_t ndata = sched_ctrl->rlc_status[lcid].bytes_in_buffer;
- /* this is the maximum data we can transport based on TBS minus headers */
- const int mindata = min(ndata, TBS - ta_len - header_length_total - sdu_length_total - 2 - (ndata >= 256));
- LOG_D(MAC,
- "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting "
- "%d bytes from RLC (lcid %d total hdr len %d), TBS: %d \n \n",
- module_id,
- frame,
- mindata,
- lcid,
- header_length_total,
- TBS);
+ tbs_size_t len = 0;
+ while (size > 3) {
+ // we do not know how much data we will get from RLC, i.e., whether it
+ // will be longer than 256B or not. Therefore, reserve space for long header, then
+ // fetch data, then fill real length
+ NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
+ buf += 3;
+ size -= 3;
- sdu_lengths[num_sdus] = mac_rlc_data_req(module_id,
- rnti,
- module_id,
- frame,
- ENB_FLAG_YES,
- MBMS_FLAG_NO,
- lcid,
- mindata,
- (char *)&mac_sdus[sdu_length_total],
- 0,
- 0);
+ /* limit requested number of bytes to what preprocessor specified, or
+ * such that TBS is full */
+ const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size);
+ len = mac_rlc_data_req(module_id,
+ rnti,
+ module_id,
+ frame,
+ ENB_FLAG_YES,
+ MBMS_FLAG_NO,
+ lcid,
+ ndata,
+ (char *)buf,
+ 0,
+ 0);
- LOG_D(MAC,
- "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n",
- module_id,
- sdu_lengths[num_sdus],
- lcid);
+ LOG_D(MAC,
+ "%4d.%2d RNTI %04x: %d bytes from DTCH %d (ndata %d, remaining size %d)\n",
+ frame,
+ slot,
+ rnti,
+ len,
+ lcid,
+ ndata,
+ size);
+ if (len == 0)
+ break;
- sdu_lcids[num_sdus] = lcid;
- sdu_length_total += sdu_lengths[num_sdus];
- header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128);
- header_length_total += header_length_last;
- num_sdus++;
+ header->R = 0;
+ header->F = 1;
+ header->LCID = lcid;
+ header->L1 = (len >> 8) & 0xff;
+ header->L2 = len & 0xff;
+ size -= len;
+ buf += len;
+ dlsch_total_bytes += len;
+ }
+ if (len == 0) {
+ /* RLC did not have data anymore, mark buffer as unused */
+ buf -= 3;
+ size += 3;
+ }
}
else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) {
- LOG_D(MAC, "Configuring DL_TX in %d.%d: random data\n", frame, slot);
+ /* we will need the large header, phy-test typically allocates all
+ * resources and fills to the last byte below */
+ NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf;
+ buf += 3;
+ size -= 3;
+ DevAssert(size > 0);
+ LOG_D(MAC, "Configuring DL_TX in %d.%d: TBS %d with %d B of random data\n", frame, slot, TBS, size);
// fill dlsch_buffer with random data
- for (int i = 0; i < TBS; i++)
- mac_sdus[i] = (unsigned char) (lrand48()&0xff);
- sdu_lcids[0] = 0x3f; // DRB
- sdu_lengths[0] = TBS - ta_len - 3;
- header_length_total += 2 + (sdu_lengths[0] >= 256);
- sdu_length_total += sdu_lengths[0];
- num_sdus +=1;
+ for (int i = 0; i < size; i++)
+ buf[i] = lrand48() & 0xff;
+ header->R = 0;
+ header->F = 1;
+ header->LCID = DL_SCH_LCID_PADDING;
+ header->L1 = (size >> 8) & 0xff;
+ header->L2 = size & 0xff;
+ size -= size;
+ buf += size;
+ dlsch_total_bytes += size;
+ }
+
+ // Add padding header and zero rest out if there is space left
+ if (size > 0) {
+ NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) buf;
+ padding->R = 0;
+ padding->LCID = DL_SCH_LCID_PADDING;
+ size -= 1;
+ buf += 1;
+ while (size > 0) {
+ *buf = 0;
+ buf += 1;
+ size -= 1;
+ }
}
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
- UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total;
-
- const int post_padding = TBS > header_length_total + sdu_length_total + ta_len;
-
- const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs;
- nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req];
- /* pointer to directly generate the PDU into the nFAPI structure */
- uint32_t *buf = tx_req->TLVs[0].value.direct;
-
- const int offset = nr_generate_dlsch_pdu(
- module_id,
- sched_ctrl,
- (unsigned char *)mac_sdus,
- (unsigned char *)buf,
- num_sdus, // num_sdus
- sdu_lengths,
- sdu_lcids,
- 255, // no drx
- NULL, // contention res id
- post_padding);
-
- // Padding: fill remainder of DLSCH with 0
- if (post_padding > 0) {
- for (int j = 0; j < TBS - offset; j++)
- buf[offset + j] = 0;
- }
-
- /* the buffer has been filled by nr_generate_dlsch_pdu(), below we simply
- * fill the remaining information */
- tx_req->PDU_length = TBS;
- tx_req->PDU_index = gNB_mac->pdu_index[0]++;
- tx_req->num_TLV = 1;
- tx_req->TLVs[0].length = TBS + 2;
- gNB_mac->TX_req[CC_id].Number_of_PDUs++;
- gNB_mac->TX_req[CC_id].SFN = frame;
- gNB_mac->TX_req[CC_id].Slot = slot;
+ UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS;
+ UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes;
retInfo->rbSize = sched_ctrl->rbSize;
retInfo->time_domain_allocation = sched_ctrl->time_domain_allocation;
@@ -779,21 +1102,20 @@ void nr_schedule_ue_spec(module_id_t module_id,
}
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 (frame%100 == 0) {
- LOG_I(MAC,
- "%d.%d, first 10 payload bytes, TBS size: %d \n",
- frame,
- slot,
- TBS);
- for(int i = 0; i < 10; i++)
- LOG_I(MAC, "byte %d: %x\n", i, ((uint8_t *) buf)[i]);
- }
-#endif
+ T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->tb, TBS));
}
+ const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs;
+ nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req];
+ tx_req->PDU_length = TBS;
+ tx_req->PDU_index = pduindex;
+ tx_req->num_TLV = 1;
+ tx_req->TLVs[0].length = TBS + 2;
+ memcpy(tx_req->TLVs[0].value.direct, harq->tb, TBS);
+ gNB_mac->TX_req[CC_id].Number_of_PDUs++;
+ gNB_mac->TX_req[CC_id].SFN = frame;
+ gNB_mac->TX_req[CC_id].Slot = slot;
+
/* mark UE as scheduled */
sched_ctrl->rbSize = 0;
}
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
index 5707f2c75a..8dbe8728f3 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
@@ -255,9 +255,10 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
/* schedules whole bandwidth for first user, all the time */
void nr_preprocessor_phytest(module_id_t module_id,
frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd)
+ sub_frame_t slot)
{
+ if (slot != 1)
+ return;
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
const int UE_id = 0;
const int CC_id = 0;
@@ -328,14 +329,25 @@ void nr_preprocessor_phytest(module_id_t module_id,
__func__,
UE_id);
- nr_acknack_scheduling(module_id,
- UE_id,
- frame,
- slot,
- num_slots_per_tdd,
- &sched_ctrl->pucch_sched_idx,
- &sched_ctrl->pucch_occ_idx);
- AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n");
+ const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot);
+ if (!alloc) {
+ LOG_D(MAC,
+ "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
+ __func__,
+ UE_id,
+ rnti,
+ frame,
+ slot);
+ UE_info->num_pdcch_cand[UE_id][cid]--;
+ int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid];
+ for (int i = 0; i < sched_ctrl->aggregation_level; i++)
+ cce_list[sched_ctrl->cce_index + i] = 0;
+ return;
+ }
+
+ AssertFatal(alloc,
+ "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n",
+ rnti, frame, slot);
sched_ctrl->rbStart = rbStart;
sched_ctrl->rbSize = rbSize;
@@ -350,13 +362,15 @@ void nr_preprocessor_phytest(module_id_t module_id,
}
sched_ctrl->mcs = 9;
sched_ctrl->numDmrsCdmGrpsNoData = 1;
+ /* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */
+ sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
/* mark the corresponding RBs as used */
for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
vrb_map[rb + sched_ctrl->rbStart] = 1;
}
-void nr_ul_preprocessor_phytest(module_id_t module_id,
+bool nr_ul_preprocessor_phytest(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd,
@@ -372,7 +386,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
__func__,
UE_info->num_UEs);
if (UE_info->num_UEs == 0)
- return;
+ return false;
const int UE_id = 0;
const int CC_id = 0;
@@ -387,15 +401,15 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
tda,
tdaList->list.count);
int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu);
- const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd);
- const int sched_slot = (slot + K2) % num_slots_per_tdd;
+ const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
+ const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
/* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE
* limitations). Note that if K2 or the TDD configuration is changed, below
* conditions might exclude each other and never be true */
if (!(is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot) && sched_slot == 8))
- return;
+ return false;
- const int bw = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
+ const int bw = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
uint16_t rbStart = 0;
uint16_t rbSize = 50; /* due to OAI UE limitations */
if (rbSize>bw)
@@ -411,7 +425,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
frame,
slot,
i);
- return;
+ return false;
}
}
@@ -438,7 +452,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
nr_of_candidates);
if (sched_ctrl->cce_index < 0) {
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__);
- return;
+ return false;
}
UE_info->num_pdcch_cand[UE_id][cid]++;
@@ -465,6 +479,8 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
sched_pusch->mcs = mcs;
sched_pusch->rbStart = rbStart;
sched_pusch->rbSize = rbSize;
+ /* get the PID of a HARQ process awaiting retransmission, or -1 for "any new" */
+ sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
/* Calculate TBS from MCS */
sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
@@ -487,4 +503,5 @@ void nr_ul_preprocessor_phytest(module_id_t module_id,
/* mark the corresponding RBs as used */
for (int rb = rbStart; rb < rbStart + rbSize; rb++)
vrb_map_UL[rb] = 1;
+ return true;
}
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index 0ef79084ae..20da8fa30a 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -502,259 +502,34 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
}
-void nr_fill_nfapi_dl_pdu(int Mod_idP,
- nfapi_nr_dl_tti_request_body_t *dl_req,
- rnti_t rnti,
- NR_CellGroupConfig_t *secondaryCellGroup,
- NR_UE_sched_ctrl_t *sched_ctrl,
- NR_sched_pucch *pucch_sched,
- nfapi_nr_dmrs_type_e dmrsConfigType,
- uint16_t R,
- uint8_t Qm,
- uint32_t TBS,
- int StartSymbolIndex,
- int NrOfSymbols,
- int harq_pid,
- int ndi,
- int round) {
- gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP];
- NR_COMMON_channels_t *cc = nr_mac->common_channels;
- NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
-
- const int bwp_id = sched_ctrl->active_bwp->bwp_Id;
- const int nrOfLayers = 1;
- const int mcs = sched_ctrl->mcs;
- const int mcs_table_index = sched_ctrl->mcsTableIdx;
- bool valid_ptrs_setup = false;
-
- AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
- "downlinkBWP_ToAddModList has %d BWP!\n",
- secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
- NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1];
-
- AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n");
- AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0,
- "searchPsacesToAddModList is empty\n");
-
- nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
- memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
- dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
- dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
-
- nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
- memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
- dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
- dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
-
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
- nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
-
-
- pdsch_pdu_rel15->pduBitmap = 0;
- pdsch_pdu_rel15->rnti = rnti;
- pdsch_pdu_rel15->pduIndex = nr_mac->pdu_index[0]++;
-
- // BWP
- pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
- pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
- pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
- if (bwp->bwp_Common->genericParameters.cyclicPrefix)
- pdsch_pdu_rel15->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix;
- else
- pdsch_pdu_rel15->CyclicPrefix = 0;
-
- pdsch_pdu_rel15->NrOfCodewords = 1;
- pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs, mcs_table_index);
- pdsch_pdu_rel15->qamModOrder[0] = 2;
- pdsch_pdu_rel15->mcsIndex[0] = mcs;
- pdsch_pdu_rel15->mcsTable[0] = mcs_table_index;
- pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[round];
- pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
- pdsch_pdu_rel15->nrOfLayers = nrOfLayers;
- pdsch_pdu_rel15->transmissionScheme = 0;
- pdsch_pdu_rel15->refPoint = 0; // Point A
- pdsch_pdu_rel15->dmrsConfigType = dmrsConfigType;
- pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
- pdsch_pdu_rel15->SCID = 0;
- pdsch_pdu_rel15->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
- pdsch_pdu_rel15->dmrsPorts = 1;
- pdsch_pdu_rel15->resourceAlloc = 1;
- pdsch_pdu_rel15->rbStart = sched_ctrl->rbStart;
- pdsch_pdu_rel15->rbSize = sched_ctrl->rbSize;
- pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
- pdsch_pdu_rel15->targetCodeRate[0] = R;
- pdsch_pdu_rel15->qamModOrder[0] = Qm;
- pdsch_pdu_rel15->TBSize[0] = TBS;
- pdsch_pdu_rel15->mcsTable[0] = sched_ctrl->mcsTableIdx;
- pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
- pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
-
- pdsch_pdu_rel15->dlDmrsSymbPos =
- fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup,
- scc->dmrs_TypeA_Position,
- pdsch_pdu_rel15->NrOfSymbols);
-
- /* Check and validate PTRS values */
- if(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) {
- valid_ptrs_setup = set_dl_ptrs_values(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup,
- pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->mcsIndex[0],
- pdsch_pdu_rel15->mcsTable[0],
- &pdsch_pdu_rel15->PTRSFreqDensity,&pdsch_pdu_rel15->PTRSTimeDensity,
- &pdsch_pdu_rel15->PTRSPortIndex,&pdsch_pdu_rel15->nEpreRatioOfPDSCHToPTRS,
- &pdsch_pdu_rel15->PTRSReOffset, pdsch_pdu_rel15->NrOfSymbols);
- if(valid_ptrs_setup==true) {
- pdsch_pdu_rel15->pduBitmap |=0x1;
- }
- }
-
- dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
- memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t) * MAX_DCI_CORESET);
-
- // bwp indicator
- int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count;
- if (n_dl_bwp < 4)
- dci_pdu_rel15[0].bwp_indicator.val = bwp_id;
- else
- dci_pdu_rel15[0].bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212
- // frequency domain assignment
- if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation==NR_PDSCH_Config__resourceAllocation_resourceAllocationType1)
- dci_pdu_rel15[0].frequency_domain_assignment.val =
- PRBalloc_to_locationandbandwidth0(
- pdsch_pdu_rel15->rbSize,
- pdsch_pdu_rel15->rbStart,
- NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,
- MAX_BWP_SIZE));
- else
- AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n");
- // time domain assignment: row index used instead of SLIV
- dci_pdu_rel15[0].time_domain_assignment.val = sched_ctrl->time_domain_allocation;
- // mcs and rv
- dci_pdu_rel15[0].mcs = mcs;
- dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0];
- // harq pid and ndi
- dci_pdu_rel15[0].harq_pid = harq_pid;
- dci_pdu_rel15[0].ndi = ndi;
- // DAI
- dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3;
-
- // TPC for PUCCH
- dci_pdu_rel15[0].tpc = sched_ctrl->tpc1; // table 7.2.1-1 in 38.213
- // PUCCH resource indicator
- dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator;
- // PDSCH to HARQ TI
- dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator;
- // antenna ports
- dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0
- // dmrs sequence initialization
- dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
- LOG_D(MAC,
- "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), "
- "time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n",
- dci_pdu_rel15[0].frequency_domain_assignment.val,
- pdsch_pdu_rel15->rbStart,
- pdsch_pdu_rel15->rbSize,
- NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE),
- dci_pdu_rel15[0].time_domain_assignment.val,
- dci_pdu_rel15[0].vrb_to_prb_mapping.val,
- dci_pdu_rel15[0].mcs,
- dci_pdu_rel15[0].tb_scaling,
- dci_pdu_rel15[0].ndi,
- dci_pdu_rel15[0].rv);
-
- nr_configure_pdcch(nr_mac,
- pdcch_pdu_rel15,
- rnti,
- sched_ctrl->search_space,
- sched_ctrl->coreset,
- scc,
- bwp,
- sched_ctrl->aggregation_level,
- sched_ctrl->cce_index);
-
- int dci_formats[2];
- int rnti_types[2];
-
- if (sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats)
- dci_formats[0] = NR_DL_DCI_FORMAT_1_1;
- else
- dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
-
- rnti_types[0] = NR_RNTI_C;
-
- fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id);
-
- LOG_D(MAC,
- "DCI params: rnti %x, rnti_type %d, dci_format %d\n",
- pdcch_pdu_rel15->dci_pdu.RNTI[0],
- rnti_types[0],
- dci_formats[0]);
- LOG_D(MAC,
- "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
- (unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
- pdcch_pdu_rel15->StartSymbolIndex,
- pdcch_pdu_rel15->DurationSymbols);
-
- LOG_D(MAC,
- "DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d "
- "nb_layers %d nb_codewords %d mcs %d TBS: %d\n",
- pdsch_pdu_rel15->rbStart,
- pdsch_pdu_rel15->rbSize,
- pdsch_pdu_rel15->StartSymbolIndex,
- pdsch_pdu_rel15->NrOfSymbols,
- pdsch_pdu_rel15->nrOfLayers,
- pdsch_pdu_rel15->NrOfCodewords,
- pdsch_pdu_rel15->mcsIndex[0],
- TBS);
-
- dl_req->nPDUs += 2;
-}
-
-void config_uldci(NR_BWP_Uplink_t *ubwp,
- nfapi_nr_pusch_pdu_t *pusch_pdu,
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
+void config_uldci(const NR_BWP_Uplink_t *ubwp,
+ const nfapi_nr_pusch_pdu_t *pusch_pdu,
dci_pdu_rel15_t *dci_pdu_rel15,
- int *dci_formats,
- int time_domain_assignment, uint8_t tpc,
- int n_ubwp, int bwp_id) {
+ int dci_format,
+ int time_domain_assignment,
+ uint8_t tpc,
+ int n_ubwp,
+ int bwp_id) {
const int bw = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
- switch (dci_formats[(pdcch_pdu_rel15->numDlDci) - 1]) {
+ dci_pdu_rel15->frequency_domain_assignment.val =
+ PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw);
+ dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment;
+ dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping;
+ dci_pdu_rel15->mcs = pusch_pdu->mcs_index;
+ dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator;
+ dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index;
+ dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id;
+ dci_pdu_rel15->tpc = tpc;
+ AssertFatal(ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1,
+ "Only frequency resource allocation type 1 is currently supported\n");
+ switch (dci_format) {
case NR_UL_DCI_FORMAT_0_0:
- dci_pdu_rel15->frequency_domain_assignment.val =
- PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw);
-
- dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment;
- dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping;
- dci_pdu_rel15->mcs = pusch_pdu->mcs_index;
-
dci_pdu_rel15->format_indicator = 0;
- dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator;
- dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index;
- dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id;
- dci_pdu_rel15->tpc = tpc;
break;
case NR_UL_DCI_FORMAT_0_1:
- dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator;
- dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index;
- dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id;
- dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping;
dci_pdu_rel15->dai[0].val = 0; //TODO
- // bwp indicator
- if (n_ubwp < 4)
- dci_pdu_rel15->bwp_indicator.val = bwp_id;
- else
- dci_pdu_rel15->bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212
- // frequency domain assignment
- AssertFatal(ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation
- == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1,
- "Only frequency resource allocation type 1 is currently supported\n");
- dci_pdu_rel15->frequency_domain_assignment.val =
- PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw);
- // time domain assignment
- dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment;
- // mcs
- dci_pdu_rel15->mcs = pusch_pdu->mcs_index;
- // tpc command for pusch
- dci_pdu_rel15->tpc = tpc;
+ // bwp indicator as per table 7.3.1.1.2-1 in 38.212
+ dci_pdu_rel15->bwp_indicator.val = n_ubwp < 4 ? bwp_id : bwp_id - 1;
// SRS resource indicator
if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) {
AssertFatal(*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook,
@@ -771,10 +546,8 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,
}
LOG_D(MAC,
- "%s() ULDCI type 0 payload: PDCCH CCEIndex %d, freq_alloc %d, "
- "time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n",
+ "%s() ULDCI type 0 payload: freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n",
__func__,
- pdcch_pdu_rel15->dci_pdu.CceIndex[pdcch_pdu_rel15->numDlDci],
dci_pdu_rel15->frequency_domain_assignment.val,
dci_pdu_rel15->time_domain_assignment.val,
dci_pdu_rel15->frequency_hopping_flag.val,
@@ -784,15 +557,12 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,
dci_pdu_rel15->rv);
}
-void nr_configure_pdcch(gNB_MAC_INST *nr_mac,
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
- uint16_t rnti,
+void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
NR_ServingCellConfigCommon_t *scc,
- NR_BWP_Downlink_t *bwp,
- uint8_t aggregation_level,
- int CCEIndex) {
+ NR_BWP_Downlink_t *bwp)
+{
if (bwp) { // This is not the InitialBWP
pdcch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
@@ -847,27 +617,6 @@ void nr_configure_pdcch(gNB_MAC_INST *nr_mac,
//precoderGranularity
pdcch_pdu->precoderGranularity = coreset->precoderGranularity;
-
- pdcch_pdu->dci_pdu.RNTI[pdcch_pdu->numDlDci]=rnti;
-
- if (coreset->pdcch_DMRS_ScramblingID != NULL &&
- ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
- pdcch_pdu->dci_pdu.ScramblingId[pdcch_pdu->numDlDci] = *coreset->pdcch_DMRS_ScramblingID;
- pdcch_pdu->dci_pdu.ScramblingRNTI[pdcch_pdu->numDlDci]=rnti;
- }
- else {
- pdcch_pdu->dci_pdu.ScramblingId[pdcch_pdu->numDlDci] = *scc->physCellId;
- pdcch_pdu->dci_pdu.ScramblingRNTI[pdcch_pdu->numDlDci]=0;
- }
-
- pdcch_pdu->dci_pdu.AggregationLevel[pdcch_pdu->numDlDci] = aggregation_level;
- pdcch_pdu->dci_pdu.CceIndex[pdcch_pdu->numDlDci] = CCEIndex;
-
- if (ss->searchSpaceType->choice.ue_Specific->dci_Formats==NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_0_And_1_0)
- pdcch_pdu->dci_pdu.beta_PDCCH_1_0[pdcch_pdu->numDlDci]=0;
-
- pdcch_pdu->dci_pdu.powerControlOffsetSS[pdcch_pdu->numDlDci]=1;
- pdcch_pdu->numDlDci++;
}
else { // this is for InitialBWP
AssertFatal(1==0,"Fill in InitialBWP PDCCH configuration\n");
@@ -1084,7 +833,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
}
-void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup,
+void prepare_dci(const NR_CellGroupConfig_t *secondaryCellGroup,
dci_pdu_rel15_t *dci_pdu_rel15,
nr_dci_format_t format,
int bwp_id) {
@@ -1160,592 +909,506 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup,
}
-void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc,
- NR_CellGroupConfig_t *secondaryCellGroup,
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
+void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc,
+ const NR_CellGroupConfig_t *secondaryCellGroup,
+ nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu,
dci_pdu_rel15_t *dci_pdu_rel15,
- int *dci_formats,
- int *rnti_types,
+ int dci_format,
+ int rnti_type,
int N_RB,
int bwp_id) {
+ uint8_t fsize = 0, pos = 0;
- uint8_t fsize=0, pos=0;
+ uint64_t *dci_pdu = (uint64_t *)pdcch_dci_pdu->Payload;
+ int dci_size = nr_dci_size(scc, secondaryCellGroup, dci_pdu_rel15, dci_format, rnti_type, N_RB, bwp_id);
+ pdcch_dci_pdu->PayloadSizeBits = dci_size;
+ AssertFatal(dci_size <= 64, "DCI sizes above 64 bits not yet supported");
- for (int d=0;dnumDlDci;d++) {
+ if (dci_format == NR_DL_DCI_FORMAT_1_1 || dci_format == NR_UL_DCI_FORMAT_0_1)
+ prepare_dci(secondaryCellGroup, dci_pdu_rel15, dci_format, bwp_id);
- uint64_t *dci_pdu = (uint64_t *)pdcch_pdu_rel15->dci_pdu.Payload[d];
- int dci_size = nr_dci_size(scc,secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],rnti_types[d],N_RB,bwp_id);
- pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d] = dci_size;
- AssertFatal(pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d]<=64, "DCI sizes above 64 bits not yet supported");
-
- if(dci_formats[d]==NR_DL_DCI_FORMAT_1_1 || dci_formats[d]==NR_UL_DCI_FORMAT_0_1)
- prepare_dci(secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],bwp_id);
-
- /// Payload generation
- switch(dci_formats[d]) {
- case NR_DL_DCI_FORMAT_1_0:
- switch(rnti_types[d]) {
- case NR_RNTI_RA:
- // Freq domain assignment
- fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
- pos=fsize;
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,N_RB,dci_size-pos,*dci_pdu);
- // Time domain assignment
- pos+=4;
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val&0xf) << (dci_size-pos));
- LOG_D(MAC,"time-domain assignment %d (3 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu);
- // VRB to PRB mapping
-
- pos++;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&0x1)<<(dci_size-pos);
- LOG_D(MAC,"vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,dci_size-pos,*dci_pdu);
- // MCS
- pos+=5;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos);
+ /// Payload generation
+ switch (dci_format) {
+ case NR_DL_DCI_FORMAT_1_0:
+ switch (rnti_type) {
+ case NR_RNTI_RA:
+ // Freq domain assignment
+ fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
+ pos = fsize;
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos));
+ LOG_D(MAC,
+ "frequency-domain assignment %d (%d bits) N_RB_BWP %d=> %d (0x%lx)\n",
+ dci_pdu_rel15->frequency_domain_assignment.val,
+ fsize,
+ N_RB,
+ dci_size - pos,
+ *dci_pdu);
+ // Time domain assignment
+ pos += 4;
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos));
+ LOG_D(MAC,
+ "time-domain assignment %d (3 bits)=> %d (0x%lx)\n",
+ dci_pdu_rel15->time_domain_assignment.val,
+ dci_size - pos,
+ *dci_pdu);
+ // VRB to PRB mapping
+ pos++;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 0x1) << (dci_size - pos);
+ LOG_D(MAC,
+ "vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n",
+ dci_pdu_rel15->vrb_to_prb_mapping.val,
+ dci_size - pos,
+ *dci_pdu);
+ // MCS
+ pos += 5;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
#ifdef DEBUG_FILL_DCI
- LOG_I(MAC,"mcs %d (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu);
+ LOG_I(MAC, "mcs %d (5 bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, dci_size - pos, *dci_pdu);
#endif
- // TB scaling
- pos+=2;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->tb_scaling&0x3)<<(dci_size-pos);
+ // TB scaling
+ pos += 2;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->tb_scaling & 0x3) << (dci_size - pos);
#ifdef DEBUG_FILL_DCI
- LOG_I(MAC,"tb_scaling %d (2 bits)=> %d (0x%lx)\n",dci_pdu_rel15->tb_scaling,dci_size-pos,*dci_pdu);
+ LOG_I(MAC, "tb_scaling %d (2 bits)=> %d (0x%lx)\n", dci_pdu_rel15->tb_scaling, dci_size - pos, *dci_pdu);
#endif
- break;
-
- case NR_RNTI_C:
-
- // indicating a DL DCI format 1bit
- pos++;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos);
- LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu);
-
- // Freq domain assignment (275rb >> fsize = 16)
- fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
- pos+=fsize;
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu);
-
- uint16_t is_ra = 1;
- for (int i=0; ifrequency_domain_assignment.val>>i)&1)) {
- is_ra = 0;
- break;
- }
- if (is_ra) //fsize are all 1 38.212 p86
- {
- // ra_preamble_index 6 bits
- pos+=6;
- *dci_pdu |= ((dci_pdu_rel15->ra_preamble_index&0x3f)<<(dci_size-pos));
-
- // UL/SUL indicator 1 bit
- pos++;
- *dci_pdu |= (dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos);
-
- // SS/PBCH index 6 bits
- pos+=6;
- *dci_pdu |= ((dci_pdu_rel15->ss_pbch_index&0x3f)<<(dci_size-pos));
-
- // prach_mask_index 4 bits
- pos+=4;
- *dci_pdu |= ((dci_pdu_rel15->prach_mask_index&0xf)<<(dci_size-pos));
-
- } //end if
-
- else {
-
- // Time domain assignment 4bit
-
- pos+=4;
- *dci_pdu |= ((dci_pdu_rel15->time_domain_assignment.val&0xf) << (dci_size-pos));
- LOG_D(MAC,"Time domain assignment %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,4,dci_size-pos,*dci_pdu);
-
- // VRB to PRB mapping 1bit
- pos++;
- *dci_pdu |= (dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos);
- LOG_D(MAC,"VRB to PRB %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,1,dci_size-pos,*dci_pdu);
-
- // MCS 5bit //bit over 32, so dci_pdu ++
- pos+=5;
- *dci_pdu |= (dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos);
- LOG_D(MAC,"MCS %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,5,dci_size-pos,*dci_pdu);
-
- // New data indicator 1bit
- pos++;
- *dci_pdu |= (dci_pdu_rel15->ndi&1)<<(dci_size-pos);
- LOG_D(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu);
-
- // Redundancy version 2bit
- pos+=2;
- *dci_pdu |= (dci_pdu_rel15->rv&0x3)<<(dci_size-pos);
- LOG_D(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu);
-
- // HARQ process number 4bit
- pos+=4;
- *dci_pdu |= ((dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos));
- LOG_D(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu);
-
- // Downlink assignment index 2bit
- pos+=2;
- *dci_pdu |= ((dci_pdu_rel15->dai[0].val&3)<<(dci_size-pos));
- LOG_D(MAC,"DAI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->dai[0].val,2,dci_size-pos,*dci_pdu);
-
- // TPC command for scheduled PUCCH 2bit
- pos+=2;
- *dci_pdu |= ((dci_pdu_rel15->tpc&3)<<(dci_size-pos));
- LOG_D(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu);
-
- // PUCCH resource indicator 3bit
- pos+=3;
- *dci_pdu |= ((dci_pdu_rel15->pucch_resource_indicator&0x7)<<(dci_size-pos));
- LOG_D(MAC,"PUCCH RI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pucch_resource_indicator,3,dci_size-pos,*dci_pdu);
-
- // PDSCH-to-HARQ_feedback timing indicator 3bit
- pos+=3;
- *dci_pdu |= ((dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val&0x7)<<(dci_size-pos));
- LOG_D(MAC,"PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val,3,dci_size-pos,*dci_pdu);
-
- } //end else
- break;
-
- case NR_RNTI_P:
-
- // Short Messages Indicator – 2 bits
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator>>(1-i))&1)<<(dci_size-pos++);
- // Short Messages – 8 bits
- for (int i=0; i<8; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages>>(7-i))&1)<<(dci_size-pos++);
- // Freq domain assignment 0-16 bit
- fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
- for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++);
- // Time domain assignment 4 bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++);
- // VRB to PRB mapping 1 bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++);
- // MCS 5 bit
- for (int i=0; i<5; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++);
-
- // TB scaling 2 bit
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling>>(1-i))&1)<<(dci_size-pos++);
-
-
- break;
-
- case NR_RNTI_SI:
- pos=1;
+ break;
- // Freq domain assignment 0-16 bit
- fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
- for (int i=0; ifrequency_domain_assignment.val>>(fsize-1-i))&1)<<(dci_size-pos++);
-
- // Time domain assignment 4 bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++);
-
- // VRB to PRB mapping 1 bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++);
-
- // MCS 5bit //bit over 32, so dci_pdu ++
- for (int i=0; i<5; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++);
-
- // Redundancy version 2 bit
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++);
-
- // System information indicator 1bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->system_info_indicator&1)<<(dci_size-pos++);
-
- // reserved 15 bits
-
- LOG_D(PHY,"dci_size = %i\n", dci_size);
- LOG_D(PHY,"fsize = %i\n", fsize);
- LOG_D(PHY,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
- LOG_D(PHY,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
- LOG_D(PHY,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val);
- LOG_D(PHY,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
- LOG_D(PHY,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
- LOG_D(PHY,"dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator);
-
- break;
-
- case NR_RNTI_TC:
- // indicating a DL DCI format 1bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++);
- // Freq domain assignment 0-16 bit
- fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
- for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++);
- // Time domain assignment 4 bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++);
- // VRB to PRB mapping 1 bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++);
- // MCS 5bit //bit over 32, so dci_pdu ++
- for (int i=0; i<5; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++);
- // New data indicator 1bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++);
- // Redundancy version 2bit
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++);
- // HARQ process number 4bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++);
-
- // Downlink assignment index – 2 bits
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->dai[0].val>>(1-i))&1)<<(dci_size-pos++);
-
- // TPC command for scheduled PUCCH – 2 bits
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++);
-
-
- // LOG_D(MAC, "DCI PDU: [0]->0x%08llx \t [1]->0x%08llx \t [2]->0x%08llx \t [3]->0x%08llx\n",
- // dci_pdu[0], dci_pdu[1], dci_pdu[2], dci_pdu[3]);
-
-
- // PDSCH-to-HARQ_feedback timing indicator – 3 bits
- for (int i=0; i<3; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val>>(2-i))&1)<<(dci_size-pos++);
-
- break;
+ case NR_RNTI_C:
+ // indicating a DL DCI format 1bit
+ pos++;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos);
+ LOG_D(MAC,
+ "Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",
+ dci_pdu_rel15->format_indicator,
+ 1,
+ N_RB,
+ dci_size - pos,
+ *dci_pdu);
+ // Freq domain assignment (275rb >> fsize = 16)
+ fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
+ pos += fsize;
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos));
+ LOG_D(MAC,
+ "Freq domain assignment %d (%d bits)=> %d (0x%lx)\n",
+ dci_pdu_rel15->frequency_domain_assignment.val,
+ fsize,
+ dci_size - pos,
+ *dci_pdu);
+ uint16_t is_ra = 1;
+ for (int i = 0; i < fsize; i++) {
+ if (!((dci_pdu_rel15->frequency_domain_assignment.val >> i) & 1)) {
+ is_ra = 0;
+ break;
+ }
}
- break;
-
- case NR_UL_DCI_FORMAT_0_0:
- switch(rnti_types[d])
- {
- case NR_RNTI_C:
- // indicating a DL DCI format 1bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++);
- // Freq domain assignment max 16 bit
- fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
- for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++);
- // Time domain assignment 4bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++);
- // Frequency hopping flag – 1 bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&1)<<(dci_size-pos++);
- // MCS 5 bit
- for (int i=0; i<5; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++);
- // New data indicator 1bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++);
- // Redundancy version 2bit
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++);
- // HARQ process number 4bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++);
-
- // TPC command for scheduled PUSCH – 2 bits
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++);
-
- // Padding bits
- for(int a = pos;a<32;a++)
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding&1)<<(dci_size-pos++);
-
- // UL/SUL indicator – 1 bit
- /* commented for now (RK): need to get this from BWP descriptor
- if (cfg->pucch_config.pucch_GroupHopping.value)
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++);
- */
- break;
-
- case NFAPI_NR_RNTI_TC:
-
- // indicating a DL DCI format 1bit
- *dci_pdu |= (dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++);
- // Freq domain assignment max 16 bit
- fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) );
- for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++);
- // Time domain assignment 4bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++);
- // Frequency hopping flag – 1 bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&1)<<(dci_size-pos++);
- // MCS 5 bit
- for (int i=0; i<5; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++);
- // New data indicator 1bit
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++);
- // Redundancy version 2bit
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++);
- // HARQ process number 4bit
- for (int i=0; i<4; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++);
-
- // TPC command for scheduled PUSCH – 2 bits
- for (int i=0; i<2; i++)
- *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++);
-
- // Padding bits
- for(int a = pos;a<32;a++)
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding&1)<<(dci_size-pos++);
-
- // UL/SUL indicator – 1 bit
- /*
- commented for now (RK): need to get this information from BWP descriptor
- if (cfg->pucch_config.pucch_GroupHopping.value)
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++);
- */
- break;
-
- }
+ if (is_ra) { // fsize are all 1 38.212 p86
+ // ra_preamble_index 6 bits
+ pos += 6;
+ *dci_pdu |= ((dci_pdu_rel15->ra_preamble_index & 0x3f) << (dci_size - pos));
+ // UL/SUL indicator 1 bit
+ pos++;
+ *dci_pdu |= (dci_pdu_rel15->ul_sul_indicator.val & 1) << (dci_size - pos);
+ // SS/PBCH index 6 bits
+ pos += 6;
+ *dci_pdu |= ((dci_pdu_rel15->ss_pbch_index & 0x3f) << (dci_size - pos));
+ // prach_mask_index 4 bits
+ pos += 4;
+ *dci_pdu |= ((dci_pdu_rel15->prach_mask_index & 0xf) << (dci_size - pos));
+ } else {
+ // Time domain assignment 4bit
+ pos += 4;
+ *dci_pdu |= ((dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos));
+ LOG_D(MAC,
+ "Time domain assignment %d (%d bits)=> %d (0x%lx)\n",
+ dci_pdu_rel15->time_domain_assignment.val,
+ 4,
+ dci_size - pos,
+ *dci_pdu);
+ // VRB to PRB mapping 1bit
+ pos++;
+ *dci_pdu |= (dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos);
+ LOG_D(MAC,
+ "VRB to PRB %d (%d bits)=> %d (0x%lx)\n",
+ dci_pdu_rel15->vrb_to_prb_mapping.val,
+ 1,
+ dci_size - pos,
+ *dci_pdu);
+ // MCS 5bit //bit over 32, so dci_pdu ++
+ pos += 5;
+ *dci_pdu |= (dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
+ LOG_D(MAC, "MCS %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, 5, dci_size - pos, *dci_pdu);
+ // New data indicator 1bit
+ pos++;
+ *dci_pdu |= (dci_pdu_rel15->ndi & 1) << (dci_size - pos);
+ LOG_D(MAC, "NDI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->ndi, 1, dci_size - pos, *dci_pdu);
+ // Redundancy version 2bit
+ pos += 2;
+ *dci_pdu |= (dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
+ LOG_D(MAC, "RV %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->rv, 2, dci_size - pos, *dci_pdu);
+ // HARQ process number 4bit
+ pos += 4;
+ *dci_pdu |= ((dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos));
+ LOG_D(MAC, "HARQ_PID %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->harq_pid, 4, dci_size - pos, *dci_pdu);
+ // Downlink assignment index 2bit
+ pos += 2;
+ *dci_pdu |= ((dci_pdu_rel15->dai[0].val & 3) << (dci_size - pos));
+ LOG_D(MAC, "DAI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->dai[0].val, 2, dci_size - pos, *dci_pdu);
+ // TPC command for scheduled PUCCH 2bit
+ pos += 2;
+ *dci_pdu |= ((dci_pdu_rel15->tpc & 3) << (dci_size - pos));
+ LOG_D(MAC, "TPC %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->tpc, 2, dci_size - pos, *dci_pdu);
+ // PUCCH resource indicator 3bit
+ pos += 3;
+ *dci_pdu |= ((dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos));
+ LOG_D(MAC,
+ "PUCCH RI %d (%d bits)=> %d (0x%lx)\n",
+ dci_pdu_rel15->pucch_resource_indicator,
+ 3,
+ dci_size - pos,
+ *dci_pdu);
+ // PDSCH-to-HARQ_feedback timing indicator 3bit
+ pos += 3;
+ *dci_pdu |= ((dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & 0x7) << (dci_size - pos));
+ LOG_D(MAC,
+ "PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n",
+ dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val,
+ 3,
+ dci_size - pos,
+ *dci_pdu);
+ } // end else
break;
- case NR_UL_DCI_FORMAT_0_1:
- switch(rnti_types[d])
- {
- case NR_RNTI_C:
- // Indicating a DL DCI format 1bit
- pos=1;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos);
-
- // Carrier indicator
- pos+=dci_pdu_rel15->carrier_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<carrier_indicator.nbits)-1))<<(dci_size-pos);
-
- // UL/SUL Indicator
- pos+=dci_pdu_rel15->ul_sul_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&((1<ul_sul_indicator.nbits)-1))<<(dci_size-pos);
-
- // BWP indicator
- pos+=dci_pdu_rel15->bwp_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<bwp_indicator.nbits)-1))<<(dci_size-pos);
-
- // Frequency domain resource assignment
- pos+=dci_pdu_rel15->frequency_domain_assignment.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<frequency_domain_assignment.nbits)-1)) << (dci_size-pos);
-
- // Time domain resource assignment
- pos+=dci_pdu_rel15->time_domain_assignment.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<time_domain_assignment.nbits)-1)) << (dci_size-pos);
-
- // Frequency hopping
- pos+=dci_pdu_rel15->frequency_hopping_flag.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&((1<frequency_hopping_flag.nbits)-1)) << (dci_size-pos);
-
- // MCS 5bit
- pos+=5;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos);
-
- // New data indicator 1bit
- pos+=1;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos);
-
- // Redundancy version 2bit
- pos+=2;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos);
-
- // HARQ process number 4bit
- pos+=4;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos);
-
- // 1st Downlink assignment index
- pos+=dci_pdu_rel15->dai[0].nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<dai[0].nbits)-1))<<(dci_size-pos);
-
- // 2nd Downlink assignment index
- pos+=dci_pdu_rel15->dai[1].nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val&((1<dai[1].nbits)-1))<<(dci_size-pos);
-
- // TPC command for scheduled PUSCH 2bit
- pos+=2;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos);
-
- // SRS resource indicator
- pos+=dci_pdu_rel15->srs_resource_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val&((1<srs_resource_indicator.nbits)-1))<<(dci_size-pos);
-
- // Precoding info and n. of layers
- pos+=dci_pdu_rel15->precoding_information.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val&((1<precoding_information.nbits)-1))<<(dci_size-pos);
-
- // Antenna ports
- pos+=dci_pdu_rel15->antenna_ports.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<antenna_ports.nbits)-1))<<(dci_size-pos);
-
- // SRS request
- pos+=dci_pdu_rel15->srs_request.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<srs_request.nbits)-1))<<(dci_size-pos);
-
- // CSI request
- pos+=dci_pdu_rel15->csi_request.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val&((1<csi_request.nbits)-1))<<(dci_size-pos);
-
- // CBG transmission information
- pos+=dci_pdu_rel15->cbgti.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<cbgti.nbits)-1))<<(dci_size-pos);
-
- // PTRS DMRS association
- pos+=dci_pdu_rel15->ptrs_dmrs_association.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val&((1<ptrs_dmrs_association.nbits)-1))<<(dci_size-pos);
-
- // Beta offset indicator
- pos+=dci_pdu_rel15->beta_offset_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val&((1<beta_offset_indicator.nbits)-1))<<(dci_size-pos);
-
- // DMRS sequence initialization
- pos+=dci_pdu_rel15->dmrs_sequence_initialization.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&((1<dmrs_sequence_initialization.nbits)-1))<<(dci_size-pos);
-
- // UL-SCH indicator
- pos+=1;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator&0x1)<<(dci_size-pos);
-
- break;
- }
+ case NR_RNTI_P:
+ // Short Messages Indicator – 2 bits
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator >> (1 - i)) & 1) << (dci_size - pos++);
+ // Short Messages – 8 bits
+ for (int i = 0; i < 8; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages >> (7 - i)) & 1) << (dci_size - pos++);
+ // Freq domain assignment 0-16 bit
+ fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
+ for (int i = 0; i < fsize; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
+ // Time domain assignment 4 bit
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
+ // VRB to PRB mapping 1 bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++);
+ // MCS 5 bit
+ for (int i = 0; i < 5; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
+ // TB scaling 2 bit
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling >> (1 - i)) & 1) << (dci_size - pos++);
break;
- case NR_DL_DCI_FORMAT_1_1:
- // Indicating a DL DCI format 1bit
- pos=1;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos);
-
- // Carrier indicator
- pos+=dci_pdu_rel15->carrier_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<carrier_indicator.nbits)-1))<<(dci_size-pos);
-
- // BWP indicator
- pos+=dci_pdu_rel15->bwp_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<bwp_indicator.nbits)-1))<<(dci_size-pos);
-
- // Frequency domain resource assignment
- pos+=dci_pdu_rel15->frequency_domain_assignment.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<frequency_domain_assignment.nbits)-1)) << (dci_size-pos);
-
- // Time domain resource assignment
- pos+=dci_pdu_rel15->time_domain_assignment.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<time_domain_assignment.nbits)-1)) << (dci_size-pos);
-
- // VRB-to-PRB mapping
- pos+=dci_pdu_rel15->vrb_to_prb_mapping.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&((1<vrb_to_prb_mapping.nbits)-1))<<(dci_size-pos);
-
- // PRB bundling size indicator
- pos+=dci_pdu_rel15->prb_bundling_size_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->prb_bundling_size_indicator.val&((1<prb_bundling_size_indicator.nbits)-1))<<(dci_size-pos);
-
- // Rate matching indicator
- pos+=dci_pdu_rel15->rate_matching_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->rate_matching_indicator.val&((1<rate_matching_indicator.nbits)-1))<<(dci_size-pos);
-
- // ZP CSI-RS trigger
- pos+=dci_pdu_rel15->zp_csi_rs_trigger.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->zp_csi_rs_trigger.val&((1<zp_csi_rs_trigger.nbits)-1)) << (dci_size-pos);
-
- //TB1
- // MCS 5bit
- pos+=5;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos);
-
- // New data indicator 1bit
- pos+=1;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos);
-
+ case NR_RNTI_SI:
+ pos = 1;
+ // Freq domain assignment 0-16 bit
+ fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
+ LOG_D(PHY, "fsize = %i\n", fsize);
+ for (int i = 0; i < fsize; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
+ LOG_D(PHY, "dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val);
+ // Time domain assignment 4 bit
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
+ LOG_D(PHY, "dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val);
+ // VRB to PRB mapping 1 bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++);
+ LOG_D(PHY, "dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val);
+ // MCS 5bit //bit over 32, so dci_pdu ++
+ for (int i = 0; i < 5; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
+ LOG_D(PHY, "dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs);
// Redundancy version 2bit
- pos+=2;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos);
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++);
+ LOG_D(PHY, "dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv);
+ // System information indicator 1bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->system_info_indicator&1)<<(dci_size-pos++);
+ LOG_D(PHY, "dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator);
+ break;
- //TB2
- // MCS 5bit
- pos+=dci_pdu_rel15->mcs2.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs2.val&((1<mcs2.nbits)-1))<<(dci_size-pos);
-
+ case NR_RNTI_TC:
+ // indicating a DL DCI format 1bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++);
+ // Freq domain assignment 0-16 bit
+ fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
+ for (int i = 0; i < fsize; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
+ // Time domain assignment 4 bit
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
+ // VRB to PRB mapping 1 bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++);
+ // MCS 5bit //bit over 32, so dci_pdu ++
+ for (int i = 0; i < 5; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
// New data indicator 1bit
- pos+=dci_pdu_rel15->ndi2.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi2.val&((1<ndi2.nbits)-1))<<(dci_size-pos);
-
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++);
// Redundancy version 2bit
- pos+=dci_pdu_rel15->rv2.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv2.val&((1<rv2.nbits)-1))<<(dci_size-pos);
-
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++);
// HARQ process number 4bit
- pos+=4;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos);
-
- // Downlink assignment index
- pos+=dci_pdu_rel15->dai[0].nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<dai[0].nbits)-1))<<(dci_size-pos);
-
- // TPC command for scheduled PUCCH 2bit
- pos+=2;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos);
-
- // PUCCH resource indicator 3bit
- pos+=3;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->pucch_resource_indicator&0x7)<<(dci_size-pos);
-
- // PDSCH-to-HARQ_feedback timing indicator
- pos+=dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val&((1<pdsch_to_harq_feedback_timing_indicator.nbits)-1))<<(dci_size-pos);
-
- // Antenna ports
- pos+=dci_pdu_rel15->antenna_ports.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<antenna_ports.nbits)-1))<<(dci_size-pos);
-
- // TCI
- pos+=dci_pdu_rel15->transmission_configuration_indication.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->transmission_configuration_indication.val&((1<transmission_configuration_indication.nbits)-1))<<(dci_size-pos);
-
- // SRS request
- pos+=dci_pdu_rel15->srs_request.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<srs_request.nbits)-1))<<(dci_size-pos);
-
- // CBG transmission information
- pos+=dci_pdu_rel15->cbgti.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<cbgti.nbits)-1))<<(dci_size-pos);
-
- // CBG flushing out information
- pos+=dci_pdu_rel15->cbgfi.nbits;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgfi.val&((1<cbgfi.nbits)-1))<<(dci_size-pos);
-
- // DMRS sequence init
- pos+=1;
- *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&0x1)<<(dci_size-pos);
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++);
+ // Downlink assignment index – 2 bits
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->dai[0].val >> (1 - i)) & 1) << (dci_size - pos++);
+ // TPC command for scheduled PUCCH – 2 bits
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++);
+ // PDSCH-to-HARQ_feedback timing indicator – 3 bits
+ for (int i = 0; i < 3; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val >> (2 - i)) & 1) << (dci_size - pos++);
+ break;
}
- LOG_D(MAC, "DCI index %d has %d bits and the payload is %lx\n", d, dci_size, *dci_pdu);
+ break;
+
+ case NR_UL_DCI_FORMAT_0_0:
+ switch (rnti_type) {
+ case NR_RNTI_C:
+ // indicating a DL DCI format 1bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++);
+ // Freq domain assignment max 16 bit
+ fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
+ for (int i = 0; i < fsize; i++)
+ *dci_pdu |= ((dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
+ // Time domain assignment 4bit
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
+ // Frequency hopping flag – 1 bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos++);
+ // MCS 5 bit
+ for (int i = 0; i < 5; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
+ // New data indicator 1bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++);
+ // Redundancy version 2bit
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++);
+ // HARQ process number 4bit
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++);
+ // TPC command for scheduled PUSCH – 2 bits
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++);
+ // Padding bits
+ for (int a = pos; a < 32; a++)
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++);
+ // UL/SUL indicator – 1 bit
+ /* commented for now (RK): need to get this from BWP descriptor
+ if (cfg->pucch_config.pucch_GroupHopping.value)
+ *dci_pdu |=
+ ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++);
+ */
+ break;
+
+ case NFAPI_NR_RNTI_TC:
+ // indicating a DL DCI format 1bit
+ *dci_pdu |= (dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++);
+ // Freq domain assignment max 16 bit
+ fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1));
+ for (int i = 0; i < fsize; i++)
+ *dci_pdu |= ((dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++);
+ // Time domain assignment 4bit
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++);
+ // Frequency hopping flag – 1 bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos++);
+ // MCS 5 bit
+ for (int i = 0; i < 5; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++);
+ // New data indicator 1bit
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++);
+ // Redundancy version 2bit
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++);
+ // HARQ process number 4bit
+ for (int i = 0; i < 4; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++);
+ // TPC command for scheduled PUSCH – 2 bits
+ for (int i = 0; i < 2; i++)
+ *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++);
+ // Padding bits
+ for (int a = pos; a < 32; a++)
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++);
+ // UL/SUL indicator – 1 bit
+ /*
+ commented for now (RK): need to get this information from BWP descriptor
+ if (cfg->pucch_config.pucch_GroupHopping.value)
+ *dci_pdu |=
+ ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++);
+ */
+ break;
+ }
+ break;
+
+ case NR_UL_DCI_FORMAT_0_1:
+ switch (rnti_type) {
+ case NR_RNTI_C:
+ // Indicating a DL DCI format 1bit
+ pos = 1;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos);
+ // Carrier indicator
+ pos += dci_pdu_rel15->carrier_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos);
+ // UL/SUL Indicator
+ pos += dci_pdu_rel15->ul_sul_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val & ((1 << dci_pdu_rel15->ul_sul_indicator.nbits) - 1)) << (dci_size - pos);
+ // BWP indicator
+ pos += dci_pdu_rel15->bwp_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos);
+ // Frequency domain resource assignment
+ pos += dci_pdu_rel15->frequency_domain_assignment.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos);
+ // Time domain resource assignment
+ pos += dci_pdu_rel15->time_domain_assignment.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos);
+ // Frequency hopping
+ pos += dci_pdu_rel15->frequency_hopping_flag.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & ((1 << dci_pdu_rel15->frequency_hopping_flag.nbits) - 1)) << (dci_size - pos);
+ // MCS 5bit
+ pos += 5;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
+ // New data indicator 1bit
+ pos += 1;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos);
+ // Redundancy version 2bit
+ pos += 2;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
+ // HARQ process number 4bit
+ pos += 4;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos);
+ // 1st Downlink assignment index
+ pos += dci_pdu_rel15->dai[0].nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos);
+ // 2nd Downlink assignment index
+ pos += dci_pdu_rel15->dai[1].nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val & ((1 << dci_pdu_rel15->dai[1].nbits) - 1)) << (dci_size - pos);
+ // TPC command for scheduled PUSCH 2bit
+ pos += 2;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos);
+ // SRS resource indicator
+ pos += dci_pdu_rel15->srs_resource_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val & ((1 << dci_pdu_rel15->srs_resource_indicator.nbits) - 1)) << (dci_size - pos);
+ // Precoding info and n. of layers
+ pos += dci_pdu_rel15->precoding_information.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val & ((1 << dci_pdu_rel15->precoding_information.nbits) - 1)) << (dci_size - pos);
+ // Antenna ports
+ pos += dci_pdu_rel15->antenna_ports.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos);
+ // SRS request
+ pos += dci_pdu_rel15->srs_request.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos);
+ // CSI request
+ pos += dci_pdu_rel15->csi_request.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val & ((1 << dci_pdu_rel15->csi_request.nbits) - 1)) << (dci_size - pos);
+ // CBG transmission information
+ pos += dci_pdu_rel15->cbgti.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos);
+ // PTRS DMRS association
+ pos += dci_pdu_rel15->ptrs_dmrs_association.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val & ((1 << dci_pdu_rel15->ptrs_dmrs_association.nbits) - 1)) << (dci_size - pos);
+ // Beta offset indicator
+ pos += dci_pdu_rel15->beta_offset_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val & ((1 << dci_pdu_rel15->beta_offset_indicator.nbits) - 1)) << (dci_size - pos);
+ // DMRS sequence initialization
+ pos += dci_pdu_rel15->dmrs_sequence_initialization.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & ((1 << dci_pdu_rel15->dmrs_sequence_initialization.nbits) - 1)) << (dci_size - pos);
+ // UL-SCH indicator
+ pos += 1;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator & 0x1) << (dci_size - pos);
+ break;
+ }
+ break;
+
+ case NR_DL_DCI_FORMAT_1_1:
+ // Indicating a DL DCI format 1bit
+ pos = 1;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos);
+ // Carrier indicator
+ pos += dci_pdu_rel15->carrier_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos);
+ // BWP indicator
+ pos += dci_pdu_rel15->bwp_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos);
+ // Frequency domain resource assignment
+ pos += dci_pdu_rel15->frequency_domain_assignment.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos);
+ // Time domain resource assignment
+ pos += dci_pdu_rel15->time_domain_assignment.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos);
+ // VRB-to-PRB mapping
+ pos += dci_pdu_rel15->vrb_to_prb_mapping.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & ((1 << dci_pdu_rel15->vrb_to_prb_mapping.nbits) - 1)) << (dci_size - pos);
+ // PRB bundling size indicator
+ pos += dci_pdu_rel15->prb_bundling_size_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->prb_bundling_size_indicator.val & ((1 << dci_pdu_rel15->prb_bundling_size_indicator.nbits) - 1)) << (dci_size - pos);
+ // Rate matching indicator
+ pos += dci_pdu_rel15->rate_matching_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->rate_matching_indicator.val & ((1 << dci_pdu_rel15->rate_matching_indicator.nbits) - 1)) << (dci_size - pos);
+ // ZP CSI-RS trigger
+ pos += dci_pdu_rel15->zp_csi_rs_trigger.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->zp_csi_rs_trigger.val & ((1 << dci_pdu_rel15->zp_csi_rs_trigger.nbits) - 1)) << (dci_size - pos);
+ // TB1
+ // MCS 5bit
+ pos += 5;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos);
+ // New data indicator 1bit
+ pos += 1;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos);
+ // Redundancy version 2bit
+ pos += 2;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos);
+ // TB2
+ // MCS 5bit
+ pos += dci_pdu_rel15->mcs2.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs2.val & ((1 << dci_pdu_rel15->mcs2.nbits) - 1)) << (dci_size - pos);
+ // New data indicator 1bit
+ pos += dci_pdu_rel15->ndi2.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi2.val & ((1 << dci_pdu_rel15->ndi2.nbits) - 1)) << (dci_size - pos);
+ // Redundancy version 2bit
+ pos += dci_pdu_rel15->rv2.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv2.val & ((1 << dci_pdu_rel15->rv2.nbits) - 1)) << (dci_size - pos);
+ // HARQ process number 4bit
+ pos += 4;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos);
+ // Downlink assignment index
+ pos += dci_pdu_rel15->dai[0].nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos);
+ // TPC command for scheduled PUCCH 2bit
+ pos += 2;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos);
+ // PUCCH resource indicator 3bit
+ pos += 3;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos);
+ // PDSCH-to-HARQ_feedback timing indicator
+ pos += dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & ((1 << dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits) - 1)) << (dci_size - pos);
+ // Antenna ports
+ pos += dci_pdu_rel15->antenna_ports.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos);
+ // TCI
+ pos += dci_pdu_rel15->transmission_configuration_indication.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->transmission_configuration_indication.val & ((1 << dci_pdu_rel15->transmission_configuration_indication.nbits) - 1)) << (dci_size - pos);
+ // SRS request
+ pos += dci_pdu_rel15->srs_request.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos);
+ // CBG transmission information
+ pos += dci_pdu_rel15->cbgti.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos);
+ // CBG flushing out information
+ pos += dci_pdu_rel15->cbgfi.nbits;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgfi.val & ((1 << dci_pdu_rel15->cbgfi.nbits) - 1)) << (dci_size - pos);
+ // DMRS sequence init
+ pos += 1;
+ *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & 0x1) << (dci_size - pos);
}
+ LOG_D(MAC, "DCI has %d bits and the payload is %lx\n", dci_size, *dci_pdu);
}
-
- /*
- int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space,
- nfapi_nr_coreset_t coreset,
- uint16_t frame,
- uint16_t slot,
- nfapi_nr_config_request_scf_t cfg) {
-
- AssertFatal(search_space.coreset_id==coreset.coreset_id, "Invalid association of coreset(%d) and search space(%d)\n",
- search_space.search_space_id, coreset.coreset_id);
-
- uint8_t is_dci_opportunity=0;
- uint16_t Ks=search_space.slot_monitoring_periodicity;
- uint16_t Os=search_space.slot_monitoring_offset;
- uint8_t Ts=search_space.duration;
-
- if (((frame*get_spf(&cfg) + slot - Os)%Ks)ssb_config.scs_common.value;
@@ -1779,35 +1442,105 @@ int extract_length(int startSymbolAndLength) {
/*
* Dump the UL or DL UE_info into LOG_T(MAC)
*/
-void dump_nr_ue_list(NR_UE_list_t *listP) {
+void dump_nr_list(NR_list_t *listP)
+{
for (int j = listP->head; j >= 0; j = listP->next[j])
- LOG_T(MAC, "DL list node %d => %d\n", j, listP->next[j]);
+ LOG_T(MAC, "NR list node %d => %d\n", j, listP->next[j]);
}
/*
- * Add a UE to NR_UE_list listP
+ * Create a new NR_list
*/
-inline void add_nr_ue_list(NR_UE_list_t *listP, int UE_id) {
+void create_nr_list(NR_list_t *list, int len)
+{
+ list->head = -1;
+ list->next = calloc(len, sizeof(*list->next));
+ AssertFatal(list, "cannot calloc() memory for NR_list_t->next\n");
+ for (int i = 0; i < len; ++i)
+ list->next[i] = -1;
+ list->tail = -1;
+ list->len = len;
+}
+
+/*
+ * Destroy an NR_list
+ */
+void destroy_nr_list(NR_list_t *list)
+{
+ free(list->next);
+}
+
+/*
+ * Add an ID to an NR_list at the end, traversing the whole list. Note:
+ * add_tail_nr_list() is a faster alternative, but this implementation ensures
+ * we do not add an existing ID.
+ */
+void add_nr_list(NR_list_t *listP, int id)
+{
int *cur = &listP->head;
while (*cur >= 0) {
- AssertFatal(*cur != UE_id, "UE_id %d already in NR_UE_list!\n", UE_id);
+ AssertFatal(*cur != id, "id %d already in NR_UE_list!\n", id);
cur = &listP->next[*cur];
}
- *cur = UE_id;
+ *cur = id;
+ if (listP->next[id] < 0)
+ listP->tail = id;
}
/*
- * Remove a UE from NR_UE_list listP
+ * Remove an ID from an NR_list
*/
-static inline void remove_nr_ue_list(NR_UE_list_t *listP, int UE_id) {
+void remove_nr_list(NR_list_t *listP, int id)
+{
int *cur = &listP->head;
- while (*cur != -1 && *cur != UE_id)
+ int *prev = &listP->head;
+ while (*cur != -1 && *cur != id) {
+ prev = cur;
cur = &listP->next[*cur];
- AssertFatal(*cur != -1, "UE %d not found in UE_list\n", UE_id);
+ }
+ AssertFatal(*cur != -1, "ID %d not found in UE_list\n", id);
int *next = &listP->next[*cur];
*cur = listP->next[*cur];
*next = -1;
- return;
+ listP->tail = *prev >= 0 && listP->next[*prev] >= 0 ? listP->tail : *prev;
+}
+
+/*
+ * Add an ID to the tail of the NR_list in O(1). Note that there is
+ * corresponding remove_tail_nr_list(), as we cannot set the tail backwards and
+ * therefore need to go through the whole list (use remove_nr_list())
+ */
+void add_tail_nr_list(NR_list_t *listP, int id)
+{
+ int *last = listP->tail < 0 ? &listP->head : &listP->next[listP->tail];
+ *last = id;
+ listP->next[id] = -1;
+ listP->tail = id;
+}
+
+/*
+ * Add an ID to the front of the NR_list in O(1)
+ */
+void add_front_nr_list(NR_list_t *listP, int id)
+{
+ const int ohead = listP->head;
+ listP->head = id;
+ listP->next[id] = ohead;
+ if (listP->tail < 0)
+ listP->tail = id;
+}
+
+/*
+ * Remove an ID from the front of the NR_list in O(1)
+ */
+void remove_front_nr_list(NR_list_t *listP)
+{
+ AssertFatal(listP->head >= 0, "Nothing to remove\n");
+ const int ohead = listP->head;
+ listP->head = listP->next[ohead];
+ listP->next[ohead] = -1;
+ if (listP->head < 0)
+ listP->tail = -1;
}
int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP)
@@ -1860,20 +1593,35 @@ int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP) {
return -1;
}
-//------------------------------------------------------------------------------
-int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
+int get_nrofHARQ_ProcessesForPDSCH(e_NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH n)
+{
+ switch (n) {
+ case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n2:
+ return 2;
+ case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n4:
+ return 4;
+ case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n6:
+ return 6;
+ case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n10:
+ return 10;
+ case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n12:
+ return 12;
+ case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16:
+ return 16;
+ default:
+ return 8;
+ }
+}
+//------------------------------------------------------------------------------
+int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secondaryCellGroup)
+{
NR_UE_info_t *UE_info = &RC.nrmac[mod_idP]->UE_info;
- NR_COMMON_channels_t *cc = RC.nrmac[mod_idP]->common_channels;
- NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
- int num_slots_ul = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
- if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols>0)
- num_slots_ul++;
- LOG_W(MAC, "[gNB %d] Adding UE with rnti %x (num_UEs %d)\n",
+ LOG_I(MAC, "[gNB %d] Adding UE with rnti %x (num_UEs %d)\n",
mod_idP,
rntiP,
UE_info->num_UEs);
- dump_nr_ue_list(&UE_info->list);
+ dump_nr_list(&UE_info->list);
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
if (UE_info->active[i])
@@ -1883,38 +1631,65 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
UE_info->num_UEs++;
UE_info->active[UE_id] = true;
UE_info->rnti[UE_id] = rntiP;
- add_nr_ue_list(&UE_info->list, UE_id);
+ UE_info->secondaryCellGroup[UE_id] = secondaryCellGroup;
+ add_nr_list(&UE_info->list, UE_id);
+ memset(&UE_info->mac_stats[UE_id], 0, sizeof(NR_mac_stats_t));
set_Y(UE_info->Y[UE_id], rntiP);
- memset((void *) &UE_info->UE_sched_ctrl[UE_id],
- 0,
- sizeof(NR_UE_sched_ctrl_t));
- UE_info->UE_sched_ctrl[UE_id].ta_frame = 0;
- UE_info->UE_sched_ctrl[UE_id].ta_update = 31;
- UE_info->UE_sched_ctrl[UE_id].ta_apply = false;
- UE_info->UE_sched_ctrl[UE_id].ul_rssi = 0;
+ compute_csi_bitlen(secondaryCellGroup, UE_info, UE_id);
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ memset(sched_ctrl, 0, sizeof(*sched_ctrl));
+ sched_ctrl->ta_frame = 0;
+ sched_ctrl->ta_update = 31;
+ sched_ctrl->ta_apply = false;
+ sched_ctrl->ul_rssi = 0;
/* set illegal time domain allocation to force recomputation of all fields */
- UE_info->UE_sched_ctrl[UE_id].pusch_save.time_domain_allocation = -1;
- UE_info->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch **)malloc(num_slots_ul*sizeof(NR_sched_pucch *));
- for (int s=0; sUE_sched_ctrl[UE_id].sched_pucch[s] = (NR_sched_pucch *)malloc(2*sizeof(NR_sched_pucch));
+ sched_ctrl->pusch_save.time_domain_allocation = -1;
+ const NR_ServingCellConfig_t *servingCellConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated;
- for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l],
- 0,
- sizeof(NR_sched_pucch));
- }
+ /* Set default BWPs */
+ const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList;
+ AssertFatal(bwpList->list.count == 1,
+ "downlinkBWP_ToAddModList has %d BWP!\n",
+ bwpList->list.count);
+ const int bwp_id = 1;
+ sched_ctrl->active_bwp = bwpList->list.array[bwp_id - 1];
+ const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList;
+ AssertFatal(ubwpList->list.count == 1,
+ "uplinkBWP_ToAddModList has %d BWP!\n",
+ ubwpList->list.count);
+ sched_ctrl->active_ubwp = ubwpList->list.array[bwp_id - 1];
+
+ /* get Number of HARQ processes for this UE */
+ AssertFatal(servingCellConfig->pdsch_ServingCellConfig->present == NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup,
+ "no pdsch-ServingCellConfig found for UE %d\n",
+ UE_id);
+ const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig->pdsch_ServingCellConfig->choice.setup;
+ const int nrofHARQ = pdsch->nrofHARQ_ProcessesForPDSCH ?
+ get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8;
+ // add all available DL HARQ processes for this UE
+ create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ);
+ for (int harq = 0; harq < nrofHARQ; harq++)
+ add_tail_nr_list(&sched_ctrl->available_dl_harq, harq);
+ create_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ);
+ create_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ);
+
+ // add all available UL HARQ processes for this UE
+ create_nr_list(&sched_ctrl->available_ul_harq, 16);
+ for (int harq = 0; harq < 16; harq++)
+ add_tail_nr_list(&sched_ctrl->available_ul_harq, harq);
+ create_nr_list(&sched_ctrl->feedback_ul_harq, 16);
+ create_nr_list(&sched_ctrl->retrans_ul_harq, 16);
LOG_I(MAC, "gNB %d] Add NR UE_id %d : rnti %x\n",
mod_idP,
UE_id,
rntiP);
- dump_nr_ue_list(&UE_info->list);
+ dump_nr_list(&UE_info->list);
return (UE_id);
}
// printf("MAC: cannot add new UE for rnti %x\n", rntiP);
LOG_E(MAC, "error in add_new_ue(), could not find space in UE_info, Dumping UE list\n");
- dump_nr_ue_list(&UE_info->list);
+ dump_nr_list(&UE_info->list);
return -1;
}
@@ -1942,11 +1717,14 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
UE_info->num_UEs--;
UE_info->active[UE_id] = FALSE;
UE_info->rnti[UE_id] = 0;
- remove_nr_ue_list(&UE_info->list, UE_id);
- free(UE_info->UE_sched_ctrl[UE_id].sched_pucch);
- memset((void *) &UE_info->UE_sched_ctrl[UE_id],
- 0,
- sizeof(NR_UE_sched_ctrl_t));
+ remove_nr_list(&UE_info->list, UE_id);
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ destroy_nr_list(&sched_ctrl->available_dl_harq);
+ destroy_nr_list(&sched_ctrl->feedback_dl_harq);
+ destroy_nr_list(&sched_ctrl->retrans_dl_harq);
+ destroy_nr_list(&sched_ctrl->available_ul_harq);
+ destroy_nr_list(&sched_ctrl->feedback_ul_harq);
+ destroy_nr_list(&sched_ctrl->retrans_ul_harq);
LOG_I(MAC, "[gNB %d] Remove NR UE_id %d : rnti %x\n",
mod_id,
UE_id,
@@ -2024,6 +1802,30 @@ void get_pdsch_to_harq_feedback(int Mod_idP,
}
+bool find_free_CCE(module_id_t module_id,
+ sub_frame_t slot,
+ int UE_id){
+ NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id];
+ uint8_t nr_of_candidates;
+ find_aggregation_candidates(&sched_ctrl->aggregation_level,
+ &nr_of_candidates,
+ sched_ctrl->search_space);
+ const int cid = sched_ctrl->coreset->controlResourceSetId;
+ const uint16_t Y = RC.nrmac[module_id]->UE_info.Y[UE_id][cid][slot];
+ const int m = RC.nrmac[module_id]->UE_info.num_pdcch_cand[UE_id][cid];
+ sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
+ sched_ctrl->active_bwp,
+ sched_ctrl->coreset,
+ sched_ctrl->aggregation_level,
+ Y,
+ m,
+ nr_of_candidates);
+ if (sched_ctrl->cce_index < 0)
+ return false;
+
+ RC.nrmac[module_id]->UE_info.num_pdcch_cand[UE_id][cid]++;
+ return true;
+}
/*void fill_nfapi_coresets_and_searchspaces(NR_CellGroupConfig_t *cg,
nfapi_nr_coreset_t *coreset,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index ec5195ec5b..f0a20d8e6f 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -34,64 +34,72 @@
extern RAN_CONTEXT_t RC;
+void nr_fill_nfapi_pucch(module_id_t mod_id,
+ frame_t frame,
+ sub_frame_t slot,
+ const NR_sched_pucch_t *pucch,
+ int UE_id)
+{
+ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
+
+ nfapi_nr_ul_tti_request_t *future_ul_tti_req =
+ &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot];
+ AssertFatal(future_ul_tti_req->SFN == pucch->frame
+ && future_ul_tti_req->Slot == pucch->ul_slot,
+ "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n",
+ future_ul_tti_req->SFN,
+ future_ul_tti_req->Slot,
+ pucch->frame,
+ pucch->ul_slot);
+ future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
+ future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
+ nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu;
+ memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t));
+ future_ul_tti_req->n_pdus += 1;
+
+ LOG_D(MAC,
+ "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d on res %d\n",
+ frame,
+ slot,
+ pucch->frame,
+ pucch->ul_slot,
+ pucch->sr_flag,
+ pucch->dai_c,
+ pucch->csi_bits,
+ pucch->resource_indicator);
+
+ NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
+ nr_configure_pucch(pucch_pdu,
+ scc,
+ UE_info->UE_sched_ctrl[UE_id].active_ubwp,
+ UE_info->rnti[UE_id],
+ pucch->resource_indicator,
+ pucch->csi_bits,
+ pucch->dai_c,
+ pucch->sr_flag);
+}
+
void nr_schedule_pucch(int Mod_idP,
- int UE_id,
- int nr_ulmix_slots,
frame_t frameP,
sub_frame_t slotP) {
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
- AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id);
+ const NR_list_t *UE_list = &UE_info->list;
- for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l];
+ for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ const int n = sizeof(sched_ctrl->sched_pucch) / sizeof(*sched_ctrl->sched_pucch);
+ for (int i = 0; i < n; i++) {
+ NR_sched_pucch_t *curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[i];
const uint16_t O_ack = curr_pucch->dai_c;
const uint16_t O_csi = curr_pucch->csi_bits;
- const uint8_t O_sr = 0; // no SR in PUCCH implemented for now
+ const uint8_t O_sr = curr_pucch->sr_flag;
if (O_ack + O_csi + O_sr == 0
|| frameP != curr_pucch->frame
|| slotP != curr_pucch->ul_slot)
continue;
- nfapi_nr_ul_tti_request_t *future_ul_tti_req =
- &RC.nrmac[Mod_idP]->UL_tti_req_ahead[0][curr_pucch->ul_slot];
- AssertFatal(future_ul_tti_req->SFN == curr_pucch->frame
- && future_ul_tti_req->Slot == curr_pucch->ul_slot,
- "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n",
- future_ul_tti_req->SFN,
- future_ul_tti_req->Slot,
- curr_pucch->frame,
- curr_pucch->ul_slot);
- future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
- future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
- nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu;
- memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t));
- future_ul_tti_req->n_pdus += 1;
-
- LOG_D(MAC,
- "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d, k %d l %d\n",
- frameP,
- slotP,
- curr_pucch->frame,
- curr_pucch->ul_slot,
- O_sr,
- O_ack,
- O_csi,
- k, l);
-
- NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
- nr_configure_pucch(pucch_pdu,
- scc,
- UE_info->UE_sched_ctrl[UE_id].active_ubwp,
- UE_info->rnti[UE_id],
- curr_pucch->resource_indicator,
- O_csi,
- O_ack,
- O_sr);
-
- memset(&UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
- 0,
- sizeof(NR_sched_pucch));
+ nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id);
+ memset(curr_pucch, 0, sizeof(*curr_pucch));
}
}
}
@@ -172,107 +180,136 @@ void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t
}
-uint16_t nr_get_csi_bitlen(int Mod_idP,
- int UE_id,
- uint8_t csi_report_id) {
-
- uint16_t csi_bitlen =0;
- NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
- CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL;
-
- CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]);
- csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
- CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
- (CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report);
-
- return csi_bitlen;
+uint16_t nr_get_csi_bitlen(const nr_csi_report_t *csi_report)
+{
+ const CRI_SSBRI_RSRP_bitlen_t *bitlen = &csi_report->CSI_report_bitlen[0];
+ return bitlen->cri_ssbri_bitlen * bitlen->nb_ssbri_cri
+ + bitlen->rsrp_bitlen
+ + bitlen->diff_rsrp_bitlen * (bitlen->nb_ssbri_cri - 1) * csi_report->nb_of_csi_ssb_report;
}
void nr_csi_meas_reporting(int Mod_idP,
- int UE_id,
frame_t frame,
- sub_frame_t slot,
- int slots_per_tdd,
- int ul_slots,
- int n_slots_frame) {
+ sub_frame_t slot)
+{
+ NR_ServingCellConfigCommon_t *scc =
+ RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
+ const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
- NR_sched_pucch *curr_pucch;
- NR_PUCCH_ResourceSet_t *pucchresset;
- NR_CSI_ReportConfig_t *csirep;
- NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
- NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
- NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];
- NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
+ 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]) {
+ const NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ const NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
+ AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count > 0,
+ "NO CSI report configuration available");
+ NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
- AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available");
+ for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
+ const NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
- for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
+ AssertFatal(csirep->reportConfigType.choice.periodic,
+ "Only periodic CSI reporting is implemented currently\n");
+ int period, offset;
+ csi_period_offset(csirep, &period, &offset);
+ const int sched_slot = (period + offset) % n_slots_frame;
+ // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
+ // preparation is done in first slot of tdd period
+ if (frame % (period / n_slots_frame) != offset / n_slots_frame)
+ continue;
+ LOG_D(MAC, "CSI in frame %d slot %d\n", frame, sched_slot);
- csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
+ const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
+ const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
+ const int n = pucchresset->resourceList.list.count;
+ int res_index = 0;
+ for (; res_index < n; res_index++)
+ if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource)
+ break;
+ AssertFatal(res_index < n,
+ "CSI resource not found among PUCCH resources\n");
- AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently");
- int period, offset, sched_slot;
- csi_period_offset(csirep,&period,&offset);
- sched_slot = (period+offset)%n_slots_frame;
- // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
- // preparation is done in first slot of tdd period
- if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) {
-
- // we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack)
- curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[(sched_slot%slots_per_tdd)-slots_per_tdd+ul_slots][0];
-
- NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
-
- int found = -1;
- pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
- int n_list = pucchresset->resourceList.list.count;
- for (int i=0; iresourceList.list.array[i] == pucchcsires->pucch_Resource)
- found = i;
- }
- AssertFatal(found>-1,"CSI resource not found among PUCCH resources");
-
- curr_pucch->resource_indicator = found;
-
- n_list = pucch_Config->resourceToAddModList->list.count;
-
- // going through the list of PUCCH resources to find the one indexed by resource_id
- for (int i=0; iresourceToAddModList->list.array[i];
- if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) {
- switch(pucchres->format.present){
- case NR_PUCCH_Resource__format_PR_format2:
- if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
- curr_pucch->simultaneous_harqcsi = false;
- else
- curr_pucch->simultaneous_harqcsi = true;
- break;
- case NR_PUCCH_Resource__format_PR_format3:
- if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
- curr_pucch->simultaneous_harqcsi = false;
- else
- curr_pucch->simultaneous_harqcsi = true;
- break;
- case NR_PUCCH_Resource__format_PR_format4:
- if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
- curr_pucch->simultaneous_harqcsi = false;
- else
- curr_pucch->simultaneous_harqcsi = true;
- break;
- default:
- AssertFatal(1==0,"Invalid PUCCH format type");
- }
- }
- }
- curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size
+ // 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];
+ 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",
+ UE_info->rnti[UE_id]);
curr_pucch->frame = frame;
curr_pucch->ul_slot = sched_slot;
+ curr_pucch->resource_indicator = res_index;
+ curr_pucch->csi_bits +=
+ nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]);
+
+ // going through the list of PUCCH resources to find the one indexed by resource_id
+ uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
+ const int m = pucch_Config->resourceToAddModList->list.count;
+ for (int j = 0; j < m; j++) {
+ NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j];
+ if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index])
+ continue;
+ int start = pucchres->startingPRB;
+ int len = 1;
+ uint64_t mask = 0;
+ switch(pucchres->format.present){
+ case NR_PUCCH_Resource__format_PR_format2:
+ len = pucchres->format.choice.format2->nrofPRBs;
+ mask = ((1 << pucchres->format.choice.format2->nrofSymbols) - 1) << pucchres->format.choice.format2->startingSymbolIndex;
+ curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI;
+ break;
+ case NR_PUCCH_Resource__format_PR_format3:
+ len = pucchres->format.choice.format3->nrofPRBs;
+ mask = ((1 << pucchres->format.choice.format3->nrofSymbols) - 1) << pucchres->format.choice.format3->startingSymbolIndex;
+ curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI;
+ break;
+ case NR_PUCCH_Resource__format_PR_format4:
+ mask = ((1 << pucchres->format.choice.format4->nrofSymbols) - 1) << pucchres->format.choice.format4->startingSymbolIndex;
+ curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI;
+ break;
+ default:
+ AssertFatal(0, "Invalid PUCCH format type\n");
+ }
+ // verify resources are free
+ for (int i = start; i < start + len; ++i) {
+ vrb_map_UL[i] |= mask;
+ }
+ AssertFatal(!curr_pucch->simultaneous_harqcsi,
+ "UE %04x has simultaneous HARQ/CSI configured, but we don't support that\n",
+ UE_info->rnti[UE_id]);
+ }
}
}
}
+static void handle_dl_harq(module_id_t mod_id,
+ int UE_id,
+ int8_t harq_pid,
+ bool success)
+{
+ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
+ NR_UE_harq_t *harq = &UE_info->UE_sched_ctrl[UE_id].harq_processes[harq_pid];
+ harq->feedback_slot = -1;
+ harq->is_waiting = false;
+ if (success) {
+ add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid);
+ harq->round = 0;
+ harq->ndi ^= 1;
+ } else if (harq->round == MAX_HARQ_ROUNDS) {
+ add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid);
+ harq->round = 0;
+ harq->ndi ^= 1;
+ NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
+ stats->dlsch_errors++;
+ LOG_D(MAC, "retransmission error for UE %d (total %d)\n", UE_id, stats->dlsch_errors);
+ } else {
+ add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].retrans_dl_harq, harq_pid);
+ harq->round++;
+ }
+}
void handle_nr_uci_pucch_0_1(module_id_t mod_id,
frame_t frame,
@@ -292,50 +329,36 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
uci_01->ul_cqi,
30);
- // TODO
- int max_harq_rounds = 4; // TODO define macro
+ 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)) {
- // handle harq
- int harq_idx_s = 0;
-
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
- // search for the right harq process
- for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
- // if the gNB received ack with a good confidence
- if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
- sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
- if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) &&
- (uci_01->harq->harq_confidence_level == 0)) {
- // toggle NDI and reset round
- sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
- sched_ctrl->harq_processes[harq_idx].round = 0;
- }
- else
- sched_ctrl->harq_processes[harq_idx].round++;
- sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
- harq_idx_s = harq_idx + 1;
- // if the max harq rounds was reached
- if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
- sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
- sched_ctrl->harq_processes[harq_idx].round = 0;
- UE_info->mac_stats[UE_id].dlsch_errors++;
- }
- break;
- }
- // if feedback slot processing is aborted
- else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
- && (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
- && sched_ctrl->harq_processes[harq_idx].is_waiting) {
- sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
- sched_ctrl->harq_processes[harq_idx].round++;
- if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
- sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
- sched_ctrl->harq_processes[harq_idx].round = 0;
- }
- sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
- }
+ const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value;
+ const uint8_t harq_confidence = uci_01->harq->harq_confidence_level;
+ const int feedback_slot = (slot - 1 + num_slots) % num_slots;
+ /* In case of realtime problems: we can only identify a HARQ process by
+ * timing. If the HARQ process's feedback_slot is not the one we
+ * expected, we assume that processing has been aborted and we need to
+ * skip this HARQ process, which is what happens in the loop below. If
+ * you don't experience real-time problems, you might simply revert the
+ * commit that introduced these changes. */
+ int8_t pid = sched_ctrl->feedback_dl_harq.head;
+ DevAssert(pid >= 0);
+ while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) {
+ LOG_W(MAC,
+ "expected feedback slot %d, but found %d instead\n",
+ sched_ctrl->harq_processes[pid].feedback_slot,
+ feedback_slot);
+ remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
+ handle_dl_harq(mod_id, UE_id, pid, 0);
+ pid = sched_ctrl->feedback_dl_harq.head;
+ DevAssert(pid >= 0);
}
+ remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
+ NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
+ DevAssert(harq->is_waiting);
+ handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
}
}
}
@@ -358,130 +381,243 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
uci_234->ul_cqi,
30);
- // TODO
- int max_harq_rounds = 4; // TODO define macro
+ 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) {
- int harq_idx_s = 0;
- int acknack;
-
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
- acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01;
- for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) {
- // if the gNB received ack with a good confidence or if the max harq rounds was reached
- if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
- // TODO add some confidence level for when there is no CRC
- sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
- if ((uci_234->harq.harq_crc != 1) && acknack) {
- // toggle NDI and reset round
- sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
- sched_ctrl->harq_processes[harq_idx].round = 0;
- }
- else
- sched_ctrl->harq_processes[harq_idx].round++;
- sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
- harq_idx_s = harq_idx + 1;
- // if the max harq rounds was reached
- if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
- sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
- sched_ctrl->harq_processes[harq_idx].round = 0;
- UE_info->mac_stats[UE_id].dlsch_errors++;
- }
- break;
- }
- // if feedback slot processing is aborted
- else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
- && (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
- && sched_ctrl->harq_processes[harq_idx].is_waiting) {
- sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
- sched_ctrl->harq_processes[harq_idx].round++;
- if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
- sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
- sched_ctrl->harq_processes[harq_idx].round = 0;
- }
- sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
- }
+ const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01;
+ const int feedback_slot = (slot - 1 + num_slots) % num_slots;
+ /* In case of realtime problems: we can only identify a HARQ process by
+ * timing. If the HARQ process's feedback_slot is not the one we
+ * expected, we assume that processing has been aborted and we need to
+ * skip this HARQ process, which is what happens in the loop below. If
+ * you don't experience real-time problems, you might simply revert the
+ * commit that introduced these changes. */
+ int8_t pid = sched_ctrl->feedback_dl_harq.head;
+ DevAssert(pid >= 0);
+ while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) {
+ LOG_W(MAC,
+ "expected feedback slot %d, but found %d instead\n",
+ sched_ctrl->harq_processes[pid].feedback_slot,
+ feedback_slot);
+ remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
+ handle_dl_harq(mod_id, UE_id, pid, 0);
+ pid = sched_ctrl->feedback_dl_harq.head;
+ DevAssert(pid >= 0);
}
+ remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
+ NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
+ DevAssert(harq->is_waiting);
+ handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack);
}
}
}
// function to update pucch scheduling parameters in UE list when a USS DL is scheduled
-void nr_acknack_scheduling(int Mod_idP,
+bool nr_acknack_scheduling(int mod_id,
int UE_id,
- frame_t frameP,
- sub_frame_t slotP,
- int slots_per_tdd,
- int *pucch_id,
- int *pucch_occ) {
+ frame_t frame,
+ sub_frame_t slot)
+{
+ const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
+ const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
+ const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
+ const int nr_ulmix_slots = tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols != 0);
+ const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0;
+ const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots;
+ const int first_ul_slot_tdd = tdd->nrofDownlinkSlots + nr_slots_period * (slot / nr_slots_period);
+ const int CC_id = 0;
- NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
- NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
- NR_sched_pucch *curr_pucch;
- int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l;
- uint8_t pdsch_to_harq_feedback[8];
- int found = 0;
- int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
- if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0)
- nr_ulmix_slots++;
+ AssertFatal(slot < first_ul_slot_tdd + (tdd->nrofUplinkSymbols != 0),
+ "cannot handle multiple TDD periods (yet): slot %d first_ul_slot_tdd %d nrofUplinkSlots %ld\n",
+ slot,
+ first_ul_slot_tdd,
+ tdd->nrofUplinkSlots);
- bool csi_pres=false;
- for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0)
- csi_pres=true;
+ /* for the moment, we consider:
+ * * only pucch_sched[0] holds HARQ (and SR)
+ * * 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! */
+ 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,
+ "%s(): csi_bits %d in sched_pucch[0]\n",
+ __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) {
+ /* advance the UL slot information in PUCCH by one so we won't schedule in
+ * the same slot again */
+ const int f = pucch->frame;
+ const int s = pucch->ul_slot;
+ nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id);
+ memset(pucch, 0, sizeof(*pucch));
+ 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];
+ // 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
+ && csi_pucch->ul_slot == pucch->ul_slot) {
+ AssertFatal(!csi_pucch->simultaneous_harqcsi,
+ "%s(): %d.%d cannot handle simultaneous_harqcsi, but found for UE %d\n",
+ __func__,
+ pucch->frame,
+ pucch->ul_slot,
+ UE_id);
+ nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
+ pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f;
+ pucch->ul_slot = (s + 2) % n_slots_frame;
+ }
}
- // As a preference always schedule ack nacks in PUCCH0 (max 2 per slots)
- // Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot
- if (csi_pres)
- max_acknacks=10;
- else
- max_acknacks=2;
+ /* if the UE's next PUCCH occasion is after the possible UL slots (within the
+ * same frame) or wrapped around to the next frame, then we assume there is
+ * no possible PUCCH allocation anymore */
+ if ((pucch->frame == frame
+ && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots))
+ || (pucch->frame == frame + 1))
+ return false;
// this is hardcoded for now as ue specific
NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
- get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback);
+ uint8_t pdsch_to_harq_feedback[8];
+ get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback);
- // for each possible ul or mixed slot
- for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l];
- //if it is possible to schedule acknack in current pucch (no exclusive csi pucch)
- if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) {
- // if there is free room in current pucch structure
- if (curr_pucch->dai_c-1){
- curr_pucch->resource_indicator = pucch_res;
- curr_pucch->frame = frameP;
- // first pucch occasion in first UL or MIXED slot
- first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
- i = 0;
- while (i<8 && found == 0) { // look if timing indicator is among allowed values
- if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
- found = 1;
- if (found == 0) i++;
- }
- if (found == 1) {
- // computing slot in which pucch is scheduled
- curr_pucch->dai_c++;
- curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
- curr_pucch->timing_indicator = i; // index in the list of timing indicators
- *pucch_id = k;
- *pucch_occ = l;
- return;
- }
- }
- }
- }
+ /* there is a scheduled SR or HARQ. Check whether we can use it for this
+ * ACKNACK */
+ if (pucch->sr_flag + pucch->dai_c > 0) {
+ /* this UE already has a PUCCH occasion */
+ DevAssert(pucch->frame == frame);
+
+ // Find the right timing_indicator value.
+ int i = 0;
+ while (i < 8) {
+ if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot)
+ break;
+ ++i;
+ }
+ if (i >= 8) {
+ // we cannot reach this timing anymore, allocate and try again
+ const int f = pucch->frame;
+ const int s = pucch->ul_slot;
+ const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
+ nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id);
+ memset(pucch, 0, sizeof(*pucch));
+ pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
+ pucch->ul_slot = (s + 1) % n_slots_frame;
+ return nr_acknack_scheduling(mod_id, UE_id, frame, slot);
+ }
+
+ pucch->timing_indicator = i;
+ pucch->dai_c++;
+ // retain old resource indicator, and we are good
+ return true;
+ }
+
+ /* 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(frame + 1 != pucch->frame,
+ "frame wrap around not handled in %s() yet\n",
+ __func__);
+ pucch->frame = frame;
+ 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;
}
}
- AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n");
+
+ // advance ul_slot if it is not reachable by UE
+ pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]);
+
+ // Find the right timing_indicator value.
+ int i = 0;
+ while (i < 8) {
+ if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot)
+ break;
+ ++i;
+ }
+ if (i >= 8) {
+ LOG_W(MAC,
+ "%4d.%2d could not find pdsch_to_harq_feedback for UE %d: earliest "
+ "ack slot %d\n",
+ frame,
+ slot,
+ UE_id,
+ pucch->ul_slot);
+ return false;
+ }
+ pucch->timing_indicator = i; // index in the list of timing indicators
+
+ pucch->dai_c++;
+ const int pucch_res = pucch_index_used[pucch->ul_slot];
+ pucch->resource_indicator = pucch_res;
+ pucch_index_used[pucch->ul_slot] += 1;
+ AssertFatal(pucch_index_used[pucch->ul_slot] <= n_res,
+ "UE %d in %4d.%2d: pucch_index_used is %d (%d available)\n",
+ UE_id,
+ pucch->frame,
+ pucch->ul_slot,
+ pucch_index_used[pucch->ul_slot],
+ n_res);
+
+ /* verify that at that slot and symbol, resources are free. We only do this
+ * for initialCyclicShift 0 (we assume it always has that one), so other
+ * initialCyclicShifts can overlap with ICS 0!*/
+ const NR_PUCCH_Resource_t *resource =
+ pucch_Config->resourceToAddModList->list.array[pucch_res];
+ DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
+ if (resource->format.choice.format0->initialCyclicShift == 0) {
+ uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE];
+ const uint16_t symb = 1 << resource->format.choice.format0->startingSymbolIndex;
+ AssertFatal((vrb_map_UL[resource->startingPRB] & symb) == 0,
+ "symbol %x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d\n",
+ symb, resource->startingPRB, pucch->ul_slot);
+ vrb_map_UL[resource->startingPRB] |= symb;
+ }
+ return true;
}
-void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
+void csi_period_offset(const NR_CSI_ReportConfig_t *csirep,
int *period, int *offset) {
NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present;
@@ -532,24 +668,6 @@ void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
}
}
-
-int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) {
-
- // to be updated later, for now simple implementation
- // use the second allocation just in case there is csi in the first
- // in that case use second resource (for a different symbol) see 9.2 in 38.213
- if (l==1) {
- if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0)
- return -1;
- else
- return 1;
- }
- else
- return 0;
-
-}
-
-
uint16_t compute_pucch_prb_size(uint8_t format,
uint8_t nr_prbs,
uint16_t O_tot,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 51651bd393..90a1811b22 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -33,6 +33,33 @@
#include "executables/softmodem-common.h"
#include "common/utils/nr/nr_common.h"
+//38.321 Table 6.1.3.1-1
+const uint32_t NR_SHORT_BSR_TABLE[32] = {
+ 0, 10, 14, 20, 28, 38, 53, 74,
+ 102, 142, 198, 276, 384, 535, 745, 1038,
+ 1446, 2014, 2806, 3909, 5446, 7587, 10570, 14726,
+20516, 28581, 39818, 55474, 77284, 107669, 150000, 300000
+};
+
+//38.321 Table 6.1.3.1-2
+const uint32_t NR_LONG_BSR_TABLE[256] ={
+ 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26,
+ 28, 30, 32, 34, 36, 38, 40, 43, 46, 49, 52, 55, 59, 62, 66, 71,
+ 75, 80, 85, 91, 97, 103, 110, 117, 124, 132, 141, 150, 160, 170, 181, 193,
+ 205, 218, 233, 248, 264, 281, 299, 318, 339, 361, 384, 409, 436, 464, 494, 526,
+ 560, 597, 635, 677, 720, 767, 817, 870, 926, 987, 1051, 1119, 1191, 1269, 1351, 1439,
+ 1532, 1631, 1737, 1850, 1970, 2098, 2234, 2379, 2533, 2698, 2873, 3059, 3258, 3469, 3694, 3934,
+ 4189, 4461, 4751, 5059, 5387, 5737, 6109, 6506, 6928, 7378, 7857, 8367, 8910, 9488, 10104, 10760,
+ 11458, 12202, 12994, 13838, 14736, 15692, 16711, 17795, 18951, 20181, 21491, 22885, 24371, 25953, 27638, 29431,
+ 31342, 33376, 35543, 37850, 40307, 42923, 45709, 48676, 51836, 55200, 58784, 62599, 66663, 70990, 75598, 80505,
+ 85730, 91295, 97221, 103532, 110252, 117409, 125030, 133146, 141789, 150992, 160793, 171231, 182345, 194182, 206786, 220209,
+ 234503, 249725, 265935, 283197, 301579, 321155, 342002, 364202, 387842, 413018, 439827, 468377, 498780, 531156, 565634, 602350,
+ 641449, 683087, 727427, 774645, 824928, 878475, 935498, 996222, 1060888, 1129752, 1203085, 1281179, 1364342, 1452903, 1547213, 1647644,
+ 1754595, 1868488, 1989774, 2118933, 2256475, 2402946, 2558924, 2725027, 2901912, 3090279, 3290873, 3504487, 3731968, 3974215, 4232186, 4506902,
+ 4799451, 5110989, 5442750, 5796046, 6172275, 6572925, 6999582, 7453933, 7937777, 8453028, 9001725, 9586039, 10208280, 10870913, 11576557, 12328006,
+13128233, 13980403, 14887889, 15854280, 16883401, 17979324, 19146385, 20389201, 21712690, 23122088, 24622972, 26221280, 27923336, 29735875, 31666069, 33721553,
+35910462, 38241455, 40723756, 43367187, 46182206, 49179951, 52372284, 55771835, 59392055, 63247269, 67352729, 71724679, 76380419, 81338368, 162676736, 4294967295
+};
void nr_process_mac_pdu(
module_id_t module_idP,
@@ -51,6 +78,13 @@ void nr_process_mac_pdu(
uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len;
+ NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
+ int UE_id = find_nr_UE_id(module_idP, rnti);
+ if (UE_id == -1) {
+ LOG_E(MAC, "%s() UE_id == -1\n",__func__);
+ return;
+ }
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
// For both DL/UL-SCH
// Except:
// - UL/DL-SCH: fixed-size MAC CE(known by LCID)
@@ -84,6 +118,9 @@ void nr_process_mac_pdu(
LOG_D(MAC, "LCID received at gNB side: %d \n", rx_lcid);
+ unsigned char *ce_ptr;
+ int n_Lcg = 0;
+
switch(rx_lcid){
// MAC CE
@@ -97,32 +134,25 @@ void nr_process_mac_pdu(
case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION:
// 38.321 Ch6.1.3.7
break;
- case UL_SCH_LCID_S_BSR:
- //38.321 section 6.1.3.1
- //fixed length
- mac_ce_len =1;
- /* Extract short BSR value */
- break;
+ case UL_SCH_LCID_S_BSR:
case UL_SCH_LCID_S_TRUNCATED_BSR:
//38.321 section 6.1.3.1
//fixed length
mac_ce_len =1;
- /* Extract short truncated BSR value */
+ /* Extract short BSR value */
+ ce_ptr = &pdu_ptr[mac_subheader_len];
+ NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr;
+ sched_ctrl->estimated_ul_buffer = 0;
+ sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size];
+ LOG_D(MAC, "SHORT BSR, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n",
+ bsr_s->LcgID,
+ bsr_s->Buffer_size,
+ NR_SHORT_BSR_TABLE[bsr_s->Buffer_size],
+ sched_ctrl->estimated_ul_buffer);
break;
case UL_SCH_LCID_L_BSR:
- //38.321 section 6.1.3.1
- //variable length
- mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
- mac_subheader_len = 2;
- if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
- mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
- mac_subheader_len = 3;
- }
- /* Extract long BSR value */
- break;
-
case UL_SCH_LCID_L_TRUNCATED_BSR:
//38.321 section 6.1.3.1
//variable length
@@ -132,9 +162,27 @@ void nr_process_mac_pdu(
mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
mac_subheader_len = 3;
}
- /* Extract long truncated BSR value */
- break;
+ /* Extract long BSR value */
+ ce_ptr = &pdu_ptr[mac_subheader_len];
+ NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr;
+ sched_ctrl->estimated_ul_buffer = 0;
+ n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 +
+ bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0;
+
+ LOG_D(MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n",
+ bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4,
+ bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0);
+
+ for (int n = 0; n < n_Lcg; n++){
+ LOG_D(MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d",
+ n, n_Lcg, pdu_ptr[mac_subheader_len + 1 + n],
+ NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]]);
+ sched_ctrl->estimated_ul_buffer +=
+ NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]];
+ }
+
+ break;
case UL_SCH_LCID_C_RNTI:
//38.321 section 6.1.3.2
@@ -230,17 +278,28 @@ void nr_process_mac_pdu(
1,
NULL);
+ /* Updated estimated buffer when receiving data */
+ if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len)
+ sched_ctrl->estimated_ul_buffer -= mac_sdu_len;
+ else
+ sched_ctrl->estimated_ul_buffer = 0;
+
break;
default:
- return;
- break;
+ LOG_D(MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid);
+ return;
+ break;
}
pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len );
pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len );
if (pdu_len < 0) {
LOG_E(MAC, "%s() residual mac pdu length < 0!, pdu_len: %d\n", __func__, pdu_len);
+ LOG_E(MAC, "MAC PDU ");
+ for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes
+ printf("%02x ", pdu_ptr[i]);
+ printf("\n");
return;
}
}
@@ -259,45 +318,51 @@ void handle_nr_ul_harq(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];
- int max_harq_rounds = 4; // TODO define macro
- uint8_t hrq_id = crc_pdu->harq_id;
- NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id];
- if (cur_harq->state==ACTIVE_SCHED) {
- if (!crc_pdu->tb_crc_status) {
- cur_harq->ndi ^= 1;
- cur_harq->round = 0;
- cur_harq->state = INACTIVE; // passed -> make inactive. can be used by scheduder for next grant
- LOG_D(MAC,
- "Ulharq id %d crc passed for RNTI %04x\n",
- hrq_id,
- crc_pdu->rnti);
- } else {
- cur_harq->round++;
- cur_harq->state = ACTIVE_NOT_SCHED;
- LOG_D(MAC,
- "Ulharq id %d crc failed for RNTI %04x\n",
- hrq_id,
- crc_pdu->rnti);
- }
-
- if (!(cur_harq->roundndi ^= 1;
- cur_harq->state = INACTIVE; // failed after 4 rounds -> make inactive
- cur_harq->round = 0;
- LOG_D(MAC,
- "RNTI %04x: Ulharq id %d crc failed in all rounds\n",
- crc_pdu->rnti,
- hrq_id);
- UE_info->mac_stats[UE_id].ulsch_errors++;
- }
- return;
- } else
+ int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
+ while (crc_pdu->harq_id != harq_pid || harq_pid < 0) {
LOG_W(MAC,
- "Incorrect ULSCH HARQ PID %d or invalid state %d for RNTI %04x "
- "(ignore this warning for RA)\n",
- hrq_id,
- cur_harq->state,
+ "Unexpected ULSCH HARQ PID %d (have %d) for RNTI %04x (ignore this warning for RA)\n",
+ crc_pdu->harq_id,
+ harq_pid,
crc_pdu->rnti);
+ if (harq_pid < 0)
+ return;
+
+ remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
+ sched_ctrl->ul_harq_processes[harq_pid].round++;
+ add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
+ harq_pid = sched_ctrl->feedback_ul_harq.head;
+ }
+ remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
+ NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid];
+ DevAssert(harq->is_waiting);
+ harq->feedback_slot = -1;
+ harq->is_waiting = false;
+ if (!crc_pdu->tb_crc_status) {
+ harq->ndi ^= 1;
+ harq->round = 0;
+ LOG_D(MAC,
+ "Ulharq id %d crc passed for RNTI %04x\n",
+ harq_pid,
+ crc_pdu->rnti);
+ add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
+ } else if (harq->round == MAX_HARQ_ROUNDS) {
+ harq->ndi ^= 1;
+ harq->round = 0;
+ LOG_D(MAC,
+ "RNTI %04x: Ulharq id %d crc failed in all rounds\n",
+ crc_pdu->rnti,
+ harq_pid);
+ UE_info->mac_stats[UE_id].ulsch_errors++;
+ add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
+ } else {
+ harq->round++;
+ LOG_D(MAC,
+ "Ulharq id %d crc failed for RNTI %04x\n",
+ harq_pid,
+ crc_pdu->rnti);
+ add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
+ }
}
/*
@@ -313,25 +378,21 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
const uint16_t timing_advance,
const uint8_t ul_cqi,
const uint16_t rssi){
- int current_rnti = 0, UE_id = -1, harq_pid = 0;
- gNB_MAC_INST *gNB_mac = NULL;
- NR_UE_info_t *UE_info = NULL;
- NR_UE_sched_ctrl_t *UE_scheduling_control = NULL;
+ gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP];
+ NR_UE_info_t *UE_info = &gNB_mac->UE_info;
- current_rnti = rntiP;
- UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti);
- gNB_mac = RC.nrmac[gnb_mod_idP];
- UE_info = &gNB_mac->UE_info;
- int target_snrx10 = gNB_mac->pusch_target_snrx10;
-
- 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));
- }
+ const int current_rnti = rntiP;
+ const int UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti);
+ const int target_snrx10 = gNB_mac->pusch_target_snrx10;
if (UE_id != -1) {
- UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]);
+ NR_UE_sched_ctrl_t *UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id];
+ const int8_t harq_pid = UE_scheduling_control->feedback_ul_harq.head;
+
+ if (sduP)
+ 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(harq_pid),
+ T_BUFFER(sduP, sdu_lenP));
UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP;
LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d\n",
@@ -370,15 +431,30 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
if (sduP != NULL){
LOG_D(MAC, "Received PDU at MAC gNB \n");
+
+ UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
+ if (UE_scheduling_control->sched_ul_bytes < 0)
+ UE_scheduling_control->sched_ul_bytes = 0;
+
nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP);
}
else {
-
+ NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
+ /* reduce sched_ul_bytes when cur_harq->round == 3 */
+ if (cur_harq->round == 3){
+ UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
+ if (UE_scheduling_control->sched_ul_bytes < 0)
+ UE_scheduling_control->sched_ul_bytes = 0;
+ }
}
} else {
if (!sduP) // check that CRC passed
return;
+ 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));
+
/* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3)
* and check the corresponding UE's RNTI match, in which case we activate
* it. */
@@ -395,21 +471,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
current_rnti);
continue;
}
- const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti);
- UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
- compute_csi_bitlen(ra->secondaryCellGroup, UE_info, UE_id);
+ const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->secondaryCellGroup);
UE_info->UE_beam_index[UE_id] = ra->beam_id;
- struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
- AssertFatal(bwpList->list.count == 1,
- "downlinkBWP_ToAddModList has %d BWP!\n",
- bwpList->list.count);
- const int bwp_id = 1;
- UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
- struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList;
- AssertFatal(ubwpList->list.count == 1,
- "uplinkBWP_ToAddModList has %d BWP!\n",
- ubwpList->list.count);
- UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1];
LOG_I(MAC,
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
"adding UE MAC Context UE_id %d/RNTI %04x\n",
@@ -445,30 +508,256 @@ long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) {
return 3;
}
-int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) {
- const uint8_t max_ul_harq_pids = 3; // temp: for testing
- // schedule active harq processes
- for (uint8_t hrq_id = 0; hrq_id < max_ul_harq_pids; hrq_id++) {
- NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id];
- if (cur_harq->state == ACTIVE_NOT_SCHED) {
- LOG_D(MAC, "Found ulharq id %d, scheduling it for retransmission\n", hrq_id);
- return hrq_id;
- }
- }
-
- // schedule new harq processes
- for (uint8_t hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) {
- NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id];
- if (cur_harq->state == INACTIVE) {
- LOG_D(MAC, "Found new ulharq id %d, scheduling it\n", hrq_id);
- return hrq_id;
- }
- }
- LOG_E(MAC, "All UL HARQ processes are busy. Cannot schedule ULSCH\n");
- return -1;
+int next_list_entry_looped(NR_list_t *list, int UE_id)
+{
+ if (UE_id < 0)
+ return list->head;
+ return list->next[UE_id] < 0 ? list->head : list->next[UE_id];
}
-void nr_simple_ulsch_preprocessor(module_id_t module_id,
+float ul_thr_ue[MAX_MOBILES_PER_GNB];
+int bsr0ue = -1;
+void pf_ul(module_id_t module_id,
+ frame_t frame,
+ sub_frame_t slot,
+ int num_slots_per_tdd,
+ NR_list_t *UE_list,
+ int n_rb_sched,
+ uint8_t *rballoc_mask,
+ int max_num_ue) {
+
+ const int CC_id = 0;
+ const int tda = 1;
+ NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon;
+ NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
+ const int min_rb = 5;
+ float coeff_ue[MAX_MOBILES_PER_GNB];
+ // UEs that could be scheduled
+ int ue_array[MAX_MOBILES_PER_GNB];
+ NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB };
+
+ /* Hack: currently, we do not have SR, and need to schedule UEs continuously.
+ * To keep the wasted resources low, we switch UEs to be scheduled in a
+ * round-robin fashion below, and only schedule a UE with BSR=0 if it is the
+ * selected one */
+ bsr0ue = next_list_entry_looped(UE_list, bsr0ue);
+
+ /* Loop UE_list to calculate throughput and coeff */
+ for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+ const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+
+ /* Calculate throughput */
+ const float a = 0.0005f; // corresponds to 200ms window
+ const uint32_t b = UE_info->mac_stats[UE_id].ulsch_current_bytes;
+ ul_thr_ue[UE_id] = (1 - a) * ul_thr_ue[UE_id] + a * b;
+
+ /* Save PUSCH field */
+ /* we want to avoid a lengthy deduction of DMRS and other parameters in
+ * every TTI if we can save it, so check whether dci_format, TDA, or
+ * num_dmrs_cdm_grps_no_data has changed and only then recompute */
+ sched_ctrl->sched_pusch.time_domain_allocation = tda;
+ sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, NR_SearchSpace__searchSpaceType_PR_ue_Specific);
+ sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
+ const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
+ const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
+ const uint8_t num_dmrs_cdm_grps_no_data = 1;
+ NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
+ if (ps->time_domain_allocation != tda
+ || ps->dci_format != dci_format
+ || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
+ nr_save_pusch_fields(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
+
+ /* Check if retransmission is necessary */
+ sched_ctrl->sched_pusch.ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
+ if (sched_ctrl->sched_pusch.ul_harq_pid >= 0) {
+ /* RETRANSMISSION: Allocate retransmission*/
+ /* Find free CCE */
+ bool freeCCE = find_free_CCE(module_id, slot, UE_id);
+ if (!freeCCE) {
+ LOG_D(MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
+ continue;
+ }
+ /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
+ max_num_ue--;
+ if (max_num_ue < 0)
+ return;
+
+ /* Save shced_frame and sched_slot before overwrite by previous PUSCH filed */
+ NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[sched_ctrl->sched_pusch.ul_harq_pid];
+ cur_harq->sched_pusch.frame = sched_ctrl->sched_pusch.frame;
+ cur_harq->sched_pusch.slot = sched_ctrl->sched_pusch.slot;
+ /* Get previous PSUCH filed info */
+ sched_ctrl->sched_pusch = cur_harq->sched_pusch;
+ NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
+ LOG_D(MAC, "%4d.%2d Allocate UL retransmission UE %d/RNTI %04x sched %4d.%2d (%d RBs)\n",
+ frame, slot, UE_id, UE_info->rnti[UE_id],
+ sched_pusch->frame, sched_pusch->slot,
+ sched_pusch->rbSize);
+
+ while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
+ if (rbStart + sched_pusch->rbSize >= bwpSize) {
+ LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
+ UE_id, UE_info->rnti[UE_id]);
+ return;
+ }
+ sched_pusch->rbStart = rbStart;
+ /* no need to recompute the TBS, it will be the same */
+
+ /* Mark the corresponding RBs as used */
+ n_rb_sched -= sched_pusch->rbSize;
+ for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
+ rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
+
+ continue;
+ }
+
+ /* Calculate TBS from MCS */
+ NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
+ const int mcs = 9;
+ sched_pusch->mcs = mcs;
+ sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
+ sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table);
+ if (ps->pusch_Config->tp_pi2BPSK
+ && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) {
+ sched_pusch->R >>= 1;
+ sched_pusch->Qm <<= 1;
+ }
+
+ /* Check BSR and schedule UE if it is zero to avoid starvation, since we do
+ * not have SR (yet) */
+ if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0) {
+ if (UE_id != bsr0ue)
+ continue;
+ /* if no data, pre-allocate 5RB */
+ bool freeCCE = find_free_CCE(module_id, slot, UE_id);
+ if (!freeCCE) {
+ LOG_D(MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE_info->rnti[UE_id]);
+ continue;
+ }
+ /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
+ max_num_ue--;
+ if (max_num_ue < 0)
+ return;
+
+ while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
+ if (rbStart + min_rb >= bwpSize) {
+ LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
+ UE_id, UE_info->rnti[UE_id]);
+ return;
+ }
+ sched_pusch->rbStart = rbStart;
+ sched_pusch->rbSize = min_rb;
+ sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
+ sched_pusch->R,
+ sched_pusch->rbSize,
+ ps->nrOfSymbols,
+ ps->N_PRB_DMRS * ps->num_dmrs_symb,
+ 0, // nb_rb_oh
+ 0,
+ 1 /* NrOfLayers */)
+ >> 3;
+
+ /* Mark the corresponding RBs as used */
+ n_rb_sched -= sched_pusch->rbSize;
+ for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
+ rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
+
+ continue;
+ }
+
+ /* Create UE_sched for UEs eligibale for new data transmission*/
+ add_tail_nr_list(&UE_sched, UE_id);
+
+ /* Calculate coefficient*/
+ const uint32_t tbs = nr_compute_tbs(sched_pusch->Qm,
+ sched_pusch->R,
+ 1, // rbSize
+ ps->nrOfSymbols,
+ ps->N_PRB_DMRS * ps->num_dmrs_symb,
+ 0, // nb_rb_oh
+ 0,
+ 1 /* NrOfLayers */)
+ >> 3;
+ coeff_ue[UE_id] = (float) tbs / ul_thr_ue[UE_id];
+ LOG_D(MAC,"b %d, ul_thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n",
+ b, UE_id, ul_thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]);
+ }
+
+
+ /* Loop UE_sched to find max coeff and allocate transmission */
+ while (UE_sched.head >= 0 && max_num_ue> 0 && n_rb_sched > 0) {
+ /* Find max coeff */
+ int *max = &UE_sched.head; /* Find max coeff: assume head is max */
+ int *p = &UE_sched.next[*max];
+ while (*p >= 0) {
+ /* Find max coeff: if the current one has larger coeff, save for later */
+ if (coeff_ue[*p] > coeff_ue[*max])
+ max = p;
+ p = &UE_sched.next[*p];
+ }
+ /* Find max coeff: remove the max one: do not use remove_nr_list() since it
+ * goes through the whole list every time. Note that UE_sched.tail might
+ * not be set correctly anymore */
+ const int UE_id = *max;
+ p = &UE_sched.next[*max];
+ *max = UE_sched.next[*max];
+ *p = -1;
+
+ bool freeCCE = find_free_CCE(module_id, slot, UE_id);
+ if (!freeCCE) {
+ LOG_D(MAC, "%4d.%2d no free CCE for UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
+ continue;
+ }
+
+ /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
+ max_num_ue--;
+ if (max_num_ue < 0)
+ return;
+
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+ const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+ NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
+
+
+ while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
+ sched_pusch->rbStart = rbStart;
+ if (rbStart + min_rb >= bwpSize) {
+ LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
+ UE_id, UE_info->rnti[UE_id]);
+ return;
+ }
+
+ /* Calculate the current scheduling bytes */
+ const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0);
+ uint16_t rbSize = min_rb - 1;
+ do {
+ rbSize++;
+ sched_pusch->rbSize = rbSize;
+ sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
+ sched_pusch->R,
+ sched_pusch->rbSize,
+ sched_ctrl->pusch_save.nrOfSymbols,
+ sched_ctrl->pusch_save.N_PRB_DMRS * sched_ctrl->pusch_save.num_dmrs_symb,
+ 0, // nb_rb_oh
+ 0,
+ 1 /* NrOfLayers */)
+ >> 3;
+ } while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart+rbSize] &&
+ sched_pusch->tb_size < B);
+ LOG_D(MAC,"rbSize %d, TBS %d, est buf %d, sched_ul %d, B %d\n",
+ rbSize, sched_pusch->tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B);
+
+ /* Mark the corresponding RBs as used */
+ n_rb_sched -= sched_pusch->rbSize;
+ for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
+ rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
+ }
+}
+
+bool nr_simple_ulsch_preprocessor(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd,
@@ -479,17 +768,14 @@ void nr_simple_ulsch_preprocessor(module_id_t module_id,
const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
NR_UE_info_t *UE_info = &nr_mac->UE_info;
- AssertFatal(UE_info->num_UEs <= 1,
- "%s() cannot handle more than one UE, but found %d\n",
- __func__,
- UE_info->num_UEs);
if (UE_info->num_UEs == 0)
- return;
+ return false;
- const int UE_id = 0;
const int CC_id = 0;
- NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ /* NOT support different K2 in here, Get the K2 for first UE */
+ int UE_id = UE_info->list.head;
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
const int tda = 1;
const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList =
sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
@@ -497,94 +783,59 @@ void nr_simple_ulsch_preprocessor(module_id_t module_id,
"time domain assignment %d >= %d\n",
tda,
tdaList->list.count);
- int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu);
- const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd);
- const int sched_slot = (slot + K2) % num_slots_per_tdd;
- if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot))
- return;
- /* get first, largest unallocated region */
- uint16_t *vrb_map_UL =
- &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * 275];
- uint16_t rbStart = 0;
- while (vrb_map_UL[rbStart]) rbStart++;
- const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
- uint16_t rbSize = 1;
- while (rbStart + rbSize < bwpSize && !vrb_map_UL[rbStart+rbSize])
- rbSize++;
+ int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu);
+ const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
+ const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
+ if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot))
+ return false;
sched_ctrl->sched_pusch.slot = sched_slot;
sched_ctrl->sched_pusch.frame = sched_frame;
- const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
- sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
- uint8_t nr_of_candidates;
- find_aggregation_candidates(&sched_ctrl->aggregation_level,
- &nr_of_candidates,
- sched_ctrl->search_space);
- sched_ctrl->coreset = get_coreset(
- sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
- const int cid = sched_ctrl->coreset->controlResourceSetId;
- const uint16_t Y = UE_info->Y[UE_id][cid][slot];
- const int m = UE_info->num_pdcch_cand[UE_id][cid];
- sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
- sched_ctrl->active_bwp,
- sched_ctrl->coreset,
- sched_ctrl->aggregation_level,
- Y,
- m,
- nr_of_candidates);
- if (sched_ctrl->cce_index < 0) {
- LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__);
- return;
+ /* Confirm all the UE have same K2 as the first UE */
+ for (UE_id = UE_info->list.next[UE_id]; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
+ NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ AssertFatal(K2 == get_K2(sched_ctrl->active_ubwp, tda, mu),
+ "Different K2, %d(UE%d) != %ld(UE%d)\n", K2, 0, get_K2(sched_ctrl->active_ubwp, tda, mu), UE_id);
+ sched_ctrl->sched_pusch.slot = sched_slot;
+ sched_ctrl->sched_pusch.frame = sched_frame;
}
- UE_info->num_pdcch_cand[UE_id][cid]++;
- sched_ctrl->sched_pusch.time_domain_allocation = tda;
- const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
- const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
- const uint8_t num_dmrs_cdm_grps_no_data = 1;
- /* we want to avoid a lengthy deduction of DMRS and other parameters in
- * every TTI if we can save it, so check whether dci_format, TDA, or
- * num_dmrs_cdm_grps_no_data has changed and only then recompute */
- NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
- if (ps->time_domain_allocation != tda
- || ps->dci_format != dci_format
- || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
- nr_save_pusch_fields(scc,
- sched_ctrl->active_ubwp,
- dci_format,
- tda,
- num_dmrs_cdm_grps_no_data,
- ps);
-
- const int mcs = 9;
- NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
- sched_pusch->mcs = mcs;
- sched_pusch->rbStart = rbStart;
- sched_pusch->rbSize = rbSize;
-
- /* Calculate TBS from MCS */
- sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
- sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table);
- if (ps->pusch_Config->tp_pi2BPSK
- && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) {
- sched_pusch->R >>= 1;
- sched_pusch->Qm <<= 1;
+ /* Change vrb_map_UL to rballoc_mask */
+ uint16_t *vrb_map_UL =
+ &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
+ const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+ int st = 0, e = 0, len = 0;
+ for (int i = 0; i < bwpSize; i++) {
+ while (vrb_map_UL[i] == 1)
+ i++;
+ st = i;
+ while (vrb_map_UL[i] == 0)
+ i++;
+ if (i - st > len) {
+ len = i - st;
+ e = i - 1;
+ }
}
- sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
- sched_pusch->R,
- sched_pusch->rbSize,
- ps->nrOfSymbols,
- ps->N_PRB_DMRS * ps->num_dmrs_symb,
- 0, // nb_rb_oh
- 0,
- 1 /* NrOfLayers */)
- >> 3;
+ st = e - len + 1;
- /* mark the corresponding RBs as used */
- for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
- vrb_map_UL[rb + sched_ctrl->sched_pusch.rbStart] = 1;
+ uint8_t rballoc_mask[bwpSize];
+
+ /* Calculate mask: if any RB in vrb_map_UL is blocked (1), the current RB will be 0 */
+ for (int i = 0; i < bwpSize; i++)
+ rballoc_mask[i] = i >= st && i <= e;
+
+ /* proportional fair scheduling algorithm */
+ pf_ul(module_id,
+ frame,
+ slot,
+ num_slots_per_tdd,
+ &UE_info->list,
+ len,
+ rballoc_mask,
+ 2);
+ return true;
}
void nr_schedule_ulsch(module_id_t module_id,
@@ -593,14 +844,32 @@ void nr_schedule_ulsch(module_id_t module_id,
int num_slots_per_tdd,
int ul_slots,
uint64_t ulsch_in_slot_bitmap) {
- RC.nrmac[module_id]->pre_processor_ul(
+ /* Uplink data ONLY can be scheduled when the current slot is downlink slot,
+ * because we have to schedule the DCI0 first before schedule uplink data */
+ if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot)) {
+ LOG_D(MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot);
+ return;
+ }
+ bool do_sched = RC.nrmac[module_id]->pre_processor_ul(
module_id, frame, slot, num_slots_per_tdd, ulsch_in_slot_bitmap);
+ if (!do_sched)
+ return;
+
+ const int CC_id = 0;
+ nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[CC_id];
+ ul_dci_req->SFN = frame;
+ ul_dci_req->Slot = slot;
+ /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each
+ * allocated PDCCH so we can easily allocate UE's DCIs independent of any
+ * CORESET order */
+ nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {0};
NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
- const NR_UE_list_t *UE_list = &UE_info->list;
+ 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]) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+ UE_info->mac_stats[UE_id].ulsch_current_bytes = 0;
/* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in
* every TTI are pre-populated by the preprocessor and used below */
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
@@ -609,11 +878,29 @@ void nr_schedule_ulsch(module_id_t module_id,
uint16_t rnti = UE_info->rnti[UE_id];
- int8_t harq_id = select_ul_harq_pid(sched_ctrl);
- if (harq_id < 0) return;
+ int8_t harq_id = sched_pusch->ul_harq_pid;
+ if (harq_id < 0) {
+ /* PP has not selected a specific HARQ Process, get a new one */
+ harq_id = sched_ctrl->available_ul_harq.head;
+ AssertFatal(harq_id >= 0,
+ "no free HARQ process available for UE %d\n",
+ UE_id);
+ remove_front_nr_list(&sched_ctrl->available_ul_harq);
+ sched_pusch->ul_harq_pid = harq_id;
+ } else {
+ /* PP selected a specific HARQ process. Check whether it will be a new
+ * transmission or a retransmission, and remove from the corresponding
+ * list */
+ if (sched_ctrl->ul_harq_processes[harq_id].round == 0)
+ remove_nr_list(&sched_ctrl->available_ul_harq, harq_id);
+ else
+ remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id);
+ }
NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id];
- cur_harq->state = ACTIVE_SCHED;
- cur_harq->last_tx_slot = sched_pusch->slot;
+ DevAssert(!cur_harq->is_waiting);
+ add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id);
+ cur_harq->feedback_slot = sched_pusch->slot;
+ cur_harq->is_waiting = true;
int rnti_types[2] = { NR_RNTI_C, 0 };
@@ -626,8 +913,11 @@ void nr_schedule_ulsch(module_id_t module_id,
UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++;
if (cur_harq->round == 0) {
UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled += sched_pusch->tb_size;
+ /* Save information on MCS, TBS etc for the current initial transmission
+ * so we have access to it when retransmitting */
+ cur_harq->sched_pusch = *sched_pusch;
} else {
- LOG_W(MAC,
+ LOG_D(MAC,
"%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n",
frame,
slot,
@@ -638,6 +928,8 @@ void nr_schedule_ulsch(module_id_t module_id,
cur_harq->round,
cur_harq->ndi);
}
+ UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
+ sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
LOG_D(MAC,
"%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
@@ -780,51 +1072,59 @@ void nr_schedule_ulsch(module_id_t module_id,
pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS
}
- nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[0];
- ul_dci_req->SFN = frame;
- ul_dci_req->Slot = slot;
- nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus];
- memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t));
- ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
- ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
- ul_dci_req->numPdus += 1;
+ /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist,
+ * create it */
+ const int bwpid = sched_ctrl->active_bwp->bwp_Id;
+ const int coresetid = sched_ctrl->coreset->controlResourceSetId;
+ nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pdcch_pdu_bwp_coreset[bwpid][coresetid];
+ if (!pdcch_pdu) {
+ nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus];
+ memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t));
+ ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
+ ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
+ pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15;
+ ul_dci_req->numPdus += 1;
+ nr_configure_pdcch(pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, sched_ctrl->active_bwp);
+ pdcch_pdu_bwp_coreset[bwpid][coresetid] = pdcch_pdu;
+ }
LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frame,slot);
- nr_configure_pdcch(RC.nrmac[0],
- pdcch_pdu_rel15,
- rnti,
- sched_ctrl->search_space,
- sched_ctrl->coreset,
- scc,
- sched_ctrl->active_bwp,
- sched_ctrl->aggregation_level,
- sched_ctrl->cce_index);
+ /* Fill PDCCH DL DCI PDU */
+ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci];
+ pdcch_pdu->numDlDci++;
+ dci_pdu->RNTI = rnti;
+ if (sched_ctrl->coreset->pdcch_DMRS_ScramblingID &&
+ sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) {
+ dci_pdu->ScramblingId = *sched_ctrl->coreset->pdcch_DMRS_ScramblingID;
+ dci_pdu->ScramblingRNTI = rnti;
+ } else {
+ dci_pdu->ScramblingId = *scc->physCellId;
+ dci_pdu->ScramblingRNTI = 0;
+ }
+ dci_pdu->AggregationLevel = sched_ctrl->aggregation_level;
+ dci_pdu->CceIndex = sched_ctrl->cce_index;
+ dci_pdu->beta_PDCCH_1_0 = 0;
+ dci_pdu->powerControlOffsetSS = 1;
- dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
- memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15));
+ dci_pdu_rel15_t uldci_payload;
+ memset(&uldci_payload, 0, sizeof(uldci_payload));
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
const int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count;
- // NOTE: below functions assume that dci_formats is an array corresponding
- // to all UL DCIs in the PDCCH, but for us it is a simple int. So before
- // having multiple UEs, the below need to be changed (IMO the functions
- // should fill for one DCI only and not handle all of them).
config_uldci(sched_ctrl->active_ubwp,
pusch_pdu,
- pdcch_pdu_rel15,
- &dci_pdu_rel15[0],
- &ps->dci_format,
+ &uldci_payload,
+ ps->dci_format,
ps->time_domain_allocation,
UE_info->UE_sched_ctrl[UE_id].tpc0,
n_ubwp,
sched_ctrl->active_bwp->bwp_Id);
fill_dci_pdu_rel15(scc,
secondaryCellGroup,
- pdcch_pdu_rel15,
- dci_pdu_rel15,
- &ps->dci_format,
- rnti_types,
+ dci_pdu,
+ &uldci_payload,
+ ps->dci_format,
+ rnti_types[0],
pusch_pdu->bwp_size,
sched_ctrl->active_bwp->bwp_Id);
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 75f96deb2f..bbaf279a08 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -64,21 +64,9 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
frame_t frame_rxP, sub_frame_t slot_rxP);
-int nr_generate_dlsch_pdu(module_id_t Mod_idP,
- NR_UE_sched_ctrl_t *ue_sched_ctl,
- unsigned char *sdus_payload,
- unsigned char *mac_pdu,
- unsigned char num_sdus,
- unsigned short *sdu_lengths,
- unsigned char *sdu_lcids,
- unsigned char drx_cmd,
- unsigned char *ue_cont_res_id,
- unsigned short post_padding);
-
void nr_schedule_ue_spec(module_id_t module_id,
frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd);
+ sub_frame_t slot);
void schedule_control_sib1(module_id_t module_id,
int CC_id,
@@ -92,8 +80,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subfra
/* \brief default preprocessor */
void nr_simple_dlsch_preprocessor(module_id_t module_id,
frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd);
+ sub_frame_t slot);
void schedule_nr_mib(module_id_t module_idP,
frame_t frameP,
@@ -109,7 +96,7 @@ void nr_schedule_ulsch(module_id_t module_id,
int ul_slots,
uint64_t ulsch_in_slot_bitmap);
-void nr_simple_ulsch_preprocessor(module_id_t module_id,
+bool nr_simple_ulsch_preprocessor(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd,
@@ -164,11 +151,10 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs);
* freq resources */
void nr_preprocessor_phytest(module_id_t module_id,
frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd);
+ sub_frame_t slot);
/* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a
* fixed set of resources */
-void nr_ul_preprocessor_phytest(module_id_t module_id,
+bool nr_ul_preprocessor_phytest(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd,
@@ -178,22 +164,6 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP);
-void nr_fill_nfapi_dl_pdu(int Mod_id,
- nfapi_nr_dl_tti_request_body_t *dl_req,
- rnti_t rnti,
- NR_CellGroupConfig_t *secondaryCellGroup,
- NR_UE_sched_ctrl_t *sched_ctrl,
- NR_sched_pucch *pucch_sched,
- nfapi_nr_dmrs_type_e dmrsConfigType,
- uint16_t R,
- uint8_t Qm,
- uint32_t tbs,
- int StartSymbolIndex,
- int NrOfSymbols,
- int harq_pid,
- int ndi,
- int round);
-
void handle_nr_uci_pucch_0_1(module_id_t mod_id,
frame_t frame,
sub_frame_t slot,
@@ -204,40 +174,30 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234);
-void config_uldci(NR_BWP_Uplink_t *ubwp,
- nfapi_nr_pusch_pdu_t *pusch_pdu,
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
+void config_uldci(const NR_BWP_Uplink_t *ubwp,
+ const nfapi_nr_pusch_pdu_t *pusch_pdu,
dci_pdu_rel15_t *dci_pdu_rel15,
- int *dci_formats,
- int time_domain_assignment, uint8_t tpc,
- int n_ubwp, int bwp_id);
+ int dci_format,
+ int time_domain_assignment,
+ uint8_t tpc,
+ int n_ubwp,
+ int bwp_id);
void nr_schedule_pucch(int Mod_idP,
- int UE_id,
- int nr_ulmix_slots,
frame_t frameP,
sub_frame_t slotP);
-void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
+void csi_period_offset(const NR_CSI_ReportConfig_t *csirep,
int *period, int *offset);
void nr_csi_meas_reporting(int Mod_idP,
+ frame_t frameP,
+ sub_frame_t slotP);
+
+bool nr_acknack_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
- sub_frame_t slotP,
- int slots_per_tdd,
- int ul_slots,
- int n_slots_frame);
-
-void nr_acknack_scheduling(int Mod_idP,
- int UE_id,
- frame_t frameP,
- sub_frame_t slotP,
- int slots_per_tdd,
- int *pucch_id,
- int *pucch_occ);
-
-int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l);
+ sub_frame_t slotP);
void get_pdsch_to_harq_feedback(int Mod_idP,
int UE_id,
@@ -276,26 +236,22 @@ void find_search_space(int ss_type,
NR_BWP_Downlink_t *bwp,
NR_SearchSpace_t *ss);
-void nr_configure_pdcch(gNB_MAC_INST *nr_mac,
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
- uint16_t rnti,
+void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
NR_ServingCellConfigCommon_t *scc,
- NR_BWP_Downlink_t *bwp,
- uint8_t aggregation_level,
- int CCEIndex);
+ NR_BWP_Downlink_t *bwp);
-void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc,
- NR_CellGroupConfig_t *secondaryCellGroup,
- nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
+void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc,
+ const NR_CellGroupConfig_t *secondaryCellGroup,
+ nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu,
dci_pdu_rel15_t *dci_pdu_rel15,
- int *dci_formats,
- int *rnti_types,
+ int dci_formats,
+ int rnti_types,
int N_RB,
int bwp_id);
-void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup,
+void prepare_dci(const NR_CellGroupConfig_t *secondaryCellGroup,
dci_pdu_rel15_t *dci_pdu_rel15,
nr_dci_format_t format,
int bwp_id);
@@ -341,14 +297,21 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB);
int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB);
-void dump_nr_ue_list(NR_UE_list_t *listP);
-void add_nr_ue_list(NR_UE_list_t *listP, int UE_id);
+/* Functions to manage an NR_list_t */
+void dump_nr_list(NR_list_t *listP);
+void create_nr_list(NR_list_t *listP, int len);
+void destroy_nr_list(NR_list_t *list);
+void add_nr_list(NR_list_t *listP, int id);
+void remove_nr_list(NR_list_t *listP, int id);
+void add_tail_nr_list(NR_list_t *listP, int id);
+void add_front_nr_list(NR_list_t *listP, int id);
+void remove_front_nr_list(NR_list_t *listP);
int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP);
int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP);
-int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP);
+int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secondaryCellGroup);
void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti);
@@ -442,4 +405,5 @@ int16_t ssb_index_from_prach(module_id_t module_idP,
void find_SSB_and_RO_available(module_id_t module_idP);
+bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id);
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index 78a0dbb649..8dc1303801 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -113,18 +113,9 @@ void mac_top_init_gNB(void)
UE_info = &nrmac->UE_info;
UE_info->num_UEs = 0;
- UE_info->list.head = -1;
+ create_nr_list(&UE_info->list, MAX_MOBILES_PER_GNB);
for (list_el = 0; list_el < MAX_MOBILES_PER_GNB; list_el++) {
- UE_info->list.next[list_el] = -1;
UE_info->active[list_el] = false;
- for (int list_harq = 0; list_harq < NR_MAX_NB_HARQ_PROCESSES; list_harq++) {
- UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].round = 0;
- UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].ndi = 0;
- UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].is_waiting = 0;
- UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].round = 0;
- UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].ndi = 0;
- UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].state = 0;
- }
}
}
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index bf834941b5..de09d07f6d 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -75,10 +75,20 @@
#define MAX_NUM_BWP 2
#define MAX_NUM_CORESET 2
#define MAX_NUM_CCE 90
+#define MAX_HARQ_ROUNDS 4
/*!\brief Maximum number of random access process */
#define NR_NB_RA_PROC_MAX 4
#define MAX_NUM_OF_SSB 64
+/*! \brief NR_list_t is a "list" (of users, HARQ processes, slices, ...).
+ * Especially useful in the scheduler and to keep "classes" of users. */
+typedef struct {
+ int head;
+ int *next;
+ int tail;
+ int len;
+} NR_list_t;
+
typedef enum {
RA_IDLE = 0,
Msg2 = 1,
@@ -282,7 +292,7 @@ typedef struct NR_sched_pucch {
uint8_t dai_c;
uint8_t timing_indicator;
uint8_t resource_indicator;
-} NR_sched_pucch;
+} NR_sched_pucch_t;
/* this struct is a helper: as long as the TDA and DCI format remain the same
* over the same uBWP and search space, there is no need to recalculate all
@@ -326,13 +336,20 @@ typedef struct NR_sched_pusch {
uint16_t R;
uint8_t Qm;
uint32_t tb_size;
+
+ /// UL HARQ PID to use for this UE, or -1 for "any new"
+ int8_t ul_harq_pid;
} NR_sched_pusch_t;
typedef struct NR_UE_harq {
- uint8_t is_waiting;
+ bool is_waiting;
uint8_t ndi;
uint8_t round;
uint16_t feedback_slot;
+
+ /* Transport block to be sent using this HARQ process */
+ uint32_t tb[16384];
+ uint32_t tb_size;
} NR_UE_harq_t;
typedef struct NR_UE_old_sched {
@@ -350,10 +367,13 @@ typedef enum {
} NR_UL_harq_states_t;
typedef struct NR_UE_ul_harq {
+ bool is_waiting;
uint8_t ndi;
uint8_t round;
- uint16_t last_tx_slot;
- NR_UL_harq_states_t state;
+ uint16_t feedback_slot;
+
+ /// sched_pusch keeps information on MCS etc used for the initial transmission
+ NR_sched_pusch_t sched_pusch;
} NR_UE_ul_harq_t;
@@ -387,10 +407,12 @@ typedef struct {
/// the currently active BWP in UL
NR_BWP_Uplink_t *active_ubwp;
- NR_sched_pucch **sched_pucch;
- /// selected PUCCH index, if scheduled
- int pucch_sched_idx;
- int pucch_occ_idx;
+ /// PUCCH scheduling information. Array of three, we assume for the moment:
+ /// HARQ in the first field, SR in second, CSI in third (as fixed by RRC
+ /// conf., i.e. if actually present). The order is important for
+ /// nr_acknack_scheduling()!
+ NR_sched_pucch_t sched_pucch[3];
+
NR_sched_pusch_save_t pusch_save;
NR_sched_pusch_t sched_pusch;
@@ -404,6 +426,11 @@ typedef struct {
uint16_t rbSize;
uint16_t rbStart;
+ /// uplink bytes that are currently scheduled
+ int sched_ul_bytes;
+ /// estimation of the UL buffer size
+ int estimated_ul_buffer;
+
// time-domain allocation for scheduled RBs
int time_domain_allocation;
@@ -414,6 +441,8 @@ typedef struct {
/// Retransmission-related information
NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES];
+ /// DL HARQ PID to use for this UE, or -1 for "any new"
+ int8_t dl_harq_pid;
uint16_t ta_frame;
int16_t ta_update;
@@ -421,8 +450,22 @@ typedef struct {
uint8_t tpc0;
uint8_t tpc1;
uint16_t ul_rssi;
+ /// information about every HARQ process
NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES];
+ /// HARQ processes that are free
+ NR_list_t available_dl_harq;
+ /// HARQ processes that await feedback
+ NR_list_t feedback_dl_harq;
+ /// HARQ processes that await retransmission
+ NR_list_t retrans_dl_harq;
+ /// information about every UL HARQ process
NR_UE_ul_harq_t ul_harq_processes[NR_MAX_NB_HARQ_PROCESSES];
+ /// UL HARQ processes that are free
+ NR_list_t available_ul_harq;
+ /// UL HARQ processes that await feedback
+ NR_list_t feedback_ul_harq;
+ /// UL HARQ processes that await retransmission
+ NR_list_t retrans_ul_harq;
int dummy;
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
} NR_UE_sched_ctrl_t;
@@ -438,22 +481,15 @@ typedef struct {
int dlsch_rounds[8];
int dlsch_errors;
int dlsch_total_bytes;
+ int dlsch_current_bytes;
int ulsch_rounds[8];
int ulsch_errors;
int ulsch_total_bytes_scheduled;
int ulsch_total_bytes_rx;
+ int ulsch_current_bytes;
} NR_mac_stats_t;
-
-/*! \brief UNR_E_list_t is a "list" of users within UE_info_t. Especial useful in
- * the scheduler and to keep "classes" of users. */
-typedef struct {
- int head;
- int next[MAX_MOBILES_PER_GNB];
-} NR_UE_list_t;
-
-
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
#define MAX_CSI_REPORTCONFIG 48
typedef struct {
@@ -461,7 +497,7 @@ typedef struct {
nr_csi_report_t csi_report_template[MAX_MOBILES_PER_GNB][MAX_CSI_REPORTCONFIG];
NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB];
NR_mac_stats_t mac_stats[MAX_MOBILES_PER_GNB];
- NR_UE_list_t list;
+ NR_list_t list;
int num_UEs;
bool active[MAX_MOBILES_PER_GNB];
@@ -477,9 +513,8 @@ typedef struct {
typedef void (*nr_pp_impl_dl)(module_id_t mod_id,
frame_t frame,
- sub_frame_t slot,
- int num_slots_per_tdd);
-typedef void (*nr_pp_impl_ul)(module_id_t mod_id,
+ sub_frame_t slot);
+typedef bool (*nr_pp_impl_ul)(module_id_t mod_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd,
@@ -510,6 +545,10 @@ typedef struct gNB_MAC_INST_s {
nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX];
/// NFAPI DL Config Request Structure
nfapi_nr_dl_tti_request_t DL_req[NFAPI_CC_MAX];
+ /// a PDCCH PDU groups DCIs per BWP and CORESET. The following structure
+ /// keeps pointers to PDCCH PDUs within DL_req so that we can easily track
+ /// PDCCH PDUs per CC/BWP/CORESET
+ nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_idx[NFAPI_CC_MAX][MAX_NUM_BWP][MAX_NUM_CORESET];
/// NFAPI UL TTI Request Structure, simple pointer into structure
/// UL_tti_req_ahead for current frame/slot
nfapi_nr_ul_tti_request_t *UL_tti_req[NFAPI_CC_MAX];
@@ -552,6 +591,10 @@ typedef struct gNB_MAC_INST_s {
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
/// list of allocated beams per period
int16_t *tdd_beam_association;
+ /// PUCCH: keep track of the resources has already been used by saving the
+ /// highest index not yet been used in a given slot. Dynamically allocated
+ /// so we can have it for every slot as a function of the numerology
+ int *pucch_index_used[MAX_NUM_BWP];
/// DL preprocessor for differentiated scheduling
nr_pp_impl_dl pre_processor_dl;
/// UL preprocessor for differentiated scheduling
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index 0e6fd614a0..6195a91ea2 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -220,7 +220,7 @@ static void *enb_tun_read_thread(void *_)
exit(1);
}
-printf("\n\n\n########## nas_sock_fd read returns len %d\n", len);
+ LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len);
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager);
@@ -264,7 +264,7 @@ static void *ue_tun_read_thread(void *_)
exit(1);
}
-printf("\n\n\n########## nas_sock_fd read returns len %d\n", len);
+ LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len);
nr_pdcp_manager_lock(nr_pdcp_ue_manager);
rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager);
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
index 804f1e8a74..1d4efc1e26 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
@@ -1581,7 +1581,7 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity,
}
if (entity->tx_size + size > entity->tx_maxsize) {
- LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
+ LOG_E(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n",
__FILE__, __LINE__, __FUNCTION__);
return;
}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
index 82d9e5e38b..2eb2bae968 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
@@ -669,8 +669,8 @@ static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s)
poll_byte = -1;
max_retx_threshold = 8;
sn_field_length = 12;
- nr_rlc_am = new_nr_rlc_entity_am(100000,
- 100000,
+ nr_rlc_am = new_nr_rlc_entity_am(10000000,
+ 10000000,
deliver_sdu, ue,
successful_delivery, ue,
max_retx_reached, ue,
@@ -752,8 +752,8 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_
if (ue->drb[drb_id-1] != NULL) {
LOG_W(RLC, "%s:%d:%s: DRB %d already exists for UE with RNTI %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
} else {
- nr_rlc_am = new_nr_rlc_entity_am(100000,
- 100000,
+ nr_rlc_am = new_nr_rlc_entity_am(10000000,
+ 10000000,
deliver_sdu, ue,
successful_delivery, ue,
max_retx_reached, ue,
@@ -824,8 +824,8 @@ static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_
if (ue->drb[drb_id-1] != NULL) {
LOG_W(RLC, "DEBUG add_drb_um %s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
} else {
- nr_rlc_um = new_nr_rlc_entity_um(1000000,
- 1000000,
+ nr_rlc_um = new_nr_rlc_entity_um(100000000,
+ 100000000,
deliver_sdu, ue,
t_reassembly,
sn_field_length);
diff --git a/openair2/NETWORK_DRIVER/LITE/device.c b/openair2/NETWORK_DRIVER/LITE/device.c
index 854c3bcc99..59340784c1 100644
--- a/openair2/NETWORK_DRIVER/LITE/device.c
+++ b/openair2/NETWORK_DRIVER/LITE/device.c
@@ -316,7 +316,11 @@ void oai_nw_drv_change_rx_flags(struct net_device *dev, int flags)
}
//---------------------------------------------------------------------------
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
+void oai_nw_drv_tx_timeout(struct net_device *dev, unsigned int txqueue)
+#else
void oai_nw_drv_tx_timeout(struct net_device *dev)
+#endif
{
//---------------------------------------------------------------------------
// Transmitter timeout, serious problems.
diff --git a/openair2/NETWORK_DRIVER/MESH/device.c b/openair2/NETWORK_DRIVER/MESH/device.c
index 181899cd6e..47c68466bd 100644
--- a/openair2/NETWORK_DRIVER/MESH/device.c
+++ b/openair2/NETWORK_DRIVER/MESH/device.c
@@ -297,10 +297,10 @@ int nas_change_mtu(struct net_device *dev, int mtu)
}
//---------------------------------------------------------------------------
-#if LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0)
-void nas_tx_timeout(struct net_device *dev)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
+void nas_tx_timeout(struct net_device *dev, unsigned int txqueue)
#else
-void nas_tx_timeout(struct net_device *dev, unsigned int x)
+void nas_tx_timeout(struct net_device *dev)
#endif
{
//---------------------------------------------------------------------------
diff --git a/openair2/NETWORK_DRIVER/UE_IP/device.c b/openair2/NETWORK_DRIVER/UE_IP/device.c
index 32f9442747..63184eb6da 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/device.c
+++ b/openair2/NETWORK_DRIVER/UE_IP/device.c
@@ -302,7 +302,12 @@ void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP) {
}
//---------------------------------------------------------------------------
-void ue_ip_tx_timeout(struct net_device *dev_pP) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
+void ue_ip_tx_timeout(struct net_device *dev_pP, unsigned int txqueue)
+#else
+void ue_ip_tx_timeout(struct net_device *dev_pP)
+#endif
+{
//---------------------------------------------------------------------------
// Transmitter timeout, serious problems.
ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
index 7f98dd6a3e..b5cda6ecd6 100644
--- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
@@ -104,6 +104,9 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
}
UL_info->uci_ind.num_ucis = 0;
+ // mark corresponding PUCCH resources as free
+ // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs
+ RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0;
}
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index adf3dfe2a8..aebdc2f1cc 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -1177,7 +1177,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig;
pdsch_servingcellconfig->codeBlockGroupTransmission = NULL;
pdsch_servingcellconfig->xOverhead = NULL;
- pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NULL;
+ pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = calloc(1, sizeof(*pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH));
+ *pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16;
pdsch_servingcellconfig->pucch_Cell= NULL;
pdsch_servingcellconfig->ext1=calloc(1,sizeof(*pdsch_servingcellconfig->ext1));
pdsch_servingcellconfig->ext1->maxMIMO_Layers = calloc(1,sizeof(*pdsch_servingcellconfig->ext1->maxMIMO_Layers));
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
index 995fbfb45e..990a27cd06 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -1,7 +1,6 @@
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
-Num_Threads_PUSCH = 8;
gNBs =
(
@@ -234,6 +233,7 @@ L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
+ pusch_proc_threads = 8;
}
);
@@ -246,7 +246,7 @@ RUs = (
att_rx = 0;
bands = [7];
max_pdschReferenceSignalPower = -27;
- max_rxgain = 75;
+ max_rxgain = 50;
eNB_instances = [0];
##beamforming 1x2 matrix: 1 layer x 2 antennas
bf_weights = [0x00007fff, 0x0000];
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
index e34b261500..555af5835d 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
@@ -1,7 +1,6 @@
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
-Num_Threads_PUSCH = 8;
gNBs =
(
@@ -250,6 +249,7 @@ L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
+ pusch_proc_threads = 8;
}
);