restructuring of UE DLSCH code to handle 2 codewords

even if 2 codewords are currently not supported and not tested, the way UE handled the possibility of having 2 codewords was messy, in between support and non-support
the intention of this MR is to cleanup the code more than extend the support

Signed-off-by: Francesco Mani <email@francescomani.it>
This commit is contained in:
francescomani
2026-09-14 22:56:26 +09:00
committed by maki
parent 08349f246b
commit 04ee4ea8e5
28 changed files with 747 additions and 879 deletions
+2 -2
View File
@@ -558,8 +558,8 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
if (phy_data->dlsch[0].active if (phy_data->dlsch[0].active
&& (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) { && (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) {
// indicate to tx thread to wait for DLSCH decoding // indicate to tx thread to wait for DLSCH decoding
if (phy_data->dlsch[0].dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH if (phy_data->dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH
const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % fp->slots_per_frame; const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch_config.k1_feedback) % fp->slots_per_frame;
tx_wait_for_dlsch[ack_nack_slot]++; tx_wait_for_dlsch[ack_nack_slot]++;
} }
} }
@@ -118,6 +118,7 @@ typedef struct {
typedef struct { typedef struct {
uint8_t harq_pid; uint8_t harq_pid;
uint8_t cw_idx;
uint8_t ack_nack; uint8_t ack_nack;
uint32_t pdu_length; uint32_t pdu_length;
uint8_t* pdu; uint8_t* pdu;
@@ -466,6 +467,17 @@ typedef struct {
typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t; typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t;
typedef struct {
uint8_t mcs;
bool new_data_indicator;
uint8_t rv;
uint16_t targetCodeRate;
uint8_t qamModOrder;
uint32_t TBS;
uint8_t ldpcBaseGraph;
uint8_t Nl;
} fapi_nr_dl_cw_info_t;
typedef struct { typedef struct {
uint16_t BWPSize; uint16_t BWPSize;
uint16_t BWPStart; uint16_t BWPStart;
@@ -482,15 +494,8 @@ typedef struct {
uint8_t prb_bundling_size_ind; uint8_t prb_bundling_size_ind;
uint8_t rate_matching_ind; uint8_t rate_matching_ind;
uint8_t zp_csi_rs_trigger; uint8_t zp_csi_rs_trigger;
uint8_t mcs; uint8_t n_codewords;
bool new_data_indicator; fapi_nr_dl_cw_info_t cw_info[2];
uint8_t rv;
uint16_t targetCodeRate;
uint8_t qamModOrder;
uint32_t TBS;
uint8_t tb2_mcs;
bool tb2_new_data_indicator;
uint8_t tb2_rv;
uint8_t harq_process_nbr; uint8_t harq_process_nbr;
vrb_to_prb_mapping_t vrb_to_prb_mapping; vrb_to_prb_mapping_t vrb_to_prb_mapping;
uint8_t dai; uint8_t dai;
@@ -523,7 +528,6 @@ typedef struct {
uint16_t dlDataScramblingId; uint16_t dlDataScramblingId;
uint16_t pduBitmap; uint16_t pduBitmap;
uint32_t k1_feedback; uint32_t k1_feedback;
uint8_t ldpcBaseGraph;
uint8_t numCsiRsForRateMatching; uint8_t numCsiRsForRateMatching;
fapi_nr_dl_config_csirs_pdu_rel15_t csiRsForRateMatching[NFAPI_MAX_NUM_CSI_RATEMATCH]; fapi_nr_dl_config_csirs_pdu_rel15_t csiRsForRateMatching[NFAPI_MAX_NUM_CSI_RATEMATCH];
} fapi_nr_dl_config_dlsch_pdu_rel15_t; } fapi_nr_dl_config_dlsch_pdu_rel15_t;
@@ -1374,127 +1374,94 @@ void nr_pdsch_ptrs_processing(int nbRx,
int nl, int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol], c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
NR_DL_UE_HARQ_t *dlsch0_harq, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch1_harq,
uint8_t nr_slot_rx, uint8_t nr_slot_rx,
unsigned char symbol, unsigned char symbol,
int nb_rb, int nb_rb,
uint16_t rnti, uint16_t rnti,
NR_UE_DLSCH_t dlsch[2]) uint16_t *ptrsSymbPos,
uint8_t *ptrsSymbIdx)
{ {
//#define DEBUG_DL_PTRS 1 //#define DEBUG_DL_PTRS 1
int32_t *ptrs_re_symbol = NULL; int32_t *ptrs_re_symbol = NULL;
int8_t ret = 0; int8_t ret = 0;
/* harq specific variables */ /* harq specific variables */
uint8_t symbInSlot = 0; int symbInSlot = dlsch_config->start_symbol + dlsch_config->number_symbols;
uint16_t *startSymbIndex = NULL; int startSymbIndex = dlsch_config->start_symbol;
uint16_t *nbSymb = NULL; int nbSymb = dlsch_config->number_symbols;
uint8_t *L_ptrs = NULL; int L_ptrs = dlsch_config->PTRSTimeDensity;
uint8_t *K_ptrs = NULL; int K_ptrs = dlsch_config->PTRSFreqDensity;
uint16_t *dmrsSymbPos = NULL; int dmrsSymbPos = dlsch_config->dlDmrsSymbPos;
uint16_t *ptrsSymbPos = NULL; int ptrsReOffset = dlsch_config->PTRSReOffset;
uint8_t *ptrsSymbIdx = NULL; int nscid = dlsch_config->nscid;
uint8_t *ptrsReOffset = NULL;
int nscid = 0;
if(dlsch0_harq->status == NR_ACTIVE) {
symbInSlot = dlsch[0].dlsch_config.start_symbol + dlsch[0].dlsch_config.number_symbols;
startSymbIndex = &dlsch[0].dlsch_config.start_symbol;
nbSymb = &dlsch[0].dlsch_config.number_symbols;
L_ptrs = &dlsch[0].dlsch_config.PTRSTimeDensity;
K_ptrs = &dlsch[0].dlsch_config.PTRSFreqDensity;
dmrsSymbPos = &dlsch[0].dlsch_config.dlDmrsSymbPos;
ptrsReOffset = &dlsch[0].dlsch_config.PTRSReOffset;
ptrsSymbPos = &dlsch[0].ptrs_symbols;
ptrsSymbIdx = &dlsch[0].ptrs_symbol_index;
nscid = dlsch[0].dlsch_config.nscid;
}
if(dlsch1_harq) {
symbInSlot = dlsch[1].dlsch_config.start_symbol + dlsch[1].dlsch_config.number_symbols;
startSymbIndex = &dlsch[1].dlsch_config.start_symbol;
nbSymb = &dlsch[1].dlsch_config.number_symbols;
L_ptrs = &dlsch[1].dlsch_config.PTRSTimeDensity;
K_ptrs = &dlsch[1].dlsch_config.PTRSFreqDensity;
dmrsSymbPos = &dlsch[1].dlsch_config.dlDmrsSymbPos;
ptrsReOffset = &dlsch[1].dlsch_config.PTRSReOffset;
ptrsSymbPos = &dlsch[1].ptrs_symbols;
ptrsSymbIdx = &dlsch[1].ptrs_symbol_index;
nscid = dlsch[1].dlsch_config.nscid;
}
/* loop over antennas */ /* loop over antennas */
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
c16_t *phase_per_symbol = (c16_t*)ptrs_phase_per_slot[aarx]; c16_t *phase_per_symbol = (c16_t*)ptrs_phase_per_slot[aarx];
ptrs_re_symbol = (int32_t*)ptrs_re_per_slot[aarx]; ptrs_re_symbol = (int32_t*)ptrs_re_per_slot[aarx];
ptrs_re_symbol[symbol] = 0; ptrs_re_symbol[symbol] = 0;
phase_per_symbol[symbol].i = 0; // Imag phase_per_symbol[symbol].i = 0; // Imag
/* set DMRS estimates to 0 angle with magnitude 1 */ /* set DMRS estimates to 0 angle with magnitude 1 */
if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { if(is_dmrs_symbol(symbol, dmrsSymbPos)) {
/* set DMRS real estimation to 32767 */ /* set DMRS real estimation to 32767 */
phase_per_symbol[symbol].r=INT16_MAX; // 32767 phase_per_symbol[symbol].r=INT16_MAX; // 32767
#ifdef DEBUG_DL_PTRS #ifdef DEBUG_DL_PTRS
printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i); printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i);
#endif #endif
} } else { // real ptrs value is set to 0
else { // real ptrs value is set to 0
phase_per_symbol[symbol].r = 0; // Real phase_per_symbol[symbol].r = 0; // Real
} }
if(dlsch0_harq->status == NR_ACTIVE) { if (symbol == startSymbIndex) {
if(symbol == *startSymbIndex) { *ptrsSymbPos = 0;
*ptrsSymbPos = 0; set_ptrs_symb_idx(ptrsSymbPos, nbSymb, startSymbIndex, 1 << L_ptrs, dmrsSymbPos);
set_ptrs_symb_idx(ptrsSymbPos, }
*nbSymb, /* if not PTRS symbol set current ptrs symbol index to zero*/
*startSymbIndex, *ptrsSymbIdx = 0;
1<< *L_ptrs, /* Check if current symbol contains PTRS */
*dmrsSymbPos); if (is_ptrs_symbol(symbol, *ptrsSymbPos)) {
} *ptrsSymbIdx = symbol;
/* if not PTRS symbol set current ptrs symbol index to zero*/ /*------------------------------------------------------------------------------------------------------- */
*ptrsSymbIdx = 0; /* 1) Estimate common phase error per PTRS symbol */
/* Check if current symbol contains PTRS */ /*------------------------------------------------------------------------------------------------------- */
if(is_ptrs_symbol(symbol, *ptrsSymbPos)) { const uint32_t *gold =
*ptrsSymbIdx = symbol;
/*------------------------------------------------------------------------------------------------------- */
/* 1) Estimate common phase error per PTRS symbol */
/*------------------------------------------------------------------------------------------------------- */
const uint32_t *gold =
nr_gold_pdsch(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, frame_parms->Nid_cell, nscid, nr_slot_rx, symbol); nr_gold_pdsch(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, frame_parms->Nid_cell, nscid, nr_slot_rx, symbol);
nr_ptrs_cpe_estimation(*K_ptrs, nr_ptrs_cpe_estimation(K_ptrs,
*ptrsReOffset, ptrsReOffset,
nb_rb, nb_rb,
rnti, rnti,
frame_parms->ofdm_symbol_size, frame_parms->ofdm_symbol_size,
rxdataF_comp[symbol][0][aarx], rxdataF_comp[symbol][0][aarx],
gold, gold,
(int16_t *)&phase_per_symbol[symbol], (int16_t *)&phase_per_symbol[symbol],
&ptrs_re_symbol[symbol]); &ptrs_re_symbol[symbol]);
} }
}// HARQ 0
/* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
if(symbol == (symbInSlot -1)) { if (symbol == (symbInSlot -1)) {
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 2) Interpolate PTRS estimated value in TD */ /* 2) Interpolate PTRS estimated value in TD */
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* If L-PTRS is > 0 then we need interpolation */ /* If L-PTRS is > 0 then we need interpolation */
if(*L_ptrs > 0) { if (L_ptrs > 0) {
ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, *startSymbIndex, *nbSymb); ret = nr_ptrs_process_slot(dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, startSymbIndex, nbSymb);
if(ret != 0) { if(ret != 0) {
LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
} }
} }
#ifdef DEBUG_DL_PTRS #ifdef DEBUG_DL_PTRS
LOG_M("ptrsEst.m","est",ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); LOG_M("ptrsEst.m","est", ptrs_phase_per_slot[aarx], frame_parms->symbols_per_slot, 1, 1);
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + (*startSymbIndex) * rx_size_symbol, rx_size_symbol * (*nbSymb), 1, 1); LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + startSymbIndex * rx_size_symbol, rx_size_symbol * nbSymb, 1, 1);
#endif #endif
/*------------------------------------------------------------------------------------------------------- */ /*------------------------------------------------------------------------------------------------------- */
/* 3) Compensated DMRS based estimated signal with PTRS estimation */ /* 3) Compensated DMRS based estimated signal with PTRS estimation */
/*--------------------------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------------------------*/
for(uint8_t i = *startSymbIndex; i < symbInSlot; i++) { for(uint8_t i = startSymbIndex; i < symbInSlot; i++) {
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
/* Skip rotation if the slot processing is wrong */ /* Skip rotation if the slot processing is wrong */
if((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) { if((!is_dmrs_symbol(i, dmrsSymbPos)) && (ret == 0)) {
#ifdef DEBUG_DL_PTRS #ifdef DEBUG_DL_PTRS
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i);
#endif #endif
rotate_cpx_vector(rxdataF_comp[i][0][aarx], &phase_per_symbol[i], rxdataF_comp[i][0][aarx], nb_rb * NR_NB_SC_PER_RB, 15); rotate_cpx_vector(rxdataF_comp[i][0][aarx], &phase_per_symbol[i], rxdataF_comp[i][0][aarx], nb_rb * NR_NB_SC_PER_RB, 15);
}// if not DMRS Symbol }// if not DMRS Symbol
@@ -126,13 +126,13 @@ void nr_pdsch_ptrs_processing(int nbRx,
int nl, int nl,
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol], c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
NR_DL_UE_HARQ_t *dlsch0_harq, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch1_harq,
uint8_t nr_slot_rx, uint8_t nr_slot_rx,
unsigned char symbol, unsigned char symbol,
int nb_rb, int nb_rb,
uint16_t rnti, uint16_t rnti,
NR_UE_DLSCH_t dlsch[2]); uint16_t *ptrsSymbPos,
uint8_t *ptrsSymbIdx);
int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue, int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue,
sl_nr_ue_phy_params_t *sl_phy_params, sl_nr_ue_phy_params_t *sl_phy_params,
@@ -170,7 +170,7 @@ static void send_ssb_rsrp_meas(PHY_VARS_NR_UE *ue,
nr_downlink_indication_t dl_indication = {0}; nr_downlink_indication_t dl_indication = {0};
fapi_nr_rx_indication_t rx_ind = {0}; fapi_nr_rx_indication_t rx_ind = {0};
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, &l1_measurements, NULL); nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, &l1_measurements, NULL);
ue->if_inst->dl_indication(&dl_indication); ue->if_inst->dl_indication(&dl_indication);
} }
+1 -1
View File
@@ -961,6 +961,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
nr_downlink_indication_t dl_indication; nr_downlink_indication_t dl_indication;
fapi_nr_rx_indication_t rx_ind = {0}; fapi_nr_rx_indication_t rx_ind = {0};
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, (void *)&l1_measurements, NULL); nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, (void *)&l1_measurements, NULL);
ue->if_inst->dl_indication(&dl_indication); ue->if_inst->dl_indication(&dl_indication);
} }
+185 -244
View File
@@ -43,178 +43,143 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch, NR_UE_DLSCH_t *dlsch,
int16_t **dlsch_llr, int cw_idx,
uint8_t **b, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
int *G, int16_t *dlsch_llr,
int nb_dlsch, uint8_t *b,
int number_rbs, int number_rbs,
uint8_t *DLSCH_ids) int G)
{ {
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch]; nrLDPC_TB_decoding_parameters_t TB_parameters = {0};
memset(TBs, 0, sizeof(TBs));
nrLDPC_slot_decoding_parameters_t slot_parameters = { nrLDPC_slot_decoding_parameters_t slot_parameters = {
.frame = proc->frame_rx, .frame = proc->frame_rx,
.slot = proc->nr_slot_rx, .slot = proc->nr_slot_rx,
.nb_TBs = nb_dlsch, .nb_TBs = 1,
.threadPool = &get_nrUE_params()->Tpool, .threadPool = &get_nrUE_params()->Tpool,
.TBs = TBs .TBs = &TB_parameters
}; };
int max_num_segments = 0; uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
int harq_pid = dlsch_config->harq_process_nbr;
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
fapi_nr_dl_cw_info_t *cw_info = &dlsch->cw_info;
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[cw_idx][dlsch_config->harq_process_nbr];
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, cw_info->rv);
uint8_t nb_re_dmrs;
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
else
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) { TB_parameters.harq_unique_pid = 2 * harq_pid + cw_idx;
uint8_t DLSCH_id = DLSCH_ids[pdsch_id]; TB_parameters.G = G;
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config; TB_parameters.nb_rb = number_rbs;
uint8_t dmrs_Type = dlsch_config->dmrsConfigType; TB_parameters.Qm = cw_info->qamModOrder;
int harq_pid = dlsch_config->harq_process_nbr; TB_parameters.mcs = cw_info->mcs;
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid]; TB_parameters.nb_layers = cw_info->Nl;
TB_parameters.BG = cw_info->ldpcBaseGraph;
TB_parameters.A = cw_info->TBS;
TB_parameters.processedSegments = &harq_process->processedSegments;
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); float Coderate = (float)cw_info->targetCodeRate / 10240.0f;
uint8_t nb_re_dmrs;
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv); LOG_D(PHY,
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
else
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
if (!harq_process) {
LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n");
return;
}
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
/* Neither harq_pid nor DLSCH_id are unique in the instance
* but their combination is.
* Since DLSCH_id < 2
* then 2 * harq_pid + DLSCH_id is unique.
*/
TB_parameters->harq_unique_pid = 2 * harq_pid + DLSCH_id;
// ------------------------------------------------------------------
TB_parameters->G = G[DLSCH_id];
TB_parameters->nb_rb = number_rbs;
TB_parameters->Qm = dlsch_config->qamModOrder;
TB_parameters->mcs = dlsch_config->mcs;
TB_parameters->nb_layers = dlsch[DLSCH_id].Nl;
TB_parameters->BG = dlsch_config->ldpcBaseGraph;
TB_parameters->A = dlsch_config->TBS;
// ------------------------------------------------------------------
TB_parameters->processedSegments = &harq_process->processedSegments;
float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f;
LOG_D(
PHY,
"%d.%d DLSCH %d Decoding, harq_pid %d TBS %d G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d " "%d.%d DLSCH %d Decoding, harq_pid %d TBS %d G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d "
"Coderate %f\n", "Coderate %f\n",
slot_parameters.frame, slot_parameters.frame,
slot_parameters.slot, slot_parameters.slot,
DLSCH_id, cw_idx,
harq_pid, harq_pid,
dlsch_config->TBS, cw_info->TBS,
TB_parameters->G, G,
nb_re_dmrs, nb_re_dmrs,
dmrs_length, dmrs_length,
TB_parameters->mcs, TB_parameters.mcs,
TB_parameters->nb_layers, TB_parameters.nb_layers,
dlsch_config->number_symbols, dlsch_config->number_symbols,
TB_parameters->nb_rb, TB_parameters.nb_rb,
TB_parameters->Qm, TB_parameters.Qm,
Coderate); Coderate);
if (harq_process->first_rx == 1) { if (harq_process->first_rx == 1) {
// This is a new packet, so compute quantities regarding segmentation // This is a new packet, so compute quantities regarding segmentation
nr_segmentation(NULL, nr_segmentation(NULL,
NULL, NULL,
lenWithCrc(1, TB_parameters->A), // We give a max size in case of 1 segment lenWithCrc(1, TB_parameters.A), // We give a max size in case of 1 segment
&TB_parameters->C, &TB_parameters.C,
&TB_parameters->K, &TB_parameters.K,
&TB_parameters->Z, // [hna] Z is Zc &TB_parameters.Z, // [hna] Z is Zc
&TB_parameters->F, &TB_parameters.F,
TB_parameters->BG); TB_parameters.BG);
harq_process->C = TB_parameters->C; harq_process->C = TB_parameters.C;
harq_process->K = TB_parameters->K; harq_process->K = TB_parameters.K;
harq_process->Z = TB_parameters->Z; harq_process->Z = TB_parameters.Z;
harq_process->F = TB_parameters->F; harq_process->F = TB_parameters.F;
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers) { if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters.nb_layers) {
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A); LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters.A);
return; return;
}
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100))
LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_parameters->nb_layers);
// clear HARQ buffer
for (int i = 0; i < harq_process->C; i++)
memset(harq_process->d[i], 0, 5 * 8448 * sizeof(int16_t));
} else {
// This is not a new packet, so retrieve previously computed quantities regarding segmentation
TB_parameters->C = harq_process->C;
TB_parameters->K = harq_process->K;
TB_parameters->Z = harq_process->Z;
TB_parameters->F = harq_process->F;
} }
max_num_segments = max(max_num_segments, TB_parameters->C);
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100))
LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K); LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_parameters.nb_layers);
// clear HARQ buffer
TB_parameters->max_ldpc_iterations = dlsch[DLSCH_id].max_ldpc_iterations; for (int i = 0; i < harq_process->C; i++)
TB_parameters->rv_index = dlsch_config->rv; memset(harq_process->d[i], 0, 5 * 8448 * sizeof(int16_t));
TB_parameters->tbslbrm = dlsch_config->tbslbrm; } else {
TB_parameters->abort_decode = &harq_process->abort_decode; // This is not a new packet, so retrieve previously computed quantities regarding segmentation
set_abort(&harq_process->abort_decode, false); TB_parameters.C = harq_process->C;
TB_parameters.K = harq_process->K;
TB_parameters.Z = harq_process->Z;
TB_parameters.F = harq_process->F;
} }
nrLDPC_segment_decoding_parameters_t segments[nb_dlsch][max_num_segments]; if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K);
TB_parameters.max_ldpc_iterations = dlsch->max_ldpc_iterations;
TB_parameters.rv_index = cw_info->rv;
TB_parameters.tbslbrm = dlsch_config->tbslbrm;
TB_parameters.abort_decode = &harq_process->abort_decode;
set_abort(&harq_process->abort_decode, false);
nrLDPC_segment_decoding_parameters_t segments[TB_parameters.C];
memset(segments, 0, sizeof(segments)); memset(segments, 0, sizeof(segments));
bool d_to_be_cleared[nb_dlsch][max_num_segments]; bool d_to_be_cleared[TB_parameters.C];
memset(d_to_be_cleared, 0, sizeof(d_to_be_cleared)); memset(d_to_be_cleared, 0, sizeof(d_to_be_cleared));
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) { TB_parameters.segments = segments;
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
int harq_pid = dlsch_config->harq_process_nbr;
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id]; uint32_t r_offset = 0;
TB_parameters->segments = segments[pdsch_id]; for (int r = 0; r < TB_parameters.C; r++) {
if (harq_process->first_rx == 1)
d_to_be_cleared[r] = true;
else
d_to_be_cleared[r] = false;
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters.segments[r];
segment_parameters->E = nr_get_E(TB_parameters.G,
TB_parameters.C,
TB_parameters.Qm,
TB_parameters.nb_layers,
r);
segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters.rv_index,
segment_parameters->E,
TB_parameters.BG,
TB_parameters.Z,
&harq_process->llrLen,
harq_process->DLround);
segment_parameters->llr = dlsch_llr + r_offset;
segment_parameters->d = harq_process->d[r];
segment_parameters->d_to_be_cleared = &d_to_be_cleared[r];
segment_parameters->c = harq_process->c[r];
segment_parameters->decodeSuccess = false;
uint32_t r_offset = 0; reset_meas(&segment_parameters->ts_deinterleave);
for (int r = 0; r < TB_parameters->C; r++) { reset_meas(&segment_parameters->ts_rate_unmatch);
if (harq_process->first_rx == 1) reset_meas(&segment_parameters->ts_ldpc_decode);
d_to_be_cleared[pdsch_id][r] = true;
else
d_to_be_cleared[pdsch_id][r] = false;
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
segment_parameters->E = nr_get_E(TB_parameters->G,
TB_parameters->C,
TB_parameters->Qm,
TB_parameters->nb_layers,
r);
segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters->rv_index,
segment_parameters->E,
TB_parameters->BG,
TB_parameters->Z,
&harq_process->llrLen,
harq_process->DLround);
segment_parameters->llr = dlsch_llr[DLSCH_id] + r_offset;
segment_parameters->d = harq_process->d[r];
segment_parameters->d_to_be_cleared = &d_to_be_cleared[pdsch_id][r];
segment_parameters->c = harq_process->c[r];
segment_parameters->decodeSuccess = false;
reset_meas(&segment_parameters->ts_deinterleave); r_offset += segment_parameters->E;
reset_meas(&segment_parameters->ts_rate_unmatch);
reset_meas(&segment_parameters->ts_ldpc_decode);
r_offset += segment_parameters->E;
}
} }
int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters); int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
@@ -224,114 +189,90 @@ void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
return; return;
} }
// post decode uint32_t offset = 0;
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) { for (int r = 0; r < TB_parameters.C; r++) {
uint8_t DLSCH_id = DLSCH_ids[pdsch_id]; nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters.segments[r];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config; if (segment_parameters->decodeSuccess) {
int harq_pid = dlsch_config->harq_process_nbr; memcpy(b + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
uint32_t offset = 0;
for (int r = 0; r < TB_parameters->C; r++) {
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
if (segment_parameters->decodeSuccess) {
memcpy(b[DLSCH_id] + offset,
harq_process->c[r],
(harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
} else {
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
LOG_D(PHY, "frame=%d, slot=%d, first_rx=%d, rv_index=%d\n", proc->frame_rx, proc->nr_slot_rx, harq_process->first_rx, dlsch_config->rv);
LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C);
LOG_D(PHY, "DLSCH %d in error\n", DLSCH_id);
}
offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &segment_parameters->ts_deinterleave);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &segment_parameters->ts_rate_unmatch);
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &segment_parameters->ts_ldpc_decode);
}
kpiStructure.nb_total++;
kpiStructure.blockSize = dlsch_config->TBS;
kpiStructure.dl_mcs = dlsch_config->mcs;
kpiStructure.nofRBs = number_rbs;
harq_process->decodeResult = harq_process->processedSegments == harq_process->C;
if (harq_process->decodeResult && harq_process->C > 1) {
/* check global CRC */
int A = dlsch->dlsch_config.TBS;
// we have regrouped the transport block
if (!check_crc(b[DLSCH_id], lenWithCrc(1, A), crcType(1, A))) {
LOG_E(PHY,
" Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_process->C);
harq_process->decodeResult = false;
}
}
if (harq_process->decodeResult) {
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we
const int sz = dlsch->dlsch_config.TBS / 8;
if (b[DLSCH_id][sz] == 0 && b[DLSCH_id][sz + 1] == 0) {
// do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24)
int i = 0;
while (b[DLSCH_id][i] == 0 && i < sz)
i++;
if (i == sz) {
LOG_E(PHY,
"received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the "
"corresponding CRC, and nothing prevents to have a all 0 packet\n");
harq_process->decodeResult = false;
}
}
}
if (harq_process->decodeResult) {
LOG_D(PHY, "DLSCH received ok \n");
harq_process->status = NR_SCH_IDLE;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
} else { } else {
LOG_D(PHY, "DLSCH received nok \n"); LOG_D(PHY, "frame=%d, slot=%d, first_rx=%d, rv_index=%d\n", proc->frame_rx, proc->nr_slot_rx, harq_process->first_rx, cw_info->rv);
kpiStructure.nb_nack++; LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C);
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
} }
offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0);
uint8_t dmrs_Type = dlsch_config->dmrsConfigType; merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &segment_parameters->ts_deinterleave);
uint8_t nb_re_dmrs; merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &segment_parameters->ts_rate_unmatch);
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &segment_parameters->ts_ldpc_decode);
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
else
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f;
LOG_D(PHY,
"%d.%d DLSCH Decoded, harq_pid %d, round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d "
"nb_symb_sch %d "
"nb_rb %d Qm %d Coderate %f\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_pid,
harq_process->DLround,
harq_process->decodeResult,
dlsch->dlsch_config.TBS,
dlsch->dlsch_config.TBS / 8,
G[DLSCH_id],
nb_re_dmrs,
dmrs_length,
dlsch->dlsch_config.mcs,
dlsch->Nl,
dlsch_config->number_symbols,
number_rbs,
dlsch_config->qamModOrder,
Coderate);
} }
kpiStructure.nb_total++;
kpiStructure.blockSize = cw_info->TBS;
kpiStructure.dl_mcs = cw_info->mcs;
kpiStructure.nofRBs = number_rbs;
harq_process->decodeResult = harq_process->processedSegments == harq_process->C;
if (harq_process->decodeResult && harq_process->C > 1) {
/* check global CRC */
// we have regrouped the transport block
if (!check_crc(b, lenWithCrc(1, cw_info->TBS), crcType(1, cw_info->TBS))) {
LOG_E(PHY,
" Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_process->C);
harq_process->decodeResult = false;
}
}
if (harq_process->decodeResult) {
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we
const int sz = cw_info->TBS / 8;
if (b[sz] == 0 && b[sz + 1] == 0) {
// do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24)
int i = 0;
while (b[i] == 0 && i < sz)
i++;
if (i == sz) {
LOG_E(PHY,
"received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the "
"corresponding CRC, and nothing prevents to have a all 0 packet\n");
harq_process->decodeResult = false;
}
}
}
if (harq_process->decodeResult) {
LOG_D(PHY, "DLSCH received ok \n");
harq_process->status = NR_SCH_IDLE;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
} else {
LOG_D(PHY, "DLSCH received nok \n");
kpiStructure.nb_nack++;
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
}
LOG_D(PHY,
"%d.%d DLSCH Decoded, harq_pid %d, cw_idx %d round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d "
"nb_symb_sch %d "
"nb_rb %d Qm %d Coderate %f\n",
proc->frame_rx,
proc->nr_slot_rx,
harq_pid,
cw_idx,
harq_process->DLround,
harq_process->decodeResult,
cw_info->TBS,
cw_info->TBS / 8,
G,
nb_re_dmrs,
dmrs_length,
cw_info->mcs,
cw_info->Nl,
dlsch_config->number_symbols,
number_rbs,
cw_info->qamModOrder,
Coderate);
} }
@@ -856,12 +856,12 @@ static void nr_dlsch_layer_demapping(const uint8_t Nl,
const uint8_t mod_order, const uint8_t mod_order,
const int llrLayerSize, const int llrLayerSize,
const int16_t llr_layers[NR_SYMBOLS_PER_SLOT][Nl][llrLayerSize], const int16_t llr_layers[NR_SYMBOLS_PER_SLOT][Nl][llrLayerSize],
const NR_UE_DLSCH_t *dlsch, const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
const uint32_t re_len[NR_SYMBOLS_PER_SLOT], const uint32_t re_len[NR_SYMBOLS_PER_SLOT],
int16_t *llr) int16_t *llr)
{ {
const int s0 = dlsch->dlsch_config.start_symbol; const int s0 = dlsch_config->start_symbol;
const int s1 = dlsch->dlsch_config.number_symbols; const int s1 = dlsch_config->number_symbols;
int k = 0; int k = 0;
switch (Nl) { switch (Nl) {
@@ -901,28 +901,28 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch,
const c16_t dl_ch_magb[rx_size_symbol], const c16_t dl_ch_magb[rx_size_symbol],
const c16_t dl_ch_magr[rx_size_symbol], const c16_t dl_ch_magr[rx_size_symbol],
const int nb_antennas_rx, const int nb_antennas_rx,
const c16_t rxdataF_comp[dlsch->Nl][nb_antennas_rx][rx_size_symbol], const c16_t rxdataF_comp[dlsch->cw_info.Nl][nb_antennas_rx][rx_size_symbol],
const int llrSize, const int llrSize,
int16_t layer_llr[dlsch->Nl][llrSize]) int16_t layer_llr[dlsch->cw_info.Nl][llrSize])
{ {
switch (dlsch->dlsch_config.qamModOrder) { switch (dlsch->cw_info.qamModOrder) {
case 2 : case 2 :
for (int l = 0; l < dlsch[0].Nl; l++) for (int l = 0; l < dlsch->cw_info.Nl; l++)
nr_qpsk_llr(rxdataF_comp[l][0], layer_llr[l], len); nr_qpsk_llr(rxdataF_comp[l][0], layer_llr[l], len);
break; break;
case 4 : case 4 :
for (int l = 0; l < dlsch[0].Nl; l++) for (int l = 0; l < dlsch->cw_info.Nl; l++)
nr_16qam_llr(rxdataF_comp[l][0], dl_ch_mag, layer_llr[l], len); nr_16qam_llr(rxdataF_comp[l][0], dl_ch_mag, layer_llr[l], len);
break; break;
case 6 : case 6 :
for(int l=0; l < dlsch[0].Nl; l++) for(int l=0; l < dlsch->cw_info.Nl; l++)
nr_64qam_llr(rxdataF_comp[l][0], dl_ch_mag, dl_ch_magb, layer_llr[l], len); nr_64qam_llr(rxdataF_comp[l][0], dl_ch_mag, dl_ch_magb, layer_llr[l], len);
break; break;
case 8: case 8:
for(int l=0; l < dlsch[0].Nl; l++) for(int l=0; l < dlsch->cw_info.Nl; l++)
nr_256qam_llr(rxdataF_comp[l][0], nr_256qam_llr(rxdataF_comp[l][0],
dl_ch_mag, dl_ch_mag,
dl_ch_magb, dl_ch_magb,
@@ -943,23 +943,25 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch,
/* Main Function */ /* Main Function */
int nr_rx_pdsch(PHY_VARS_NR_UE *ue, int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t dlsch[2], NR_UE_DLSCH_t *dlsch,
const freq_alloc_bitmap_t *freq_alloc, const freq_alloc_bitmap_t *freq_alloc,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch_harq,
unsigned char symbol, unsigned char symbol,
bool first_symbol_flag, bool first_symbol_flag,
unsigned char harq_pid, unsigned char harq_pid,
uint32_t pdsch_est_size, uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size], int32_t dl_ch_estimates[][pdsch_est_size],
int16_t *llr[2], int16_t *llr,
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT], uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int32_t *log2_maxh, int32_t *log2_maxh,
int rx_size_symbol, int rx_size_symbol,
int nbRx, int nbRx,
c16_t rxdataF_comp[][dlsch->Nl][nbRx][rx_size_symbol], c16_t rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->Nl][nbRx][rx_size_symbol], c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->Nl][nbRx][rx_size_symbol], c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol], c16_t dl_ch_magr[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT], c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT], int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
int G, int G,
@@ -967,7 +969,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
pdsch_scope_req_t *scope_req) pdsch_scope_req_t *scope_req)
{ {
NR_DL_FRAME_PARMS *fp = &ue->frame_parms; NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
const int nl = dlsch[0].Nl; const int nl = dlsch->cw_info.Nl;
const int n_rx = fp->nb_antennas_rx; const int n_rx = fp->nb_antennas_rx;
const int matrixSz = n_rx * nl; const int matrixSz = n_rx * nl;
__attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol]; __attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol];
@@ -979,72 +981,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
const int gNB_id = proc->gNB_id; const int gNB_id = proc->gNB_id;
uint8_t slot = 0; uint8_t slot = 0;
int32_t codeword_TB0 = -1;
int32_t codeword_TB1 = -1;
uint32_t nb_re_pdsch = -1; uint32_t nb_re_pdsch = -1;
DevAssert(dlsch_harq);
NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL;
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
if (NR_MAX_NB_LAYERS>4)
dlsch1_harq = &ue->dl_harq_processes[1][harq_pid];
if (dlsch0_harq && dlsch1_harq){
LOG_D(PHY,
"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n",
frame,
nr_slot_rx,
symbol,
harq_pid,
dlsch0_harq->status,
dlsch1_harq->status);
if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){
codeword_TB0 = dlsch0_harq->codeword; // SV: where is this set? revisit for DL MIMO.
codeword_TB1 = dlsch1_harq->codeword;
dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid];
dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid];
DEBUG_HARQ("[DEMOD] I am assuming both TBs are active, in cw0 %d and cw1 %d \n", codeword_TB0, codeword_TB1);
} else if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status != NR_ACTIVE) ) {
codeword_TB0 = dlsch0_harq->codeword;
dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid];
dlsch1_harq = NULL;
DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active, in cw %d \n", codeword_TB0);
} else if ((dlsch0_harq->status != NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){
codeword_TB1 = dlsch1_harq->codeword;
dlsch0_harq = NULL;
dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid];
DEBUG_HARQ("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", codeword_TB1);
LOG_E(PHY, "[DEMOD] slot %d TB0 not active and TB1 active case is not supported\n", nr_slot_rx);
return -1;
} else {
LOG_E(PHY, "[DEMOD] slot %d: no active DLSCH (2 layers case)\n", nr_slot_rx);
return (-1);
}
} else if (dlsch0_harq) {
if (dlsch0_harq->status == NR_ACTIVE) {
codeword_TB0 = dlsch0_harq->codeword;
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active\n");
} else {
LOG_E(PHY, "[DEMOD] slot %d nr_rx_pdsch no active DLSCH (one layer case)\n", nr_slot_rx);
return (-1);
}
} else {
LOG_E(PHY, "[DEMOD] slot %d Inconsistent call to nr_rx_pdsch (no layer 0)\n", nr_slot_rx);
return -1;
}
DEBUG_HARQ("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1);
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config;
DevAssert(dlsch0_harq);
if (gNB_id > 2) { if (gNB_id > 2) {
LOG_E(PHY, "Illegal gNB_id %d\n", gNB_id); LOG_E(PHY, "Illegal gNB_id %d\n", gNB_id);
@@ -1229,7 +1167,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
fp, fp,
symbol, symbol,
nb_re_pdsch, nb_re_pdsch,
dlsch_config->qamModOrder, dlsch->cw_info.qamModOrder,
nb_rb_pdsch, nb_rb_pdsch,
*log2_maxh); // log2_maxh+I0_shift *log2_maxh); // log2_maxh+I0_shift
stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_COMPENSATION_STATS); stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_COMPENSATION_STATS);
@@ -1286,7 +1224,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
dl_ch_magb[symbol], dl_ch_magb[symbol],
dl_ch_magr[symbol], dl_ch_magr[symbol],
dl_ch_estimates_ext, dl_ch_estimates_ext,
dlsch_config->qamModOrder, dlsch->cw_info.qamModOrder,
*log2_maxh, *log2_maxh,
symbol, symbol,
nb_re_pdsch, nb_re_pdsch,
@@ -1312,14 +1250,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
int nbSymb = 0; int nbSymb = 0;
int pduBitmap = 0; int pduBitmap = 0;
if(dlsch0_harq->status == NR_ACTIVE) { if(dlsch_harq->status == NR_ACTIVE) {
startSymbIdx = dlsch_config->start_symbol; startSymbIdx = dlsch_config->start_symbol;
nbSymb = dlsch_config->number_symbols; nbSymb = dlsch_config->number_symbols;
pduBitmap = dlsch_config->pduBitmap; pduBitmap = dlsch_config->pduBitmap;
} }
/* Check for PTRS bitmap and process it respectively */ /* Check for PTRS bitmap and process it respectively */
if((pduBitmap & 0x1) && (dlsch[0].rnti_type == TYPE_C_RNTI_)) { if((pduBitmap & 0x1) && (dlsch->rnti_type == TYPE_C_RNTI_)) {
nr_pdsch_ptrs_processing(nbRx, nr_pdsch_ptrs_processing(nbRx,
ptrs_phase_per_slot, ptrs_phase_per_slot,
ptrs_re_per_slot, ptrs_re_per_slot,
@@ -1327,13 +1265,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
nl, nl,
rxdataF_comp, rxdataF_comp,
fp, fp,
dlsch0_harq, dlsch_config,
dlsch1_harq,
nr_slot_rx, nr_slot_rx,
symbol, symbol,
freq_alloc->num_rbs, freq_alloc->num_rbs,
dlsch[0].rnti, dlsch->rnti,
dlsch); &dlsch->ptrs_symbols,
&dlsch->ptrs_symbol_index);
dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol]; dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol];
} }
/* at last symbol in a slot calculate LLR's for whole slot */ /* at last symbol in a slot calculate LLR's for whole slot */
@@ -1341,7 +1279,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
/* create LLR layer buffer */ /* create LLR layer buffer */
int max_symb_re = 0; int max_symb_re = 0;
GET_ARRAY_MAX(dl_valid_re, NR_SYMBOLS_PER_SLOT, max_symb_re); GET_ARRAY_MAX(dl_valid_re, NR_SYMBOLS_PER_SLOT, max_symb_re);
const int llr_per_symbol = max_symb_re * dlsch->dlsch_config.qamModOrder; const int llr_per_symbol = max_symb_re * dlsch->cw_info.qamModOrder;
__attribute__((aligned(32))) int16_t layer_llr[NR_SYMBOLS_PER_SLOT][nl][llr_per_symbol]; __attribute__((aligned(32))) int16_t layer_llr[NR_SYMBOLS_PER_SLOT][nl][llr_per_symbol];
// Generate LLR from PTRS compensated signal // Generate LLR from PTRS compensated signal
@@ -1360,14 +1298,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
} }
stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS); stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS);
start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING); start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
nr_dlsch_layer_demapping(nl, dlsch_config->qamModOrder, llr_per_symbol, layer_llr, dlsch, dl_valid_re, llr[0]); nr_dlsch_layer_demapping(nl, dlsch->cw_info.qamModOrder, llr_per_symbol, layer_llr, dlsch_config, dl_valid_re, llr);
stop_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING); stop_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
/*
for (int i=0; i < 2; i++){
snprintf(filename, 50, "llr%d_symb_%d_nr_slot_rx_%d.m", i, symbol, nr_slot_rx);
write_output(filename,"llr", &llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb_pdsch*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb_pdsch*4*dlsch1_harq->Qm), 1, 0);
}
*/
if (UEScopeHasTryLock(ue)) { if (UEScopeHasTryLock(ue)) {
metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx }; metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx };
int total_valid_res = 0; int total_valid_res = 0;
@@ -446,7 +446,8 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
nr_fill_rx_indication(&rx_ind, nr_fill_rx_indication(&rx_ind,
FAPI_NR_RX_PDU_TYPE_SSB, FAPI_NR_RX_PDU_TYPE_SSB,
ue, ue,
NULL, 0,
0,
NULL, NULL,
number_pdus, number_pdus,
proc, proc,
+2 -2
View File
@@ -404,7 +404,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
if (decoderState) { if (decoderState) {
if (ue) { // decoding failed in synced state if (ue) { // decoding failed in synced state
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL); nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, NULL, NULL);
if (ue->if_inst && ue->if_inst->dl_indication) if (ue->if_inst && ue->if_inst->dl_indication)
ue->if_inst->dl_indication(&dl_indication); ue->if_inst->dl_indication(&dl_indication);
} }
@@ -464,7 +464,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
if (ue) { if (ue) {
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL); nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, (void *)result, NULL);
if (ue->if_inst && ue->if_inst->dl_indication) if (ue->if_inst && ue->if_inst->dl_indication)
ue->if_inst->dl_indication(&dl_indication); ue->if_inst->dl_indication(&dl_indication);
@@ -60,19 +60,17 @@ int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb
@param[in] dlsch_llr Pointers to LLR values computed by dlsch_demodulation @param[in] dlsch_llr Pointers to LLR values computed by dlsch_demodulation
@param[in] b @param[in] b
@param[in] G array of Gs @param[in] G array of Gs
@param[in] nb_dlsch number of active downlink shared channels
@param[in] DLSCH_ids array of active downlink shared channels
@returns 0 on success, 1 on unsuccessful decoding @returns 0 on success, 1 on unsuccessful decoding
*/ */
void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t *dlsch, NR_UE_DLSCH_t *dlsch,
short **dlsch_llr, int cw_idx,
uint8_t **b, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
int *G, int16_t *dlsch_llr,
int nb_dlsch, uint8_t *b,
int number_rbs, int number_rbs,
uint8_t *DLSCH_ids); int G);
int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue, int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue,
const NR_UE_ULSCH_t *ulsch, const NR_UE_ULSCH_t *ulsch,
@@ -278,23 +276,25 @@ void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue,
*/ */
int nr_rx_pdsch(PHY_VARS_NR_UE *ue, int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t dlsch[2], NR_UE_DLSCH_t *dlsch,
const freq_alloc_bitmap_t *freq_alloc, const freq_alloc_bitmap_t *freq_alloc,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
NR_DL_UE_HARQ_t *dlsch_harq,
unsigned char symbol, unsigned char symbol,
bool first_symbol_flag, bool first_symbol_flag,
unsigned char harq_pid, unsigned char harq_pid,
uint32_t pdsch_est_size, uint32_t pdsch_est_size,
int32_t dl_ch_estimates[][pdsch_est_size], int32_t dl_ch_estimates[][pdsch_est_size],
int16_t *llr[2], int16_t *llr,
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT], uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int32_t *log2_maxh, int32_t *log2_maxh,
int rx_size_symbol, int rx_size_symbol,
int nbRx, int nbRx,
c16_t rxdataF_comp[][dlsch->Nl][nbRx][rx_size_symbol], c16_t rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_mag[][dlsch->Nl][nbRx][rx_size_symbol], c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magb[][dlsch->Nl][nbRx][rx_size_symbol], c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol], c16_t dl_ch_magr[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT], c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT], int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
int G, int G,
@@ -97,16 +97,13 @@ typedef struct {
} NR_DL_UE_HARQ_t; } NR_DL_UE_HARQ_t;
typedef struct { typedef struct {
fapi_nr_dl_cw_info_t cw_info;
/// RNTI /// RNTI
uint16_t rnti; uint16_t rnti;
/// RNTI type /// RNTI type
uint8_t rnti_type; uint8_t rnti_type;
/// Active flag for DLSCH demodulation /// Active flag for DLSCH demodulation
bool active; bool active;
/// Structure to hold dlsch config from MAC
fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
/// Number of MIMO layers (streams)
uint8_t Nl;
/// Maximum number of LDPC iterations /// Maximum number of LDPC iterations
uint8_t max_ldpc_iterations; uint8_t max_ldpc_iterations;
/// number of iterations used in last turbo decoding /// number of iterations used in last turbo decoding
+3 -2
View File
@@ -521,8 +521,9 @@ typedef struct nr_phy_data_tx_s {
typedef struct nr_phy_data_s { typedef struct nr_phy_data_s {
NR_UE_PDCCH_CONFIG phy_pdcch_config; NR_UE_PDCCH_CONFIG phy_pdcch_config;
fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
NR_UE_DLSCH_t dlsch[2]; NR_UE_DLSCH_t dlsch[2];
int n_dlsch_codewords;
// Sidelink Rx action decided by MAC // Sidelink Rx action decided by MAC
sl_nr_rx_config_type_enum_t sl_rx_action; sl_nr_rx_config_type_enum_t sl_rx_action;
NR_UE_CSI_RS csirs_vars; NR_UE_CSI_RS csirs_vars;
@@ -535,7 +536,7 @@ enum stream_status_e { STREAM_STATUS_UNSYNC, STREAM_STATUS_SYNCING, STREAM_STATU
*/ */
typedef struct nr_rxtx_thread_data_s { typedef struct nr_rxtx_thread_data_s {
UE_nr_rxtx_proc_t proc; UE_nr_rxtx_proc_t proc;
PHY_VARS_NR_UE *UE; PHY_VARS_NR_UE *UE;
int writeBlockSize; int writeBlockSize;
nr_phy_data_t phy_data; nr_phy_data_t phy_data;
dynamic_barrier_t* next_barrier; dynamic_barrier_t* next_barrier;
+3 -2
View File
@@ -102,8 +102,9 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
uint8_t pdu_type, uint8_t pdu_type,
PHY_VARS_NR_UE *ue, PHY_VARS_NR_UE *ue,
NR_UE_DLSCH_t *dlsch0, int cw_idx,
NR_UE_DLSCH_t *dlsch1, int harq_pid,
NR_UE_DLSCH_t *dlsch,
uint16_t n_pdus, uint16_t n_pdus,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
void *typeSpecific, void *typeSpecific,
+35 -34
View File
@@ -21,48 +21,44 @@ extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
const char *const dl_pdu_type[] = {"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM", "TA"}; const char *const dl_pdu_type[] = {"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM", "TA"};
const char *const ul_pdu_type[] = {"PRACH", "PUCCH", "PUSCH", "SRS"}; const char *const ul_pdu_type[] = {"PRACH", "PUCCH", "PUSCH", "SRS"};
static void configure_dlsch(NR_UE_DLSCH_t *dlsch0, static void configure_dlsch(NR_UE_DLSCH_t *dlsch,
NR_DL_UE_HARQ_t *harq_list, NR_DL_UE_HARQ_t *harq_list,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu,
NR_UE_MAC_INST_t *mac, NR_UE_MAC_INST_t *mac,
int cw_idx,
int rnti) int rnti)
{ {
const uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr; const uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr;
dlsch0->active = true; dlsch->active = true;
dlsch0->rnti = rnti; dlsch->rnti = rnti;
LOG_D(PHY,"current_harq_pid = %d\n", current_harq_pid); LOG_D(PHY,"Configure DLSCH for pid = %d\n", current_harq_pid);
NR_DL_UE_HARQ_t *dlsch0_harq = &harq_list[current_harq_pid]; NR_DL_UE_HARQ_t *dlsch_harq = &harq_list[current_harq_pid];
dlsch->cw_info = dlsch_config_pdu->cw_info[cw_idx];
//get nrOfLayers from DCI info if (dlsch->cw_info.Nl == 0) {
uint8_t Nl = 0; LOG_E(PHY, "Invalid number of layers %d for DLSCH\n", dlsch->cw_info.Nl);
for (int i = 0; i < 12; i++) { // max 12 ports
if ((dlsch_config_pdu->dmrs_ports >> i) & 0x01)
Nl += 1;
}
if (Nl == 0) {
LOG_E(PHY, "Invalid number of layers %d for DLSCH\n", Nl);
// setting NACK for this TB // setting NACK for this TB
dlsch0->active = false; dlsch->active = false;
update_harq_status(mac, current_harq_pid, 0); update_harq_status(mac, current_harq_pid, cw_idx, 0);
return; return;
} }
dlsch0->Nl = Nl;
if (dlsch_config_pdu->new_data_indicator) { if (dlsch->cw_info.new_data_indicator) {
dlsch0_harq->first_rx = true; dlsch_harq->first_rx = true;
dlsch0_harq->DLround = 0; dlsch_harq->DLround = 0;
} else { } else {
dlsch0_harq->first_rx = false; dlsch_harq->first_rx = false;
dlsch0_harq->DLround++; dlsch_harq->DLround++;
} }
downlink_harq_process(dlsch0_harq, current_harq_pid, dlsch_config_pdu->new_data_indicator, dlsch_config_pdu->rv, dlsch0->rnti_type); downlink_harq_process(dlsch_harq, current_harq_pid, dlsch->cw_info.new_data_indicator, dlsch->cw_info.rv, dlsch->rnti_type);
if (dlsch0_harq->status != NR_ACTIVE) { if (dlsch_harq->status != NR_ACTIVE) {
// dlsch0_harq->status not ACTIVE due to false retransmission // dlsch_harq->status not ACTIVE due to false retransmission
// Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status // Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status
dlsch0->active = false; dlsch->active = false;
LOG_W(NR_MAC, "dlsch0_harq->status not ACTIVE due to false retransmission harq pid: %d\n", current_harq_pid); LOG_W(NR_MAC, "dlsch0_harq->status not ACTIVE due to false retransmission harq pid: %d\n", current_harq_pid);
update_harq_status(mac, current_harq_pid, dlsch0_harq->decodeResult); update_harq_status(mac, current_harq_pid, cw_idx, dlsch_harq->decodeResult);
} }
} }
@@ -161,23 +157,28 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
case FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH: { case FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH: {
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15;
NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0; NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0;
phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords;
phy_data->dlsch_config = *dlsch_config_pdu;
dlsch0->rnti_type = TYPE_RA_RNTI_; dlsch0->rnti_type = TYPE_RA_RNTI_;
dlsch0->dlsch_config = *dlsch_config_pdu; configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, 0, pdu->dlsch_config_pdu.rnti);
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti);
} break; } break;
case FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH: { case FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH: {
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15;
NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0; NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0;
phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords;
phy_data->dlsch_config = *dlsch_config_pdu;
dlsch0->rnti_type = TYPE_SI_RNTI_; dlsch0->rnti_type = TYPE_SI_RNTI_;
dlsch0->dlsch_config = *dlsch_config_pdu; configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, 0, pdu->dlsch_config_pdu.rnti);
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti);
} break; } break;
case FAPI_NR_DL_CONFIG_TYPE_DLSCH: { case FAPI_NR_DL_CONFIG_TYPE_DLSCH: {
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15;
NR_UE_DLSCH_t *dlsch0 = &phy_data->dlsch[0]; phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords;
dlsch0->rnti_type = TYPE_C_RNTI_; phy_data->dlsch_config = *dlsch_config_pdu;
dlsch0->dlsch_config = *dlsch_config_pdu; for (int c = 0; c < dlsch_config_pdu->n_codewords; c++) {
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti); NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[c];
dlsch->rnti_type = TYPE_C_RNTI_;
configure_dlsch(dlsch, phy->dl_harq_processes[c], dlsch_config_pdu, mac, c, pdu->dlsch_config_pdu.rnti);
}
} break; } break;
case FAPI_NR_CONFIG_TA_COMMAND: case FAPI_NR_CONFIG_TA_COMMAND:
configure_ta_command(phy, &pdu->ta_command_pdu); configure_ta_command(phy, &pdu->ta_command_pdu);
+1 -1
View File
@@ -29,6 +29,6 @@ void nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config);
\param synch_request including target_Nid_cell*/ \param synch_request including target_Nid_cell*/
void nr_ue_synch_request(nr_synch_request_t *synch_request); void nr_ue_synch_request(nr_synch_request_t *synch_request);
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack); void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, int cw_idx, uint8_t ack_nack);
#endif #endif
+85 -109
View File
@@ -94,31 +94,35 @@ static uint32_t get_ssb_arfcn(NR_DL_FRAME_PARMS *frame_parms)
uint64_t ssb_freq = frame_parms->dl_CarrierFreq - (band_size_hz / 2) + frame_parms->subcarrier_spacing * ssb_center_sc; uint64_t ssb_freq = frame_parms->dl_CarrierFreq - (band_size_hz / 2) + frame_parms->subcarrier_spacing * ssb_center_sc;
return to_nrarfcn(ssb_freq); return to_nrarfcn(ssb_freq);
} }
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
uint8_t pdu_type, uint8_t pdu_type,
PHY_VARS_NR_UE *ue, PHY_VARS_NR_UE *ue,
NR_UE_DLSCH_t *dlsch0, int cw_idx,
NR_UE_DLSCH_t *dlsch1, int harq_pid,
NR_UE_DLSCH_t *dlsch,
uint16_t n_pdus, uint16_t n_pdus,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
void *typeSpecific, void *typeSpecific,
uint8_t *b) uint8_t *b)
{ {
if (n_pdus > 1){ if (n_pdus > 1) {
LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__); LOG_E(PHY, "Multiple number of DL PDUs not supported yet...\n");
return;
} }
fapi_nr_rx_indication_body_t *rx = rx_ind->rx_indication_body + n_pdus - 1; fapi_nr_rx_indication_body_t *rx = rx_ind->rx_indication_body + n_pdus - 1;
switch (pdu_type){ switch (pdu_type){
case FAPI_NR_RX_PDU_TYPE_SIB: case FAPI_NR_RX_PDU_TYPE_SIB:
case FAPI_NR_RX_PDU_TYPE_RAR: case FAPI_NR_RX_PDU_TYPE_RAR:
case FAPI_NR_RX_PDU_TYPE_DLSCH: case FAPI_NR_RX_PDU_TYPE_DLSCH:
if(dlsch0) { if(dlsch) {
NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr]; NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[cw_idx][harq_pid];
rx->pdsch_pdu.harq_pid = dlsch0->dlsch_config.harq_process_nbr; rx->pdsch_pdu.harq_pid = harq_pid;
rx->pdsch_pdu.ack_nack = dl_harq0->decodeResult; rx->pdsch_pdu.cw_idx = cw_idx;
rx->pdsch_pdu.ack_nack = dl_harq->decodeResult;
rx->pdsch_pdu.pdu = b; rx->pdsch_pdu.pdu = b;
rx->pdsch_pdu.pdu_length = dlsch0->dlsch_config.TBS / 8; rx->pdsch_pdu.pdu_length = dlsch->cw_info.TBS / 8;
if (dl_harq0->decodeResult) { if (dl_harq->decodeResult) {
int t = WS_C_RNTI; int t = WS_C_RNTI;
if (pdu_type == FAPI_NR_RX_PDU_TYPE_RAR) if (pdu_type == FAPI_NR_RX_PDU_TYPE_RAR)
t = WS_RA_RNTI; t = WS_RA_RNTI;
@@ -130,16 +134,13 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
.pdu_buffer_size = rx->pdsch_pdu.pdu_length, .pdu_buffer_size = rx->pdsch_pdu.pdu_length,
.ueid = 0, .ueid = 0,
.rntiType = t, .rntiType = t,
.rnti = dlsch0->rnti, .rnti = dlsch->rnti,
.sysFrame = proc->frame_rx, .sysFrame = proc->frame_rx,
.subframe = proc->nr_slot_rx, .subframe = proc->nr_slot_rx,
.harq_pid = dlsch0->dlsch_config.harq_process_nbr}; .harq_pid = harq_pid};
trace_pdu(&tmp); trace_pdu(&tmp);
} }
} }
if(dlsch1) {
AssertFatal(1==0,"Second codeword currently not supported\n");
}
break; break;
case FAPI_NR_RX_PDU_TYPE_SSB: { case FAPI_NR_RX_PDU_TYPE_SSB: {
if (typeSpecific) { if (typeSpecific) {
@@ -168,7 +169,6 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
rx->pdu_type = pdu_type; rx->pdu_type = pdu_type;
rx_ind->number_pdus = n_pdus; rx_ind->number_pdus = n_pdus;
} }
int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){ int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){
@@ -488,8 +488,10 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t dlsch[2], NR_UE_DLSCH_t *dlsch,
int16_t *llr[2], NR_DL_UE_HARQ_t *dlsch_harq,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg,
int16_t *llr,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
int G, int G,
freq_alloc_bitmap_t *freq_alloc) freq_alloc_bitmap_t *freq_alloc)
@@ -502,11 +504,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
LOG_E(NR_PHY, "Handling of more than one CW not implemented\n"); LOG_E(NR_PHY, "Handling of more than one CW not implemented\n");
return -1; return -1;
} }
NR_UE_DLSCH_t *dlsch0 = &dlsch[0];
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg = &dlsch0->dlsch_config;
int harq_pid = dlschCfg->harq_process_nbr; int harq_pid = dlschCfg->harq_process_nbr;
// dlsch0_harq contains the previous transmissions data for this harq pid
NR_DL_UE_HARQ_t *dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
LOG_D(PHY, LOG_D(PHY,
"[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, start RB %d, end RB %d, symbol_start %d, nb_symbols " "[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, start RB %d, end RB %d, symbol_start %d, nb_symbols "
@@ -516,18 +515,18 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
frame_rx, frame_rx,
nr_slot_rx, nr_slot_rx,
harq_pid, harq_pid,
dlsch0_harq->status, dlsch_harq->status,
dlschCfg->BWPStart, dlschCfg->BWPStart,
freq_alloc->first_rb, freq_alloc->first_rb,
freq_alloc->last_rb, freq_alloc->last_rb,
dlschCfg->start_symbol, dlschCfg->start_symbol,
dlschCfg->number_symbols, dlschCfg->number_symbols,
dlschCfg->dlDmrsSymbPos, dlschCfg->dlDmrsSymbPos,
dlsch0->Nl); dlsch->cw_info.Nl);
const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size + 15) / 16) * 16; const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size + 15) / 16) * 16;
fourDimArray_t *toFree = NULL; fourDimArray_t *toFree = NULL;
allocCast2D(pdsch_dl_ch_estimates, int32_t, toFree, ue->frame_parms.nb_antennas_rx * dlsch0->Nl, pdsch_est_size, false); allocCast2D(pdsch_dl_ch_estimates, int32_t, toFree, ue->frame_parms.nb_antennas_rx * dlsch->cw_info.Nl, pdsch_est_size, false);
c16_t ptrs_phase_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT]; c16_t ptrs_phase_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
memset(ptrs_phase_per_slot, 0, sizeof(ptrs_phase_per_slot)); memset(ptrs_phase_per_slot, 0, sizeof(ptrs_phase_per_slot));
@@ -541,7 +540,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
c16_t, c16_t,
toFree2, toFree2,
ue->frame_parms.symbols_per_slot, ue->frame_parms.symbols_per_slot,
dlsch[0].Nl, dlsch->cw_info.Nl,
ue->frame_parms.nb_antennas_rx, ue->frame_parms.nb_antennas_rx,
rx_size_symbol, rx_size_symbol,
false); false);
@@ -551,7 +550,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS); start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
for (int m = dlschCfg->start_symbol; m < (dlschCfg->start_symbol + dlschCfg->number_symbols); m++) { for (int m = dlschCfg->start_symbol; m < (dlschCfg->start_symbol + dlschCfg->number_symbols); m++) {
if (dlschCfg->dlDmrsSymbPos & (1 << m)) { if (dlschCfg->dlDmrsSymbPos & (1 << m)) {
for (int nl = 0; nl < dlsch0->Nl; nl++) { // for MIMO Config: it shall loop over no_layers for (int nl = 0; nl < dlsch->cw_info.Nl; nl++) { // for MIMO Config: it shall loop over no_layers
LOG_D(PHY, "PDSCH Channel estimation layer %d, slot %d, symbol %d\n", nl, nr_slot_rx, m); LOG_D(PHY, "PDSCH Channel estimation layer %d, slot %d, symbol %d\n", nl, nr_slot_rx, m);
uint32_t nvar_tmp = 0; uint32_t nvar_tmp = 0;
nr_pdsch_channel_estimation(ue, nr_pdsch_channel_estimation(ue,
@@ -580,7 +579,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
} }
} }
stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS); stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
nvar /= (dlschCfg->number_symbols * dlsch0->Nl * ue->frame_parms.nb_antennas_rx); nvar /= (dlschCfg->number_symbols * dlsch->cw_info.Nl * ue->frame_parms.nb_antennas_rx);
nr_ue_measurement_procedures(2, ue, proc, freq_alloc->num_rbs, pdsch_est_size, pdsch_dl_ch_estimates); nr_ue_measurement_procedures(2, ue, proc, freq_alloc->num_rbs, pdsch_est_size, pdsch_dl_ch_estimates);
if (ue->chest_time == 1) { // averaging time domain channel estimates if (ue->chest_time == 1) { // averaging time domain channel estimates
@@ -589,7 +588,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
dlschCfg->number_symbols, dlschCfg->number_symbols,
dlschCfg->start_symbol, dlschCfg->start_symbol,
dlschCfg->dlDmrsSymbPos, dlschCfg->dlDmrsSymbPos,
freq_alloc->num_rbs); freq_alloc->num_rbs,
dlsch->cw_info.Nl);
} }
uint16_t first_symbol_with_data = dlschCfg->start_symbol; uint16_t first_symbol_with_data = dlschCfg->start_symbol;
@@ -630,7 +630,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
c16_t, c16_t,
toFree3, toFree3,
NR_SYMBOLS_PER_SLOT, NR_SYMBOLS_PER_SLOT,
dlsch[0].Nl, dlsch->cw_info.Nl,
ue->frame_parms.nb_antennas_rx, ue->frame_parms.nb_antennas_rx,
rx_size_symbol, rx_size_symbol,
false); false);
@@ -639,7 +639,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
c16_t, c16_t,
toFree4, toFree4,
NR_SYMBOLS_PER_SLOT, NR_SYMBOLS_PER_SLOT,
dlsch[0].Nl, dlsch->cw_info.Nl,
ue->frame_parms.nb_antennas_rx, ue->frame_parms.nb_antennas_rx,
rx_size_symbol, rx_size_symbol,
false); false);
@@ -648,7 +648,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
c16_t, c16_t,
toFree5, toFree5,
NR_SYMBOLS_PER_SLOT, NR_SYMBOLS_PER_SLOT,
dlsch[0].Nl, dlsch->cw_info.Nl,
ue->frame_parms.nb_antennas_rx, ue->frame_parms.nb_antennas_rx,
rx_size_symbol, rx_size_symbol,
false); false);
@@ -663,6 +663,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
proc, proc,
dlsch, dlsch,
freq_alloc, freq_alloc,
dlschCfg,
dlsch_harq,
m, m,
first_symbol_flag, first_symbol_flag,
harq_pid, harq_pid,
@@ -760,90 +762,68 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls
*/ */
static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t dlsch[2], NR_UE_DLSCH_t *dlsch,
int16_t *llr[2], int cw_idx,
int G[2], int G,
freq_alloc_bitmap_t *freq_alloc) freq_alloc_bitmap_t *freq_alloc,
fapi_nr_dl_config_dlsch_pdu_rel15_t *config,
int16_t *llr)
{ {
if (dlsch[0].active == false) { if (dlsch->active == false) {
LOG_E(PHY, "DLSCH should be active when calling this function\n"); LOG_E(PHY, "DLSCH should be active when calling this function\n");
return; return;
} }
int harq_pid = dlsch[0].dlsch_config.harq_process_nbr; int harq_pid = config->harq_process_nbr;
int frame_rx = proc->frame_rx; int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx; int nr_slot_rx = proc->nr_slot_rx;
NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][harq_pid];
NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid];
nr_downlink_indication_t dl_indication; nr_downlink_indication_t dl_indication;
fapi_nr_rx_indication_t rx_ind = {0}; fapi_nr_rx_indication_t rx_ind = {0};
uint16_t number_pdus = 1; uint16_t number_pdus = 1;
uint8_t is_cw0_active = dl_harq0->status; LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW%d [harq_pid %d]\n", frame_rx % 1024, nr_slot_rx, cw_idx, harq_pid);
uint8_t is_cw1_active = dl_harq1->status;
int nb_dlsch = 0;
nb_dlsch += (is_cw0_active == NR_ACTIVE) ? 1 : 0;
nb_dlsch += (is_cw1_active == NR_ACTIVE) ? 1 : 0;
LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw0_active);
LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw1_active);
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
// exit dlsch procedures as there are no active dlsch // exit dlsch procedures as there are no active dlsch
if (is_cw0_active != ACTIVE && is_cw1_active != NR_ACTIVE) { NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[cw_idx][harq_pid];
if (dl_harq->status != NR_ACTIVE) {
// don't wait anymore // don't wait anymore
LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid); LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid);
if (dlsch[0].dlsch_config.k1_feedback) { if (config->k1_feedback) {
const int ack_nack_slot_and_frame = const int ack_nack_slot_and_frame = (proc->nr_slot_rx + config->k1_feedback) + proc->frame_rx * fp->slots_per_frame;
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]); dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
} }
return; return;
} }
uint8_t DLSCH_ids[nb_dlsch]; start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
int pdsch_id = 0; nr_dlsch_unscrambling(llr, G, 0, config->dlDataScramblingId, dlsch->rnti);
uint8_t *p_b[2] = {NULL}; stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
for (uint8_t DLSCH_id = 0; DLSCH_id < 2; DLSCH_id++) {
NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[DLSCH_id][harq_pid];
if (dl_harq->status != NR_ACTIVE)
continue;
DLSCH_ids[pdsch_id++] = DLSCH_id;
start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
nr_dlsch_unscrambling(llr[DLSCH_id], G[DLSCH_id], 0, dlsch[DLSCH_id].dlsch_config.dlDataScramblingId, dlsch[DLSCH_id].rnti);
stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
p_b[DLSCH_id] = dl_harq->b;
}
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, freq_alloc->num_rbs, DLSCH_ids); nr_dlsch_decoding(ue, proc, dlsch, cw_idx, config, llr, dl_harq->b, freq_alloc->num_rbs, G);
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
int ind_type = -1; int ind_type = -1;
switch (dlsch[0].rnti_type) { switch (dlsch->rnti_type) {
case TYPE_RA_RNTI_: case TYPE_RA_RNTI_:
ind_type = FAPI_NR_RX_PDU_TYPE_RAR; ind_type = FAPI_NR_RX_PDU_TYPE_RAR;
break; break;
case TYPE_SI_RNTI_: case TYPE_SI_RNTI_:
ind_type = FAPI_NR_RX_PDU_TYPE_SIB; ind_type = FAPI_NR_RX_PDU_TYPE_SIB;
break; break;
case TYPE_C_RNTI_: case TYPE_C_RNTI_:
ind_type = FAPI_NR_RX_PDU_TYPE_DLSCH; ind_type = FAPI_NR_RX_PDU_TYPE_DLSCH;
break; break;
default: default:
AssertFatal(true, "Invalid DLSCH type %d\n", dlsch[0].rnti_type); AssertFatal(false, "Invalid DLSCH type %d\n", dlsch->rnti_type);
break; break;
} }
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b[0]); nr_fill_rx_indication(&rx_ind, ind_type, ue, cw_idx, harq_pid, dlsch, number_pdus, proc, NULL, dl_harq->b);
LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8); LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch->cw_info.TBS, dlsch->cw_info.TBS / 8);
if (cpumeas(CPUMEAS_GETSTATE)) { if (cpumeas(CPUMEAS_GETSTATE)) {
LOG_D(PHY, LOG_D(PHY,
" --> Unscrambling %5.3f\n", " --> Unscrambling %5.3f\n",
@@ -861,9 +841,8 @@ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
} }
// DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH // DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH
if ((dlsch[0].rnti_type == TYPE_C_RNTI_ || dlsch[0].rnti_type == TYPE_RA_RNTI_) && dlsch[0].dlsch_config.k1_feedback) { if ((dlsch->rnti_type == TYPE_C_RNTI_ || dlsch->rnti_type == TYPE_RA_RNTI_) && config->k1_feedback) {
const int ack_nack_slot_and_frame = const int ack_nack_slot_and_frame = (proc->nr_slot_rx + config->k1_feedback) + proc->frame_rx * fp->slots_per_frame;
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]); dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
} }
@@ -874,11 +853,8 @@ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
} }
uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment
if (ue->phy_sim_dlsch_b && is_cw0_active == NR_ACTIVE) if (ue->phy_sim_dlsch_b)
memcpy(ue->phy_sim_dlsch_b, p_b[0], dlsch_bytes); memcpy(ue->phy_sim_dlsch_b, dl_harq->b, dlsch_bytes);
else if (ue->phy_sim_dlsch_b && is_cw1_active == NR_ACTIVE)
memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes);
} }
static bool check_meas_to_perform(PHY_VARS_NR_UE *ue, int nr_slot_rx) static bool check_meas_to_perform(PHY_VARS_NR_UE *ue, int nr_slot_rx)
@@ -1150,7 +1126,6 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
int nr_slot_rx = proc->nr_slot_rx; int nr_slot_rx = proc->nr_slot_rx;
int gNB_id = proc->gNB_id; int gNB_id = proc->gNB_id;
NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[0];
// do procedures for C-RNTI // do procedures for C-RNTI
bool slot_fep_map[14] = {0}; bool slot_fep_map[14] = {0};
@@ -1182,9 +1157,13 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
nr_ue_csi_rs_procedures(ue, proc, rxdataF, &phy_data->csirs_vars.csirs_config_pdu); nr_ue_csi_rs_procedures(ue, proc, rxdataF, &phy_data->csirs_vars.csirs_config_pdu);
} }
int G[2] = {0}; int16_t *llr[2];
if (dlsch[0].active) { fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &phy_data->dlsch_config;
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config; for (int c = 0; c < phy_data->n_dlsch_codewords; c++) {
NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[c];
if (!dlsch->active)
continue;
uint16_t nb_symb_sch = dlsch_config->number_symbols; uint16_t nb_symb_sch = dlsch_config->number_symbols;
uint16_t start_symb_sch = dlsch_config->start_symbol; uint16_t start_symb_sch = dlsch_config->start_symbol;
@@ -1219,32 +1198,30 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
unav_res = n_ptrs * ptrsSymbPerSlot; unav_res = n_ptrs * ptrsSymbPerSlot;
} }
unav_res += compute_csi_rm_unav_res(dlsch_config); unav_res += compute_csi_rm_unav_res(dlsch_config);
G[0] = nr_get_G(freq_alloc.num_rbs, int G = nr_get_G(freq_alloc.num_rbs,
dlsch_config->number_symbols, dlsch_config->number_symbols,
nb_re_dmrs, nb_re_dmrs,
dmrs_len, dmrs_len,
unav_res, unav_res,
dlsch_config->qamModOrder, dlsch->cw_info.qamModOrder,
dlsch[0].Nl); dlsch->cw_info.Nl);
const uint32_t rx_llr_buf_sz = ALIGNARRAYSIZE(G[0], 32); // each LLR is 2 bytes hence 64 byte aligned const uint32_t rx_llr_buf_sz = ALIGNARRAYSIZE(G, 32); // each LLR is 2 bytes hence 64 byte aligned
const uint32_t nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1; llr[c] = (int16_t *)malloc16_clear(rx_llr_buf_sz * sizeof(int16_t));
int16_t* llr[2];
for (int i = 0; i < nb_codewords; i++)
llr[i] = (int16_t *)malloc16_clear(rx_llr_buf_sz * sizeof(int16_t));
// dlsch_harq contains the previous transmissions data for this harq pid
NR_DL_UE_HARQ_t *harq = &ue->dl_harq_processes[c][dlsch_config->harq_process_nbr];
// it returns -1 in case of internal failure, or 0 in case of normal result // it returns -1 in case of internal failure, or 0 in case of normal result
int ret_pdsch = nr_ue_pdsch_procedures(ue, proc, dlsch, llr, rxdataF, G[0], &freq_alloc); int ret_pdsch = nr_ue_pdsch_procedures(ue, proc, dlsch, harq, dlsch_config, llr[c], rxdataF, &freq_alloc);
TracyCPlot("pdsch mcs", dlsch->dlsch_config.mcs); TracyCPlot("pdsch mcs", dlsch->cw_info.mcs);
UEscopeCopy(ue, pdschLlr, llr[0], sizeof(int16_t), 1, G[0], 0); UEscopeCopy(ue, pdschLlr, llr[c], sizeof(int16_t), 1, G, 0);
LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d\n", nr_slot_rx); LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d\n", nr_slot_rx);
start_meas_nr_ue_phy(ue, DLSCH_PROCEDURES_STATS); start_meas_nr_ue_phy(ue, DLSCH_PROCEDURES_STATS);
if (ret_pdsch >= 0) { if (ret_pdsch >= 0) {
nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G, &freq_alloc); nr_ue_dlsch_procedures(ue, proc, dlsch, c, G, &freq_alloc, dlsch_config, llr[c]);
} } else {
else {
LOG_E(NR_PHY, "Demodulation impossible, internal error\n"); LOG_E(NR_PHY, "Demodulation impossible, internal error\n");
if (dlsch_config->k1_feedback) { if (dlsch_config->k1_feedback) {
const int ack_nack_slot_and_frame = const int ack_nack_slot_and_frame =
@@ -1264,10 +1241,9 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
&rxdataF[0][start_symb_sch * ue->frame_parms.ofdm_symbol_size], &rxdataF[0][start_symb_sch * ue->frame_parms.ofdm_symbol_size],
sizeof(int32_t) * nb_symb_sch * ue->frame_parms.ofdm_symbol_size); sizeof(int32_t) * nb_symb_sch * ue->frame_parms.ofdm_symbol_size);
if (ue->phy_sim_pdsch_llr) if (ue->phy_sim_pdsch_llr)
memcpy(ue->phy_sim_pdsch_llr, llr[0], sizeof(int16_t) * rx_llr_buf_sz); memcpy(ue->phy_sim_pdsch_llr, llr[c], sizeof(int16_t) * rx_llr_buf_sz);
for (int i=0; i<nb_codewords; i++) free(llr[c]);
free(llr[i]);
} }
if (nr_slot_rx==9) { if (nr_slot_rx==9) {
+23 -26
View File
@@ -457,20 +457,22 @@ int main(int argc, char **argv)
NR_UE_DLSCH_t *dlsch0_ue = &dlsch_ue[0]; NR_UE_DLSCH_t *dlsch0_ue = &dlsch_ue[0];
NR_DL_UE_HARQ_t *harq_process = &UE->dl_harq_processes[0][harq_pid]; NR_DL_UE_HARQ_t *harq_process = &UE->dl_harq_processes[0][harq_pid];
harq_process->first_rx = 1; harq_process->first_rx = 1;
dlsch0_ue->dlsch_config.mcs = Imcs; fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
dlsch0_ue->dlsch_config.mcs_table = mcs_table; dlsch_config.cw_info[0].mcs = Imcs;
dlsch0_ue->Nl = Nl; dlsch_config.mcs_table = mcs_table;
dlsch0_ue->dlsch_config.number_rbs = nb_rb; dlsch_config.number_rbs = nb_rb;
dlsch0_ue->dlsch_config.qamModOrder = mod_order; dlsch_config.cw_info[0].Nl = Nl;
dlsch0_ue->dlsch_config.rv = rvidx; dlsch_config.cw_info[0].qamModOrder = mod_order;
dlsch0_ue->dlsch_config.targetCodeRate = rate; dlsch_config.cw_info[0].rv = rvidx;
dlsch0_ue->dlsch_config.TBS = TBS; dlsch_config.cw_info[0].targetCodeRate = rate;
dlsch0_ue->dlsch_config.ldpcBaseGraph = get_BG(TBS, rate); dlsch_config.cw_info[0].TBS = TBS;
dlsch0_ue->dlsch_config.dmrsConfigType = NFAPI_NR_DMRS_TYPE1; dlsch_config.cw_info[0].ldpcBaseGraph = get_BG(TBS, rate);
dlsch0_ue->dlsch_config.dlDmrsSymbPos = 4; dlsch_config.dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
dlsch0_ue->dlsch_config.n_dmrs_cdm_groups = 1; dlsch_config.dlDmrsSymbPos = 4;
dlsch0_ue->dlsch_config.tbslbrm = Tbslbrm; dlsch_config.n_dmrs_cdm_groups = 1;
printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch0_ue->dlsch_config.mcs, dlsch0_ue->dlsch_config.qamModOrder, nb_symb_sch); dlsch_config.tbslbrm = Tbslbrm;
dlsch0_ue->cw_info = dlsch_config.cw_info[0];
printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch_config.cw_info[0].mcs, dlsch_config.cw_info[0].qamModOrder, nb_symb_sch);
uint8_t test_input[TBS / 8 + 4]; // + 3 for CRC + 1 additional byte, see nr_dlsch_encoding() uint8_t test_input[TBS / 8 + 4]; // + 3 for CRC + 1 additional byte, see nr_dlsch_encoding()
dlsch->pdu = test_input; dlsch->pdu = test_input;
@@ -536,27 +538,23 @@ int main(int argc, char **argv)
exit(-1); exit(-1);
#endif #endif
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; // number of segments to be allocated
int num_rb = dlsch0_ue->dlsch_config.number_rbs; int num_rb = dlsch_config.number_rbs;
if (num_rb != 273) { if (num_rb != 273) {
a_segments = a_segments*num_rb; a_segments = a_segments*num_rb;
a_segments = (a_segments/273)+1; a_segments = (a_segments/273)+1;
} }
uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
__attribute__ ((aligned(32))) uint8_t b[dlsch_bytes]; __attribute__ ((aligned(32))) uint8_t b[dlsch_bytes];
uint8_t DLSCH_ids[1] = {0};
short *p_channel_output_fixed = channel_output_fixed;
uint8_t *p_b = b;
int available_bits_array[1] = { available_bits };
nr_dlsch_decoding(UE, nr_dlsch_decoding(UE,
&proc, &proc,
dlsch0_ue, dlsch0_ue,
&p_channel_output_fixed, 0,
&p_b, &dlsch_config,
available_bits_array, channel_output_fixed,
1, b,
num_rb, num_rb,
DLSCH_ids); available_bits);
if (dlsch0_ue->last_iteration_cnt > dlsch0_ue->max_ldpc_iterations) if (dlsch0_ue->last_iteration_cnt > dlsch0_ue->max_ldpc_iterations)
n_errors++; n_errors++;
@@ -634,4 +632,3 @@ int main(int argc, char **argv)
return (n_errors); return (n_errors);
} }
+12 -10
View File
@@ -1310,12 +1310,14 @@ int main(int argc, char **argv)
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr; int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
TBS = dlsch0->dlsch_config.TBS; TBS = phy_data.dlsch_config.cw_info[0].TBS;
uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos); uint16_t length_dmrs = get_num_dmrs(phy_data.dlsch_config.dlDmrsSymbPos);
uint16_t nb_rb = dlsch0->dlsch_config.number_rbs; uint16_t nb_rb = phy_data.dlsch_config.number_rbs;
uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups; uint8_t nb_re_dmrs = phy_data.dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ?
uint8_t mod_order = dlsch0->dlsch_config.qamModOrder; 6 * phy_data.dlsch_config.n_dmrs_cdm_groups :
uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols; 4 * phy_data.dlsch_config.n_dmrs_cdm_groups;
uint8_t mod_order = phy_data.dlsch_config.cw_info[0].qamModOrder;
uint8_t nb_symb_sch = phy_data.dlsch_config.number_symbols;
uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb; uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb;
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers); available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers);
if (pdu_bit_map & 0x1) { if (pdu_bit_map & 0x1) {
@@ -1457,10 +1459,10 @@ int main(int argc, char **argv)
const int s = pdsch_pdu_rel15->StartSymbolIndex; const int s = pdsch_pdu_rel15->StartSymbolIndex;
const int n = pdsch_pdu_rel15->NrOfSymbols; const int n = pdsch_pdu_rel15->NrOfSymbols;
for (int i = s; i < s + n; i++) { for (int i = s; i < s + n; i++) {
const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos; const uint32_t dmrsBitMap = phy_data.dlsch_config.dlDmrsSymbPos;
const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType; const uint32_t dmrsCfg = phy_data.dlsch_config.dmrsConfigType;
const uint32_t nrb = phy_data.dlsch[0].dlsch_config.number_rbs; const uint32_t nrb = phy_data.dlsch_config.number_rbs;
const uint32_t ncdmg = phy_data.dlsch[0].dlsch_config.n_dmrs_cdm_groups; const uint32_t ncdmg = phy_data.dlsch_config.n_dmrs_cdm_groups;
const uint32_t numValidReSym = ((dmrsBitMap >> i) & 1) const uint32_t numValidReSym = ((dmrsBitMap >> i) & 1)
? ((dmrsCfg == NFAPI_NR_DMRS_TYPE1) ? nrb * (12 - 6 * ncdmg) : nrb * (12 - 4 * ncdmg)) ? ((dmrsCfg == NFAPI_NR_DMRS_TYPE1) ? nrb * (12 - 6 * ncdmg) : nrb * (12 - 4 * ncdmg))
: (nrb * 12); : (nrb * 12);
+3 -2
View File
@@ -83,8 +83,9 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
uint8_t pdu_type, uint8_t pdu_type,
PHY_VARS_NR_UE *ue, PHY_VARS_NR_UE *ue,
NR_UE_DLSCH_t *dlsch0, int cw_idx,
NR_UE_DLSCH_t *dlsch1, int harq_pid,
NR_UE_DLSCH_t *dlsch,
uint16_t n_pdus, uint16_t n_pdus,
const UE_nr_rxtx_proc_t *proc, const UE_nr_rxtx_proc_t *proc,
void *typeSpecific, void *typeSpecific,
@@ -3033,7 +3033,7 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP,
size += 8; size += 8;
// TB2 // TB2
long *maxCWperDCI = pdsch_Config ? pdsch_Config->maxNrofCodeWordsScheduledByDCI : NULL; long *maxCWperDCI = pdsch_Config ? pdsch_Config->maxNrofCodeWordsScheduledByDCI : NULL;
if ((maxCWperDCI != NULL) && (*maxCWperDCI == 2)) { if (maxCWperDCI && (*maxCWperDCI == NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n2)) {
size += 8; size += 8;
} }
// HARQ process number – 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-1-1 is configured; // HARQ process number – 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-1-1 is configured;
+1 -1
View File
@@ -595,7 +595,7 @@ typedef struct NR_UE_MAC_INST_s {
// Defined for abstracted mode // Defined for abstracted mode
nr_downlink_indication_t dl_info; nr_downlink_indication_t dl_info;
NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES]; NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES][2]; // one harq process for each codeword
NR_UE_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES]; NR_UE_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES];
NR_TAG_Id_t tag_Id; NR_TAG_Id_t tag_Id;
+8 -6
View File
@@ -200,12 +200,14 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
nr_mac->scheduling_info.phr_info.phr_reporting = 0; nr_mac->scheduling_info.phr_info.phr_reporting = 0;
nr_mac->scheduling_info.phr_info.was_mac_reset = true; nr_mac->scheduling_info.phr_info.was_mac_reset = true;
// flush the soft buffers for all DL HARQ processes for (int c = 0; c < 2; c++) {
memset(nr_mac->dl_harq_info, 0, sizeof(nr_mac->dl_harq_info)); // flush the soft buffers for all DL HARQ processes
// for each DL HARQ process, consider the next received transmission for a TB as the very first transmission
// for each DL HARQ process, consider the next received transmission for a TB as the very first transmission for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) memset(&nr_mac->dl_harq_info[k][c], 0, sizeof(NR_UE_DL_HARQ_STATUS_t));
nr_mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value nr_mac->dl_harq_info[k][c].last_ndi = -1; // initialize to invalid value
}
}
// release, if any, Temporary C-RNTI // release, if any, Temporary C-RNTI
nr_mac->ra.t_crnti = 0; nr_mac->ra.t_crnti = 0;
+1 -1
View File
@@ -1190,7 +1190,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order)
void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack)
{ {
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid][0]; // single cw for MSG4
int sched_slot = current_harq->ul_slot; int sched_slot = current_harq->ul_slot;
int sched_frame = current_harq->ul_frame; int sched_frame = current_harq->ul_frame;
PUCCH_sched_t pucch = {.n_CCE = current_harq->n_CCE, PUCCH_sched_t pucch = {.n_CCE = current_harq->n_CCE,
@@ -218,9 +218,11 @@ int get_sum_delta_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame)
const int num_dl_harq = get_nrofHARQ_ProcessesForPDSCH(&mac->sc_info); const int num_dl_harq = get_nrofHARQ_ProcessesForPDSCH(&mac->sc_info);
for (int i = 0; i < num_dl_harq; i++) { for (int i = 0; i < num_dl_harq; i++) {
if (mac->dl_harq_info[i].active && mac->dl_harq_info[i].ul_slot == slot && mac->dl_harq_info[i].ul_frame == frame) { for (int c = 0; c < 2; c++) {
delta_tpc_sum += mac->dl_harq_info[i].delta_pucch; if (mac->dl_harq_info[i][c].active && mac->dl_harq_info[i][c].ul_slot == slot && mac->dl_harq_info[i][c].ul_frame == frame) {
mac->dl_harq_info[i].delta_pucch = 0; delta_tpc_sum += mac->dl_harq_info[i][c].delta_pucch;
mac->dl_harq_info[i][c].delta_pucch = 0;
}
} }
} }
return delta_tpc_sum; return delta_tpc_sum;
+249 -210
View File
@@ -435,6 +435,7 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
static void set_harq_status(NR_UE_MAC_INST_t *mac, static void set_harq_status(NR_UE_MAC_INST_t *mac,
uint8_t pucch_id, uint8_t pucch_id,
uint8_t harq_id, uint8_t harq_id,
int cw_id,
int8_t delta_pucch, int8_t delta_pucch,
uint16_t data_toul_fb, uint16_t data_toul_fb,
uint8_t dai, uint8_t dai,
@@ -443,7 +444,7 @@ static void set_harq_status(NR_UE_MAC_INST_t *mac,
frame_t frame, frame_t frame,
int slot) int slot)
{ {
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id][cw_id];
current_harq->active = true; current_harq->active = true;
current_harq->ack_received = false; current_harq->ack_received = false;
current_harq->pucch_resource_indicator = pucch_id; current_harq->pucch_resource_indicator = pucch_id;
@@ -469,13 +470,15 @@ static void set_harq_status(NR_UE_MAC_INST_t *mac,
// looking for other active HARQ processes with feedback in the same frame/slot // looking for other active HARQ processes with feedback in the same frame/slot
if (i == harq_id) if (i == harq_id)
continue; continue;
NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i]; for (int c = 0; c < 2; c++) {
if (harq->active && NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i][c];
harq->ul_frame == current_harq->ul_frame && if (harq->active &&
harq->ul_slot == current_harq->ul_slot) { harq->ul_frame == current_harq->ul_frame &&
// highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot harq->ul_slot == current_harq->ul_slot) {
if (harq->dai_cumul > highest_dai) // highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot
highest_dai = harq->dai_cumul - 1; if (harq->dai_cumul > highest_dai)
highest_dai = harq->dai_cumul - 1;
}
} }
} }
@@ -667,6 +670,99 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
return ret; return ret;
} }
// Table 7.3.1.3-1 of 38.211
static int get_nl_for_cw(int Nl, int cw_idx)
{
AssertFatal(Nl >= 0 && Nl <= 8, "Invalid number of layers %d\n", Nl);
if (Nl < 5)
return Nl;
else {
if (cw_idx == 0)
return Nl / 2;
else
return Nl / 2 + Nl % 2;
}
}
static bool get_cw_info(NR_UE_DL_HARQ_STATUS_t *current_harq,
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu,
uint8_t pdu_type,
fapi_nr_dl_cw_info_t *cw_info,
int number_rbs,
int nb_re_dmrs,
int nb_rb_oh,
int rv,
int mcs,
int ndi,
int cw_idx)
{
uint8_t Nl = 0;
for (int i = 0; i < 12; i++) { // max 12 ports
if ((dlsch_pdu->dmrs_ports >> i) & 0x01)
Nl += 1;
}
cw_info->mcs = mcs;
/* RV for transport block */
cw_info->rv = rv;
/* NDI for transport block*/
if (pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH || pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH || ndi != current_harq->last_ndi) {
// new data
cw_info->new_data_indicator = true;
current_harq->R = 0;
current_harq->TBS = 0;
} else
cw_info->new_data_indicator = false;
if (pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH && pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) {
current_harq->last_ndi = ndi;
if (cw_info->new_data_indicator)
current_harq->round = 0;
else
current_harq->round++;
}
cw_info->qamModOrder = nr_get_Qm_dl(cw_info->mcs, dlsch_pdu->mcs_table);
if (cw_info->qamModOrder == 0) {
LOG_W(NR_MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI\n");
return false;
}
cw_info->Nl = get_nl_for_cw(Nl, cw_idx);
int R = nr_get_code_rate_dl(cw_info->mcs, dlsch_pdu->mcs_table);
if (R > 0) {
cw_info->targetCodeRate = R;
cw_info->TBS = nr_compute_tbs(cw_info->qamModOrder,
R,
number_rbs,
dlsch_pdu->number_symbols,
nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos),
nb_rb_oh,
0,
cw_info->Nl);
// storing for possible retransmissions
if (!cw_info->new_data_indicator && current_harq->TBS != cw_info->TBS) {
LOG_W(NR_MAC,
"NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
cw_info->TBS,
current_harq->TBS);
cw_info->new_data_indicator = true; // treated as new data
}
current_harq->R = cw_info->targetCodeRate;
current_harq->TBS = cw_info->TBS;
}
else {
cw_info->targetCodeRate = current_harq->R;
cw_info->TBS = current_harq->TBS;
}
if (cw_info->TBS == 0) {
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
return false;
}
cw_info->ldpcBaseGraph = get_BG(cw_info->TBS, cw_info->targetCodeRate);
return true;
}
static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
frame_t frame, frame_t frame,
int slot, int slot,
@@ -789,7 +885,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
0, 0,
dci->frequency_domain_assignment) dci->frequency_domain_assignment)
< 0) { < 0) {
LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); LOG_W(NR_MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
return -1; return -1;
} }
@@ -873,76 +969,28 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
NULL, // SPS not implemented, NULL, // SPS not implemented,
false, // as above false, // as above
NULL); // MCS-C-RNTI not implemented NULL); // MCS-C-RNTI not implemented
/* MCS */
dlsch_pdu->mcs = dci->mcs;
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val]; int nb_re_dmrs = ((dlsch_pdu->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
/* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ int nb_rb_oh = mac->sc_info.xOverhead_PDSCH ? nb_rb_oh = 6 * (1 + *mac->sc_info.xOverhead_PDSCH) : 0;
if (dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH || NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val][0];
dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH || if (!get_cw_info(current_harq,
dci->ndi != current_harq->last_ndi) { dlsch_pdu,
// new data dl_conf_req->pdu_type,
dlsch_pdu->new_data_indicator = true; &dlsch_pdu->cw_info[0],
current_harq->R = 0; dlsch_pdu->number_rbs,
current_harq->TBS = 0; nb_re_dmrs,
} else { nb_rb_oh,
dlsch_pdu->new_data_indicator = false; dci->rv,
} dci->mcs,
dci->ndi,
if (dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH && 0))
dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) {
current_harq->last_ndi = dci->ndi;
}
dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
if (dlsch_pdu->qamModOrder == 0) {
LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
return -1; return -1;
}
int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); dlsch_pdu->n_codewords = 1;
if (R > 0) {
dlsch_pdu->targetCodeRate = R;
int nb_rb_oh;
if (mac->sc_info.xOverhead_PDSCH)
nb_rb_oh = 6 * (1 + *mac->sc_info.xOverhead_PDSCH);
else
nb_rb_oh = 0;
int nb_re_dmrs = ((dlsch_pdu->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
dlsch_pdu->TBS = nr_compute_tbs(dlsch_pdu->qamModOrder,
R,
dlsch_pdu->number_rbs,
dlsch_pdu->number_symbols,
nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos),
nb_rb_oh,
0,
1);
// storing for possible retransmissions
current_harq->R = dlsch_pdu->targetCodeRate;
if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) {
LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
dlsch_pdu->TBS, current_harq->TBS);
dlsch_pdu->new_data_indicator = true; // treated as new data
}
current_harq->TBS = dlsch_pdu->TBS;
}
else {
dlsch_pdu->targetCodeRate = current_harq->R;
dlsch_pdu->TBS = current_harq->TBS;
}
dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate);
if (dlsch_pdu->TBS == 0) {
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
return -1;
}
int bw_tbslbrm = current_DL_BWP ? mac->sc_info.dl_bw_tbslbrm : dlsch_pdu->BWPSize; int bw_tbslbrm = current_DL_BWP ? mac->sc_info.dl_bw_tbslbrm : dlsch_pdu->BWPSize;
dlsch_pdu->tbslbrm = nr_compute_tbslbrm(dlsch_pdu->mcs_table, bw_tbslbrm, 1); dlsch_pdu->tbslbrm = nr_compute_tbslbrm(dlsch_pdu->mcs_table, bw_tbslbrm, 1);
/* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
dlsch_pdu->rv = dci->rv;
/* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ /* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
dlsch_pdu->harq_process_nbr = dci->harq_pid.val; dlsch_pdu->harq_process_nbr = dci->harq_pid.val;
/* TB_SCALING (only if CRC scrambled by P-RNTI or RA-RNTI) */ /* TB_SCALING (only if CRC scrambled by P-RNTI or RA-RNTI) */
@@ -1009,6 +1057,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
set_harq_status(mac, set_harq_status(mac,
dci->pucch_resource_indicator, dci->pucch_resource_indicator,
dci->harq_pid.val, dci->harq_pid.val,
0,
tpc[dci->tpc], tpc[dci->tpc],
feedback_ti, feedback_ti,
dci->dai[0].val, dci->dai[0].val,
@@ -1017,10 +1066,6 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
frame, frame,
slot); slot);
} }
if (dlsch_pdu->new_data_indicator)
current_harq->round = 0;
else
current_harq->round++;
if (current_harq->round < sizeofArray(mac->stats.dl.rounds)) if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
mac->stats.dl.rounds[current_harq->round]++; mac->stats.dl.rounds[current_harq->round]++;
} }
@@ -1043,9 +1088,9 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
"(nr_ue_procedures.c) vrb_to_prb_mapping=%d \n>>> mcs=%d\n>>> ndi=%d\n>>> rv=%d\n>>> harq_process_nbr=%d\n>>> dai=%d\n>>> " "(nr_ue_procedures.c) vrb_to_prb_mapping=%d \n>>> mcs=%d\n>>> ndi=%d\n>>> rv=%d\n>>> harq_process_nbr=%d\n>>> dai=%d\n>>> "
"scaling_factor_S=%f\n>>> tpc_pucch=%d\n>>> pucch_res_ind=%d\n>>> pdsch_to_harq_feedback_time_ind=%d\n", "scaling_factor_S=%f\n>>> tpc_pucch=%d\n>>> pucch_res_ind=%d\n>>> pdsch_to_harq_feedback_time_ind=%d\n",
dlsch_pdu->vrb_to_prb_mapping, dlsch_pdu->vrb_to_prb_mapping,
dlsch_pdu->mcs, dlsch_pdu->cw_info[0].mcs,
dlsch_pdu->new_data_indicator, dlsch_pdu->cw_info[0].new_data_indicator,
dlsch_pdu->rv, dlsch_pdu->cw_info[0].rv,
dlsch_pdu->harq_process_nbr, dlsch_pdu->harq_process_nbr,
dci->dai[0].val, dci->dai[0].val,
dlsch_pdu->scaling_factor_S, dlsch_pdu->scaling_factor_S,
@@ -1055,7 +1100,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
dlsch_pdu->k1_feedback = feedback_ti; dlsch_pdu->k1_feedback = feedback_ti;
LOG_D(MAC, "(nr_ue_procedures.c) pdu_type=%d\n\n", dl_conf_req->pdu_type); LOG_D(MAC, "(nr_ue_procedures.c) pdu_type=%d\n", dl_conf_req->pdu_type);
// the prepared dci is valid, we add it in the list // the prepared dci is valid, we add it in the list
dl_config->number_pdus++; dl_config->number_pdus++;
@@ -1213,9 +1258,6 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
dlsch_pdu->dmrsConfigType = dl_dmrs_config->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2; dlsch_pdu->dmrsConfigType = dl_dmrs_config->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2;
/* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214,
using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */
dlsch_pdu->n_dmrs_cdm_groups = 1;
/* VRB_TO_PRB_MAPPING */ /* VRB_TO_PRB_MAPPING */
if ((pdsch_Config->resourceAllocation == 1) && (pdsch_Config->vrb_ToPRB_Interleaver != NULL)) if ((pdsch_Config->resourceAllocation == 1) && (pdsch_Config->vrb_ToPRB_Interleaver != NULL))
dlsch_pdu->vrb_to_prb_mapping = dlsch_pdu->vrb_to_prb_mapping =
@@ -1226,28 +1268,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
dlsch_pdu->rate_matching_ind = dci->rate_matching_indicator.val; dlsch_pdu->rate_matching_ind = dci->rate_matching_indicator.val;
/* ZP_CSI_RS_TRIGGER */ /* ZP_CSI_RS_TRIGGER */
dlsch_pdu->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val; dlsch_pdu->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val;
/* MCS (for transport block 1)*/
dlsch_pdu->mcs = dci->mcs;
/* NDI (for transport block 1)*/
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val];
if (dci->ndi != current_harq->last_ndi) {
// new data
dlsch_pdu->new_data_indicator = true;
current_harq->R = 0;
current_harq->TBS = 0;
}
else {
dlsch_pdu->new_data_indicator = false;
}
current_harq->last_ndi = dci->ndi;
/* RV (for transport block 1)*/
dlsch_pdu->rv = dci->rv;
/* MCS (for transport block 2)*/
dlsch_pdu->tb2_mcs = dci->mcs2.val;
/* NDI (for transport block 2)*/
dlsch_pdu->tb2_new_data_indicator = dci->ndi2.val;
/* RV (for transport block 2)*/
dlsch_pdu->tb2_rv = dci->rv2.val;
/* HARQ_PROCESS_NUMBER */ /* HARQ_PROCESS_NUMBER */
dlsch_pdu->harq_process_nbr = dci->harq_pid.val; dlsch_pdu->harq_process_nbr = dci->harq_pid.val;
/* TPC_PUCCH */ /* TPC_PUCCH */
@@ -1276,13 +1297,32 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
return -1; return -1;
} }
NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info;
int nb_rb_oh;
if (sc_info->xOverhead_PDSCH)
nb_rb_oh = 6 * (1 + *sc_info->xOverhead_PDSCH);
else
nb_rb_oh = 0;
/* ANTENNA_PORTS */ /* ANTENNA_PORTS */
uint8_t n_codewords = 1; // FIXME!!!
long *max_length = dl_dmrs_config->maxLength; long *max_length = dl_dmrs_config->maxLength;
long *dmrs_type = dl_dmrs_config->dmrs_Type; long *dmrs_type = dl_dmrs_config->dmrs_Type;
// In case the higher layer parameter maxNrofCodeWordsScheduledByDCI indicates that two codeword transmission is enabled,
// then one of the two transport blocks is disabled by DCI format 1_1
// if IMCS = 26 and if rvid = 1 for the corresponding transport block
bool cw0 = true;
bool cw1 = true;
if (pdsch_Config->maxNrofCodeWordsScheduledByDCI
&& *pdsch_Config->maxNrofCodeWordsScheduledByDCI == NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n2) {
cw0 = dci->rv != 1 || dci->mcs != 26;
cw1 = dci->rv2.val != 1 || dci->mcs2.val != 26;
} else
cw1 = false;
dlsch_pdu->n_front_load_symb = 1; // default value dlsch_pdu->n_front_load_symb = 1; // default value
set_antenna_port_parameters(dlsch_pdu, n_codewords, max_length, dmrs_type, dci->antenna_ports.val); set_antenna_port_parameters(dlsch_pdu, cw0 + cw1, max_length, dmrs_type, dci->antenna_ports.val);
int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
/* dmrs symbol positions*/ /* dmrs symbol positions*/
dlsch_pdu->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config, dlsch_pdu->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config,
@@ -1293,6 +1333,105 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
tda_info.mapping_type, tda_info.mapping_type,
dlsch_pdu->n_front_load_symb); dlsch_pdu->n_front_load_symb);
dlsch_pdu->mcs_table = get_dlsch_mcs_table(NR_DL_DCI_FORMAT_1_1,
rnti_type,
dci_ind->ss_type,
pdsch_Config ? pdsch_Config->mcs_Table : NULL,
NULL, // SPS not implemented,
false, // as above
NULL); // MCS-C-RNTI not implemented
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
// according to TS 38.213 Table 9.2.3-1
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing);
uint16_t feedback_ti = 0;
const int tpc[] = {-1, 0, 1, 3};
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
"file (min_rxtxtime).\n",
feedback_ti,
GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing));
}
int number_rbs;
if (dlsch_pdu->resource_alloc == 1) {
number_rbs = dlsch_pdu->number_rbs;
} else {
uint32_t temp_bitmap[9];
memcpy(temp_bitmap, dlsch_pdu->rb_bitmap, 36);
number_rbs = count_bits(temp_bitmap, 9);
}
int cw_idx = 0;
NR_UE_DL_HARQ_STATUS_t *current_harq = NULL;
if (cw0) {
current_harq = &mac->dl_harq_info[dci->harq_pid.val][0];
if (get_cw_info(current_harq,
dlsch_pdu,
dl_conf_req->pdu_type,
&dlsch_pdu->cw_info[0],
number_rbs,
nb_re_dmrs,
nb_rb_oh,
dci->rv,
dci->mcs,
dci->ndi,
cw_idx)) {
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
mac->stats.dl.rounds[current_harq->round]++;
// set the harq status at MAC for feedback
set_harq_status(mac,
dci->pucch_resource_indicator,
dci->harq_pid.val,
0,
tpc[dci->tpc],
feedback_ti,
dci->dai[0].val,
dci_ind->n_CCE,
dci_ind->N_CCE,
frame,
slot);
cw_idx++;
} else
return -1;
}
if (cw1) {
current_harq = &mac->dl_harq_info[dci->harq_pid.val][cw_idx];
if (get_cw_info(current_harq,
dlsch_pdu,
dl_conf_req->pdu_type,
&dlsch_pdu->cw_info[1],
number_rbs,
nb_re_dmrs,
nb_rb_oh,
dci->rv2.val,
dci->mcs2.val,
dci->ndi2.val,
cw_idx)) {
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
mac->stats.dl.rounds[current_harq->round]++;
// set the harq status at MAC for feedback
set_harq_status(mac,
dci->pucch_resource_indicator,
dci->harq_pid.val,
1,
tpc[dci->tpc],
feedback_ti,
dci->dai[0].val,
dci_ind->n_CCE,
dci_ind->N_CCE,
frame,
slot);
cw_idx++;
} else
return -1;
}
dlsch_pdu->n_codewords = cw_idx;
/* TCI */ /* TCI */
if (dl_conf_req->dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1) { if (dl_conf_req->dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1) {
// 0 bit if higher layer parameter tci-PresentInDCI is not enabled // 0 bit if higher layer parameter tci-PresentInDCI is not enabled
@@ -1311,107 +1450,9 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
/* DMRS_SEQ_INI */ /* DMRS_SEQ_INI */
// FIXME!!! // FIXME!!!
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
// according to TS 38.213 Table 9.2.3-1
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing);
uint16_t feedback_ti = 0;
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
"file (min_rxtxtime).\n",
feedback_ti,
GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing));
// set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3};
set_harq_status(mac,
dci->pucch_resource_indicator,
dci->harq_pid.val,
tpc[dci->tpc],
feedback_ti,
dci->dai[0].val,
dci_ind->n_CCE,
dci_ind->N_CCE,
frame,
slot);
}
if (dlsch_pdu->new_data_indicator)
current_harq->round = 0;
else
current_harq->round++;
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
mac->stats.dl.rounds[current_harq->round]++;
// send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding // send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding
dlsch_pdu->k1_feedback = feedback_ti; dlsch_pdu->k1_feedback = feedback_ti;
dlsch_pdu->mcs_table = get_dlsch_mcs_table(NR_DL_DCI_FORMAT_1_1,
rnti_type,
dci_ind->ss_type,
pdsch_Config ? pdsch_Config->mcs_Table : NULL,
NULL, // SPS not implemented,
false, // as above
NULL); // MCS-C-RNTI not implemented
dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
if (dlsch_pdu->qamModOrder == 0) {
LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
return -1;
}
uint8_t Nl = 0;
for (int i = 0; i < 12; i++) { // max 12 ports
if ((dlsch_pdu->dmrs_ports >> i) & 0x01)
Nl += 1;
}
NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info;
int nb_rb_oh;
if (sc_info->xOverhead_PDSCH)
nb_rb_oh = 6 * (1 + *sc_info->xOverhead_PDSCH);
else
nb_rb_oh = 0;
int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
int number_rbs;
if (dlsch_pdu->resource_alloc == 1) {
number_rbs = dlsch_pdu->number_rbs;
} else {
uint32_t temp_bitmap[9];
memcpy(temp_bitmap, dlsch_pdu->rb_bitmap, 36);
number_rbs = count_bits(temp_bitmap, 9);
}
int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
if (R > 0) {
dlsch_pdu->targetCodeRate = R;
dlsch_pdu->TBS = nr_compute_tbs(dlsch_pdu->qamModOrder,
R,
number_rbs,
dlsch_pdu->number_symbols,
nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos),
nb_rb_oh,
0,
Nl);
// storing for possible retransmissions
if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) {
LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
dlsch_pdu->TBS, current_harq->TBS);
dlsch_pdu->new_data_indicator = true; // treated as new data
}
current_harq->R = dlsch_pdu->targetCodeRate;
current_harq->TBS = dlsch_pdu->TBS;
}
else {
dlsch_pdu->targetCodeRate = current_harq->R;
dlsch_pdu->TBS = current_harq->TBS;
}
dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate);
if (dlsch_pdu->TBS == 0) {
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
return -1;
}
// TBS_LBRM according to section 5.4.2.1 of 38.212 // TBS_LBRM according to section 5.4.2.1 of 38.212
int max_mimo_layers = 0; int max_mimo_layers = 0;
if (sc_info->maxMIMO_Layers_PDSCH) if (sc_info->maxMIMO_Layers_PDSCH)
@@ -1424,10 +1465,11 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
/*PTRS configuration */ /*PTRS configuration */
dlsch_pdu->pduBitmap = 0; dlsch_pdu->pduBitmap = 0;
if (dl_dmrs_config->phaseTrackingRS != NULL) { if (dl_dmrs_config->phaseTrackingRS != NULL) {
AssertFatal(cw_idx == 1, "Cannot handle PTRS with 2 codewords\n");
bool valid_ptrs_setup = bool valid_ptrs_setup =
set_dl_ptrs_values(dl_dmrs_config->phaseTrackingRS->choice.setup, set_dl_ptrs_values(dl_dmrs_config->phaseTrackingRS->choice.setup,
number_rbs, number_rbs,
dlsch_pdu->mcs, dlsch_pdu->cw_info[0].mcs,
dlsch_pdu->mcs_table, dlsch_pdu->mcs_table,
&dlsch_pdu->PTRSFreqDensity, &dlsch_pdu->PTRSFreqDensity,
&dlsch_pdu->PTRSTimeDensity, &dlsch_pdu->PTRSTimeDensity,
@@ -2339,11 +2381,8 @@ bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sche
/* look for dl acknowledgment which should be done on current uplink slot */ /* look for dl acknowledgment which should be done on current uplink slot */
for (int code_word = 0; code_word < number_of_code_word; code_word++) { for (int code_word = 0; code_word < number_of_code_word; code_word++) {
for (int dl_harq_pid = 0; dl_harq_pid < num_dl_harq; dl_harq_pid++) { for (int dl_harq_pid = 0; dl_harq_pid < num_dl_harq; dl_harq_pid++) {
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid][code_word];
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid];
if (current_harq->active) { if (current_harq->active) {
LOG_D(PHY, "HARQ pid %d is active for %d.%d\n", LOG_D(PHY, "HARQ pid %d is active for %d.%d\n",
dl_harq_pid, current_harq->ul_frame, current_harq->ul_slot); dl_harq_pid, current_harq->ul_frame, current_harq->ul_slot);
+14 -12
View File
@@ -116,15 +116,22 @@ static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer); nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
} }
static void flush_harq_buffers(NR_UE_MAC_INST_t *mac)
{
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
for (int c = 0; c < 2; c++) {
memset(&mac->dl_harq_info[k][c], 0, sizeof(NR_UE_DL_HARQ_STATUS_t));
mac->dl_harq_info[k][c].last_ndi = -1; // initialize to invalid value
}
memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info));
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
}
}
void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
{ {
// flush all HARQ buffers for all Serving Cells // flush all HARQ buffers for all Serving Cells
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { flush_harq_buffers(mac);
memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info));
memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info));
mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
}
// release PUCCH for all Serving Cells; // release PUCCH for all Serving Cells;
// release SRS for all Serving Cells; // release SRS for all Serving Cells;
release_PUCCH_SRS(mac); release_PUCCH_SRS(mac);
@@ -142,12 +149,7 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
void handle_ulsync_loss(NR_UE_MAC_INST_t *mac) void handle_ulsync_loss(NR_UE_MAC_INST_t *mac)
{ {
// flush all HARQ buffers for all Serving Cells // flush all HARQ buffers for all Serving Cells
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { flush_harq_buffers(mac);
memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info));
memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info));
mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
}
// clear any configured downlink assignments and uplink grants; // clear any configured downlink assignments and uplink grants;
if (mac->dl_config_request) if (mac->dl_config_request)
memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request));
+3 -2
View File
@@ -145,6 +145,7 @@ static int8_t handle_dlsch(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
if (mac->ra.ra_state != nrRA_WAIT_RAR) // no HARQ for MSG2 if (mac->ra.ra_state != nrRA_WAIT_RAR) // no HARQ for MSG2
update_harq_status(mac, update_harq_status(mac,
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid,
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.cw_idx,
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack); dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack);
if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack) if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack)
nr_ue_send_sdu(mac, dl_info, pdu_id); nr_ue_send_sdu(mac, dl_info, pdu_id);
@@ -167,9 +168,9 @@ static int8_t handle_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int s
return 0; return 0;
} }
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack) void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, int cw_idx, uint8_t ack_nack)
{ {
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid]; NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid][cw_idx];
if (current_harq->active) { if (current_harq->active) {
LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack); LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack);