mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-15 05:30:29 +00:00
Compare commits
129 Commits
pre-commit
...
NR_schedul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
856a8bb4a3 | ||
|
|
c50d905146 | ||
|
|
935932151e | ||
|
|
fb7e923047 | ||
|
|
d106f6f8df | ||
|
|
93be3017bf | ||
|
|
d6dd9b3135 | ||
|
|
eb45cb8687 | ||
|
|
e6033d246e | ||
|
|
9a03c5b039 | ||
|
|
66f18732f5 | ||
|
|
0ac2e2d5e0 | ||
|
|
0f3d3b5602 | ||
|
|
5c234393de | ||
|
|
3a77f10dbb | ||
|
|
ce09d16a52 | ||
|
|
617ac6aebe | ||
|
|
ec98cd2f31 | ||
|
|
9fd49e0479 | ||
|
|
4186e1e683 | ||
|
|
36a811724a | ||
|
|
b4eb8b2340 | ||
|
|
b9cbbe1e18 | ||
|
|
626c81cc7c | ||
|
|
d0ab53b377 | ||
|
|
b85b7efe74 | ||
|
|
98e268d138 | ||
|
|
570160c537 | ||
|
|
459235673a | ||
|
|
c654c8c052 | ||
|
|
3867d59851 | ||
|
|
2ef60b2ffb | ||
|
|
2c5a116b20 | ||
|
|
340395c5a0 | ||
|
|
19982425dd | ||
|
|
26a3abb7fe | ||
|
|
89dc371522 | ||
|
|
7113583612 | ||
|
|
0c9a642c65 | ||
|
|
93b75f6d3f | ||
|
|
feda5b5b4a | ||
|
|
bfd8554d3f | ||
|
|
ea74bdeb5c | ||
|
|
d782ca8916 | ||
|
|
dee7eb1392 | ||
|
|
758f73479c | ||
|
|
0ff18ca624 | ||
|
|
ea75f729f7 | ||
|
|
ad4c5c924e | ||
|
|
770a8bf009 | ||
|
|
bab9678dff | ||
|
|
7e4668aae8 | ||
|
|
cc946b48e4 | ||
|
|
c8bdc2056e | ||
|
|
bff0d7ae67 | ||
|
|
7be2cff096 | ||
|
|
a3dcb92087 | ||
|
|
6ee38033b7 | ||
|
|
8e2deaaa58 | ||
|
|
cd7fab2cb9 | ||
|
|
6935c88d59 | ||
|
|
5340e9959a | ||
|
|
6201ffeec9 | ||
|
|
66726e865d | ||
|
|
0ae7188183 | ||
|
|
7d26899e17 | ||
|
|
c243aaf85f | ||
|
|
8ec4be0b01 | ||
|
|
c65b14c1d3 | ||
|
|
c4f3221643 | ||
|
|
6c5b74c00f | ||
|
|
f433f0a32c | ||
|
|
bdeec18c98 | ||
|
|
835b1fa3eb | ||
|
|
4a8e8301ce | ||
|
|
ca06c977ed | ||
|
|
ca7a080b8f | ||
|
|
f690fe04bb | ||
|
|
fa406c4788 | ||
|
|
d30d7b52dd | ||
|
|
3c0fd8e0ae | ||
|
|
7002713ad6 | ||
|
|
495278e617 | ||
|
|
8429ba3be1 | ||
|
|
e4351d18ba | ||
|
|
fedf36955c | ||
|
|
c2c44ba6ef | ||
|
|
0902368131 | ||
|
|
236550e840 | ||
|
|
0dac26e289 | ||
|
|
45d9d5b418 | ||
|
|
364b906408 | ||
|
|
aeff5dd3ab | ||
|
|
9f2ce99b1f | ||
|
|
78a6244c84 | ||
|
|
6fa96e4a24 | ||
|
|
2846bc2f59 | ||
|
|
7ffef72e37 | ||
|
|
cc723979ea | ||
|
|
5237e07a15 | ||
|
|
0ea27844d6 | ||
|
|
f995c82c49 | ||
|
|
c1e181f7ce | ||
|
|
62d044715b | ||
|
|
b0ef857554 | ||
|
|
5b4da657be | ||
|
|
d5d2f2c039 | ||
|
|
4aa9ef1aa8 | ||
|
|
05138c0419 | ||
|
|
6f04f8e061 | ||
|
|
da9e8b233e | ||
|
|
532e2ef436 | ||
|
|
3a11d68760 | ||
|
|
3730d7e313 | ||
|
|
b0751db2c7 | ||
|
|
40438fbffe | ||
|
|
04b7b8e27a | ||
|
|
8ae3bf47b4 | ||
|
|
679fa48db3 | ||
|
|
a88bfd6c07 | ||
|
|
d32065498b | ||
|
|
d8f2dd818d | ||
|
|
3b92a3b440 | ||
|
|
b951b3db5e | ||
|
|
b2f7231782 | ||
|
|
da56c6e7b4 | ||
|
|
400f4681c0 | ||
|
|
827a6bfd45 | ||
|
|
0e9e44d6d6 |
@@ -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.
|
||||
|
||||
|
||||
@@ -630,30 +630,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;
|
||||
|
||||
@@ -698,7 +698,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 {
|
||||
|
||||
@@ -258,9 +258,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_id<NUMBER_OF_NR_ULSCH_MAX; ULSCH_id++) {
|
||||
printf("ULSCH_id %d : %p\n",ULSCH_id,gNB->dlsch[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 *) );
|
||||
@@ -277,7 +275,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; i<Prx; i++) {
|
||||
pusch_vars[ULSCH_id]->rxdataF_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 );
|
||||
@@ -294,16 +291,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_id<NUMBER_OF_UE_MAX; ulsch_id++)
|
||||
gNB->UE_stats_ptr[ulsch_id] = &gNB->UE_stats[ulsch_id];
|
||||
*/
|
||||
printf("After ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,8 +104,8 @@ 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 = (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED)?
|
||||
(n_rb*6) : (pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*36/cset_nsymb); //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)
|
||||
(n_rb*6) : (dci_pdu->AggregationLevel*36/cset_nsymb); //2(QPSK)*3(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
|
||||
|
||||
@@ -126,19 +127,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<encoded_length>>5; i++)
|
||||
@@ -171,8 +172,8 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
cset_start_sc -= frame_parms.ofdm_symbol_size;
|
||||
|
||||
/*Reorder REG list for a freq first mapping*/
|
||||
uint8_t reg_idx0 = pdcch_pdu_rel15->dci_pdu.CceIndex[d]*NR_NB_REG_PER_CCE;
|
||||
uint8_t nb_regs = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*NR_NB_REG_PER_CCE;
|
||||
uint8_t reg_idx0 = dci_pdu->CceIndex*NR_NB_REG_PER_CCE;
|
||||
uint8_t nb_regs = dci_pdu->AggregationLevel*NR_NB_REG_PER_CCE;
|
||||
|
||||
/*Mapping the encoded DCI along with the DMRS */
|
||||
for (int reg_idx=reg_idx0; reg_idx<(nb_regs+reg_idx0); reg_idx++) {
|
||||
@@ -221,8 +222,10 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
} // m
|
||||
} // reg_idx
|
||||
|
||||
LOG_I(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;d<pdcch_pdu_rel15->numDlDci;d++)
|
||||
}
|
||||
|
||||
@@ -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;d<pdcch_pdu_rel15->numDlDci;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_idx<L; cce_idx++) {
|
||||
cce = &gNB->cce_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;i<pdcch_pdu_rel15->numDlDci;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;//slot % num_slots_tdd;
|
||||
|
||||
dlsch->slot_tx[slot] = 1;
|
||||
dlsch->harq_ids[frame%2][slot] = harq_pid;
|
||||
dlsch->harq_ids[frame%2][slot] = 0;//harq_pid;
|
||||
AssertFatal(harq_pid < 8 && harq_pid >= 0,
|
||||
"illegal harq_pid %d\n",harq_pid);
|
||||
|
||||
dlsch->harq_mask |= (1<<harq_pid);
|
||||
dlsch->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;i<pdcch_pdu_rel15->numDlDci;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);
|
||||
|
||||
@@ -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;
|
||||
@@ -421,15 +420,8 @@ void dump_pdsch_stats(PHY_VARS_gNB *gNB) {
|
||||
|
||||
for (int i=0;i<NUMBER_OF_NR_SCH_STATS_MAX;i++)
|
||||
if (gNB->dlsch_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);
|
||||
|
||||
@@ -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,78 +62,67 @@ 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; i<dlsch->Mdlharq; 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; r<a_segments; r++) {
|
||||
|
||||
#ifdef DEBUG_DLSCH_FREE
|
||||
LOG_D(PHY,"Freeing dlsch process %d c[%d] (%p)\n",i,r,dlsch->harq_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;
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned char Kmimo,
|
||||
unsigned char Mdlharq,
|
||||
@@ -144,7 +132,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
|
||||
{
|
||||
|
||||
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
|
||||
|
||||
@@ -156,126 +144,67 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
|
||||
uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
|
||||
|
||||
|
||||
dlsch = (NR_gNB_DLSCH_t *)malloc16(sizeof(NR_gNB_DLSCH_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; layer<NR_MAX_NB_LAYERS; layer++) {
|
||||
dlsch->ue_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;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
|
||||
dlsch->ue_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; q<NR_MAX_NB_CODEWORDS; q++)
|
||||
dlsch->mod_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; i<Mdlharq; i++) {
|
||||
dlsch->harq_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; 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)
|
||||
dlsch->harq_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;
|
||||
AssertFatal((dlsch = (NR_gNB_DLSCH_t *)malloc16(sizeof(NR_gNB_DLSCH_t)))!=NULL,"cannot allocate dlsch\n");
|
||||
|
||||
bzero(dlsch,sizeof(NR_gNB_DLSCH_t));
|
||||
dlsch->Kmimo = Kmimo;
|
||||
dlsch->Mdlharq = Mdlharq;
|
||||
dlsch->Mlimit = 4;
|
||||
dlsch->Nsoft = Nsoft;
|
||||
|
||||
for (layer=0; layer<NR_MAX_NB_LAYERS; layer++) {
|
||||
dlsch->ue_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;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
|
||||
dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
|
||||
}
|
||||
}
|
||||
|
||||
if (exit_flag==0) {
|
||||
for (i=0; i<Mdlharq; i++) {
|
||||
dlsch->harq_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));
|
||||
|
||||
free_gNB_dlsch(&dlsch,N_RB);
|
||||
|
||||
return(NULL);
|
||||
|
||||
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
|
||||
bzero(harq,sizeof(NR_DL_gNB_HARQ_t));
|
||||
AssertFatal((harq->b = (unsigned char*)malloc16(dlsch_bytes))!=NULL,"cannot allocate memory for harq->b\n");
|
||||
AssertFatal((harq->pdu = (uint8_t*)malloc16(dlsch_bytes))!=NULL,"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)
|
||||
AssertFatal((harq->c[r] = (uint8_t*)malloc16(8448))!=NULL,"cannot allocate harq->c[%d]\n",r);
|
||||
AssertFatal((harq->d[r] = (uint8_t*)malloc16(68*384))!=NULL,"cannot allocate harq->d[%d]\n",r);; //max size for coded output
|
||||
bzero(harq->c[r],8448);
|
||||
bzero(harq->d[r],(3*8448));
|
||||
AssertFatal((harq->e = (uint8_t*)malloc16(14*N_RB*12*8))!=NULL,"cannot allocate harq->e\n");
|
||||
bzero(harq->e,14*N_RB*12*8);
|
||||
AssertFatal((harq->f = (uint8_t*)malloc16(14*N_RB*12*8))!=NULL,"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++) {
|
||||
for (i=0; i<10; i++) {
|
||||
dlsch->harq_ids[0][i] = Mdlharq;
|
||||
dlsch->harq_ids[1][i] = Mdlharq;
|
||||
}
|
||||
for (i=0; i<Mdlharq; i++) {
|
||||
if (dlsch->harq_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; r<MAX_NUM_NR_DLSCH_SEGMENTS; r++)
|
||||
if (dlsch->harq_processes[i]->d[r])
|
||||
dlsch->harq_processes[i]->d[r][j] = NR_NULL;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0; i<Mdlharq; i++) {
|
||||
for (j=0; j<96; j++)
|
||||
for (r=0; r<MAX_NUM_NR_DLSCH_SEGMENTS; r++)
|
||||
if (harq->d[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,156 @@ 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)]);
|
||||
|
||||
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; r<dlsch->harq_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
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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(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
|
||||
|
||||
F = dlsch->harq_processes[harq_pid]->F;
|
||||
|
||||
Kr = dlsch->harq_processes[harq_pid]->K;
|
||||
for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
|
||||
//printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,harq->K,Kr,BG,harq->C);
|
||||
|
||||
for (r=0; r<harq->C; 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; r<harq->C; r++) {
|
||||
|
||||
if (F>0) {
|
||||
for (int k=(Kr-F-2*(*Zc)); k<Kr-2*(*Zc); k++) {
|
||||
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
|
||||
dlsch->harq_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 +444,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;
|
||||
|
||||
@@ -289,12 +289,12 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB,
|
||||
AssertFatal( (dlsch_id>=0) && (dlsch_id<NUMBER_OF_NR_DLSCH_MAX),
|
||||
"illegal or no dlsch_id found!!! rnti %04x dlsch_id %d\n",rel15->rnti,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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -393,6 +393,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->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)));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -201,10 +201,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);
|
||||
|
||||
@@ -809,6 +809,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;
|
||||
}
|
||||
if (do_reset == TRUE) {
|
||||
init_downlink_harq_status(ue->dlsch[thread_idx][gNB_id][code_word]->harq_processes[dl_harq_pid]);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,8 +160,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];
|
||||
@@ -177,15 +176,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);
|
||||
@@ -645,6 +654,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
|
||||
@@ -810,10 +822,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));
|
||||
@@ -859,7 +871,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;
|
||||
@@ -875,15 +887,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; i<MAX_NUM_CORESET; i++)
|
||||
gNB_mac->UE_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);
|
||||
}
|
||||
@@ -1028,8 +1036,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");
|
||||
@@ -1042,7 +1050,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)
|
||||
@@ -1082,9 +1090,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");
|
||||
|
||||
@@ -102,22 +102,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;
|
||||
|
||||
@@ -2380,8 +2380,8 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -176,8 +176,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,
|
||||
|
||||
@@ -245,6 +245,8 @@ typedef struct {
|
||||
uint8_t generate_nr_prach;
|
||||
/// 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;
|
||||
|
||||
@@ -952,7 +952,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
|
||||
void *pduP,
|
||||
uint16_t cell_id)
|
||||
{
|
||||
LOG_I(MAC,"[L2][MAC] decode mib\n");
|
||||
LOG_D(MAC,"[L2][MAC] decode mib\n");
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
@@ -1247,7 +1247,6 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
ulcfg_pdu->pusch_config_pdu.dmrs_config_type = dmrs_config_type;
|
||||
ulcfg_pdu->pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1;
|
||||
ulcfg_pdu->pusch_config_pdu.nrOfLayers = 1;
|
||||
ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator = 0;
|
||||
ulcfg_pdu->pusch_config_pdu.pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
|
||||
ulcfg_pdu->pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density;
|
||||
ulcfg_pdu->pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density;
|
||||
@@ -1274,8 +1273,9 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
TBS_bytes = TBS/8;
|
||||
ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size = TBS_bytes;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1){
|
||||
// Getting IP traffic to be transmitted
|
||||
// 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,
|
||||
frame_tx,
|
||||
@@ -1285,6 +1285,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
|
||||
TBS_bytes,
|
||||
&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) {
|
||||
@@ -4771,7 +4772,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)
|
||||
|
||||
@@ -350,6 +350,14 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL,
|
||||
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
|
||||
|
||||
for (int i = 0; i < MAX_NUM_BWP; ++i) {
|
||||
RC.nrmac[Mod_idP]->pucch_index_used[i] =
|
||||
calloc(n, sizeof(*RC.nrmac[Mod_idP]->pucch_index_used));
|
||||
AssertFatal(RC.nrmac[Mod_idP]->pucch_index_used[i],
|
||||
"could not allocate memory for RC.nrmac[]->pucch_index_used[%d]\n",
|
||||
i);
|
||||
}
|
||||
|
||||
LOG_I(MAC,"Configuring common parameters from NR ServingCellConfig\n");
|
||||
|
||||
config_common(Mod_idP,
|
||||
@@ -389,22 +397,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 */
|
||||
|
||||
@@ -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_id<MAX_MOBILES_PER_GNB;UE_id++) {
|
||||
if (UE_info->active[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;
|
||||
@@ -360,13 +367,16 @@ 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);
|
||||
const uint64_t ulsch_in_slot_bitmap = BIT( 8);
|
||||
|
||||
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; i<MAX_NUM_CORESET; i++)
|
||||
RC.nrmac[module_idP]->UE_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; i<MAX_NUM_CORESET; i++)
|
||||
UE_info->num_pdcch_cand[UE_id][i] = 0;
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
//mbsfn_status[CC_id] = 0;
|
||||
|
||||
@@ -407,12 +417,13 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
schedule_nr_prach(module_idP, f, s);
|
||||
}
|
||||
|
||||
// This schedule SR
|
||||
// TODO
|
||||
// Schedule SR: check in slot 0 for the whole frame
|
||||
if (slot == 0)
|
||||
nr_sr_reporting(module_idP, frame, slot);
|
||||
|
||||
// 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
|
||||
@@ -421,19 +432,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);
|
||||
|
||||
|
||||
@@ -766,7 +766,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];
|
||||
@@ -793,27 +793,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
|
||||
@@ -824,7 +852,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);
|
||||
@@ -837,7 +864,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,275);
|
||||
@@ -887,65 +918,61 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
|
||||
pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, NrOfSymbols);
|
||||
|
||||
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,
|
||||
/* 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;
|
||||
|
||||
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_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;
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
@@ -955,11 +982,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;
|
||||
|
||||
@@ -126,7 +126,12 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
|
||||
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];
|
||||
@@ -331,13 +336,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;
|
||||
@@ -385,46 +396,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);
|
||||
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);
|
||||
|
||||
dl_req->nPDUs += 2;
|
||||
|
||||
@@ -504,4 +519,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 && slot != 3)
|
||||
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,13 +401,13 @@ 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);
|
||||
uint16_t rbStart = 0;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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; k<nr_ulmix_slots; k++) {
|
||||
for (int l=0; l<2; l++) {
|
||||
NR_sched_pucch *curr_pucch = &UE_info->UE_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,137 @@ 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; // what's the context of the offset here, is it the same as the period ??
|
||||
// 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; i<n_list; i++) {
|
||||
if (*pucchresset->resourceList.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; i<n_list; i++) {
|
||||
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->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 * 275];
|
||||
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,52 +330,39 @@ 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 int8_t 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];
|
||||
const int feedback_slot = (slot - 1 + num_slots) % num_slots;
|
||||
AssertFatal(harq->feedback_slot == feedback_slot,
|
||||
"expected feedback slot %d, but found %d instead\n",
|
||||
harq->feedback_slot, feedback_slot);
|
||||
DevAssert(harq->is_waiting);
|
||||
LOG_D(MAC,
|
||||
"%s(): in %d.%d handle feedback for HARQ PID %d feedback_slot %d\n",
|
||||
__func__,
|
||||
frame,
|
||||
slot,
|
||||
pid,
|
||||
feedback_slot);
|
||||
handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// check scheduling request result, confidence_level == 0 is good
|
||||
if (uci_01->pduBitmap & 0x1) {
|
||||
sched_ctrl->SR |= uci_01->sr->sr_indication && uci_01->sr->sr_confidence_level == 0;
|
||||
if (uci_01->sr->sr_indication && uci_01->sr->sr_confidence_level == 0)
|
||||
LOG_I(MAC, "UE %d scheduling request\n", UE_id);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
|
||||
@@ -358,130 +383,253 @@ 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 int8_t 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];
|
||||
const int feedback_slot = (slot - 1 + num_slots) % num_slots;
|
||||
AssertFatal(harq->feedback_slot == feedback_slot,
|
||||
"expected feedback slot %d, but found %d instead\n",
|
||||
harq->feedback_slot, feedback_slot);
|
||||
DevAssert(harq->is_waiting);
|
||||
LOG_D(MAC,
|
||||
"%s(): in %d.%d handle feedback for HARQ PID %d feedback_slot %d\n",
|
||||
__func__,
|
||||
frame,
|
||||
slot,
|
||||
pid,
|
||||
feedback_slot);
|
||||
handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack);
|
||||
}
|
||||
}
|
||||
|
||||
// check scheduling request result, confidence_level == 0 is good
|
||||
if (uci_234->pduBitmap & 0x1) {
|
||||
AssertFatal(0, "PUCCH Formats 2/3/4: we do not handle SR\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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; k<nr_ulmix_slots; k++) {
|
||||
if(UE_info->UE_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)
|
||||
* * pucch_sched[1] holds a second SR, if at all
|
||||
* * 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; k<nr_ulmix_slots; k++) {
|
||||
for (l=0; l<1; l++) { // scheduling 2 PUCCH in a single slot does not work with the phone, currently
|
||||
curr_pucch = &UE_info->UE_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<max_acknacks) {
|
||||
pucch_res = get_pucch_resource(UE_info,UE_id,k,l);
|
||||
if (pucch_res>-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;
|
||||
}
|
||||
|
||||
/* check if the next occasion coincides with a pre-scheduled PUCCH occasion,
|
||||
* i.e., scheduling request. If yes, rerun algorithm on this information */
|
||||
NR_sched_pucch_t *pucch1 = &sched_ctrl->sched_pucch[1];
|
||||
if (pucch1->sr_flag > 0 && pucch1->frame == pucch->frame && pucch1->ul_slot == pucch->ul_slot) {
|
||||
*pucch = *pucch1;
|
||||
memset(pucch1, 0, sizeof(*pucch1));
|
||||
return nr_acknack_scheduling(mod_id, UE_id, frame, slot);
|
||||
}
|
||||
|
||||
// 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 * 275];
|
||||
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 +680,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,
|
||||
@@ -626,3 +756,143 @@ uint16_t compute_pucch_prb_size(uint8_t format,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void nr_sr_reporting(int Mod_idP, frame_t SFN, 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_list_t *UE_list = &UE_info->list;
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
if (UE_info->active[UE_id]) {
|
||||
NR_PUCCH_ResourceSet_t *pucchresset;
|
||||
NR_sched_pucch_t *curr_pucch;
|
||||
NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig;
|
||||
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
|
||||
//NR_SchedulingRequestConfig_t *schedulingRequestConfig = secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig;
|
||||
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;
|
||||
|
||||
AssertFatal(pucch_Config->schedulingRequestResourceToAddModList->list.count>0,"NO SR configuration available");
|
||||
|
||||
for (int SR_resource_id =0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++){
|
||||
SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id]; // to makesure later of the index.
|
||||
//NR_SchedulingRequestResourceId_t schedulingRequestResourceId = SchedulingRequestResourceConfig->schedulingRequestResourceId;
|
||||
//NR_SchedulingRequestId_t schedulingRequest_ID = SchedulingRequestResourceConfig->schedulingRequestID;
|
||||
|
||||
|
||||
/*for (int SRConfig =0; SRConfig<schedulingRequestConfig->schedulingRequestToAddModList->list.count;SRConfig++){
|
||||
|
||||
NR_SchedulingRequestToAddMod_t *SchedulingRequestToAddMod = schedulingRequestConfig->schedulingRequestToAddModList->list.array[SRConfig];
|
||||
if(SchedulingRequestToAddMod->schedulingRequestId == schedulingRequest_ID)
|
||||
long *prohibitTimer = SchedulingRequestToAddMod->sr_ProhibitTimer;
|
||||
}*/
|
||||
|
||||
int SR_period; int SR_offset;
|
||||
|
||||
periodicity__SRR(SchedulingRequestResourceConfig,&SR_period,&SR_offset);
|
||||
const int num_SRs = n_slots_frame / SR_period;
|
||||
AssertFatal(num_SRs <= 2,
|
||||
"cannot handle more than 2 SRs per frame, but have %d!\n",
|
||||
num_SRs);
|
||||
const bool SR_even = !(n_slots_frame % SR_period);
|
||||
AssertFatal(SR_even, "cannot handle SR periodicity not evenly dividing number of slots\n");
|
||||
// first condition: SR every frame; second condition: less than every frame
|
||||
if (!(SR_period < n_slots_frame || SFN % (SR_period / n_slots_frame) == SR_offset / n_slots_frame))
|
||||
return;
|
||||
|
||||
NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource;
|
||||
|
||||
int found = -1;
|
||||
pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1
|
||||
|
||||
|
||||
int n_list = pucchresset->resourceList.list.count;
|
||||
for (int i=0; i<n_list; i++) {
|
||||
if (*pucchresset->resourceList.list.array[i] == *PucchResourceId )
|
||||
found = i;
|
||||
}
|
||||
AssertFatal(found>-1,"SR resource not found among PUCCH resources");
|
||||
|
||||
for (int i = 0; i < num_SRs; ++i) {
|
||||
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[i];
|
||||
curr_pucch->sr_flag=true;
|
||||
curr_pucch->frame = SFN;
|
||||
curr_pucch->ul_slot = (i * SR_period + SR_offset) % n_slots_frame; // first, start on slot 0
|
||||
curr_pucch->resource_indicator = found;
|
||||
|
||||
LOG_D(MAC,
|
||||
"Scheduling Request for %4d.%2d with SR bit %d sched_pucch %d resource %d\n",
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
curr_pucch->sr_flag,
|
||||
i,
|
||||
curr_pucch->resource_indicator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void periodicity__SRR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset){
|
||||
|
||||
NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present;
|
||||
|
||||
switch (P_O){
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1:
|
||||
*period = 1;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl1;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl2:
|
||||
*period = 2;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl2;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl4:
|
||||
*period = 4;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl4;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5:
|
||||
*period = 5;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl5;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8:
|
||||
*period = 8;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl8;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10:
|
||||
*period = 10;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl10;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16:
|
||||
*period = 16;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl16;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20:
|
||||
*period = 20;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl20;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40:
|
||||
*period = 40;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl40;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80:
|
||||
*period = 80;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl80;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160:
|
||||
*period = 160;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl160;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320:
|
||||
*period = 320;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl320;
|
||||
break;
|
||||
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640:
|
||||
*period = 640;
|
||||
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl640;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"No periodicityAndOffset resources found in schedulingrequestresourceconfig");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,47 @@ 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->round<max_harq_rounds)) {
|
||||
cur_harq->ndi ^= 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
|
||||
const int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
|
||||
if (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);
|
||||
return;
|
||||
}
|
||||
DevAssert(harq_pid == crc_pdu->harq_id);
|
||||
remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
|
||||
NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid];
|
||||
DevAssert(harq->feedback_slot == slot - 1);
|
||||
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 +374,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 +427,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 +467,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 +504,251 @@ 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];
|
||||
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 };
|
||||
|
||||
/* 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, 275);
|
||||
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0 && !sched_ctrl->SR)
|
||||
continue;
|
||||
|
||||
/* Schedule UE if there is a SR and no data (otherwise, will be scheduled
|
||||
* baded on data to transmit) */
|
||||
if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0
|
||||
&& sched_ctrl->SR) {
|
||||
/* 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, 275);
|
||||
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||||
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 +759,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 +774,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,275);
|
||||
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 * 275];
|
||||
const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275);
|
||||
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 +835,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;
|
||||
@@ -608,12 +868,31 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
continue;
|
||||
|
||||
uint16_t rnti = UE_info->rnti[UE_id];
|
||||
sched_ctrl->SR = false;
|
||||
|
||||
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 +905,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,
|
||||
@@ -742,6 +1024,9 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size;
|
||||
pusch_pdu->pusch_data.num_cb = 0; //CBG not supported
|
||||
|
||||
UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
|
||||
sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
|
||||
|
||||
/* PUSCH PTRS */
|
||||
if (ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) {
|
||||
// TODO to be fixed from RRC config
|
||||
@@ -761,51 +1046,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);
|
||||
|
||||
|
||||
@@ -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, sub_frame_t subframeP, uint8_t slots_per_frame);
|
||||
|
||||
@@ -105,7 +92,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,
|
||||
@@ -159,11 +146,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,
|
||||
@@ -173,22 +159,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,
|
||||
@@ -199,40 +169,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,
|
||||
@@ -271,26 +231,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);
|
||||
@@ -337,14 +293,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);
|
||||
|
||||
@@ -438,4 +401,13 @@ 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);
|
||||
|
||||
void nr_sr_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP);
|
||||
|
||||
void periodicity__SRR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRecconf,
|
||||
int *period,
|
||||
int *offset);
|
||||
|
||||
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,23 @@ typedef struct {
|
||||
uint8_t tpc0;
|
||||
uint8_t tpc1;
|
||||
uint16_t ul_rssi;
|
||||
bool SR;
|
||||
/// 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 +482,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 +498,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 +514,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 +546,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];
|
||||
@@ -549,6 +589,10 @@ typedef struct gNB_MAC_INST_s {
|
||||
time_stats_t schedule_pch;
|
||||
/// CCE lists
|
||||
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
|
||||
/// 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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -668,8 +668,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,
|
||||
@@ -751,8 +751,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,
|
||||
@@ -823,8 +823,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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -82,13 +82,15 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
int n_physical_antenna_ports,
|
||||
int initial_csi_index);
|
||||
int initial_csi_index,
|
||||
int UEID);
|
||||
|
||||
void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
int n_physical_antenna_ports,
|
||||
int initial_csi_index);
|
||||
int initial_csi_index,
|
||||
int UEID);
|
||||
|
||||
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig);
|
||||
|
||||
|
||||
@@ -166,11 +166,14 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t));
|
||||
fill_default_rbconfig(ue_context_p->ue_context.rb_config);
|
||||
}
|
||||
|
||||
ue_uid_t LocalUEID = ue_context_p->local_uid;
|
||||
fill_default_reconfig(carrier->servingcellconfigcommon,
|
||||
reconfig_ies,
|
||||
ue_context_p->ue_context.secondaryCellGroup,
|
||||
carrier->pdsch_AntennaPorts,
|
||||
carrier->initial_csi_index[rrc->Nb_ue]);
|
||||
carrier->initial_csi_index[rrc->Nb_ue],
|
||||
LocalUEID);
|
||||
ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
||||
NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config));
|
||||
memset((void *)CG_Config,0,sizeof(*CG_Config));
|
||||
|
||||
@@ -147,7 +147,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
int scg_id,
|
||||
int servCellIndex,
|
||||
int n_physical_antenna_ports,
|
||||
int initial_csi_index) {
|
||||
int initial_csi_index,
|
||||
int LocalUEID) {
|
||||
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
||||
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
|
||||
|
||||
@@ -182,7 +183,17 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->rlc_BearerToAddModList->list, RLC_BearerConfig);
|
||||
secondaryCellGroup->mac_CellGroupConfig=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig));
|
||||
secondaryCellGroup->mac_CellGroupConfig->drx_Config = NULL;
|
||||
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig = NULL;
|
||||
|
||||
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig));
|
||||
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList));
|
||||
NR_SchedulingRequestToAddMod_t *SchedulingRequestConf = calloc(1,sizeof(*SchedulingRequestConf));
|
||||
SchedulingRequestConf->schedulingRequestId = 0; //Could be changed
|
||||
SchedulingRequestConf->sr_ProhibitTimer = calloc(1,sizeof(*SchedulingRequestConf->sr_ProhibitTimer));
|
||||
*SchedulingRequestConf->sr_ProhibitTimer = 3; //could be changed
|
||||
SchedulingRequestConf->sr_TransMax = 3; ; //could be changed
|
||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList->list,SchedulingRequestConf);
|
||||
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToReleaseList = NULL;
|
||||
|
||||
secondaryCellGroup->mac_CellGroupConfig->bsr_Config=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->bsr_Config));
|
||||
secondaryCellGroup->mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf80;
|
||||
secondaryCellGroup->mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf320;
|
||||
@@ -1060,7 +1071,21 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
||||
pucchfmt2->nrofSlots=NULL;
|
||||
pucchfmt2->pi2BPSK=NULL;
|
||||
pucchfmt2->simultaneousHARQ_ACK_CSI=NULL;
|
||||
pucch_Config->schedulingRequestResourceToAddModList=NULL;
|
||||
|
||||
// for scheduling requestresource
|
||||
|
||||
int n_list= pucchresset0->resourceList.list.count;
|
||||
pucch_Config->schedulingRequestResourceToAddModList = calloc(1,sizeof(*pucch_Config->schedulingRequestResourceToAddModList));
|
||||
NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1,sizeof(*schedulingRequestResourceConfig));
|
||||
schedulingRequestResourceConfig->schedulingRequestResourceId = LocalUEID+1;
|
||||
schedulingRequestResourceConfig->schedulingRequestID = 0;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset));
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
|
||||
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl10 = 7; // we can leave this as slot 7 or change when number of UEs is higher(they orthogonal now based on PUCCHRes alloc)
|
||||
schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource));
|
||||
*schedulingRequestResourceConfig->resource = LocalUEID%n_list;
|
||||
ASN_SEQUENCE_ADD(&pucch_Config->schedulingRequestResourceToAddModList->list,schedulingRequestResourceConfig);
|
||||
|
||||
pucch_Config->schedulingRequestResourceToReleaseList=NULL;
|
||||
pucch_Config->multi_CSI_PUCCH_ResourceList=NULL;
|
||||
pucch_Config->dl_DataToUL_ACK = calloc(1,sizeof(*pucch_Config->dl_DataToUL_ACK));
|
||||
@@ -1140,7 +1165,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));
|
||||
@@ -1266,14 +1292,15 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||
int n_physical_antenna_ports,
|
||||
int initial_csi_index) {
|
||||
int initial_csi_index,
|
||||
int LocalUEID) {
|
||||
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
||||
AssertFatal(reconfig!=NULL,"reconfig is null\n");
|
||||
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
|
||||
// radioBearerConfig
|
||||
reconfig->radioBearerConfig=NULL;
|
||||
// secondaryCellGroup
|
||||
fill_default_secondaryCellGroup(servingcellconfigcommon,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index);
|
||||
fill_default_secondaryCellGroup(servingcellconfigcommon,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index,LocalUEID);
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
||||
|
||||
char scg_buffer[1024];
|
||||
|
||||
Reference in New Issue
Block a user