fix(nrLDPC_decoder): Cleaning LDPC iteration accounting in NR
The idea is to make LDPC iteration accounting more standard from a C coding perspective by making two changes: 1. Now the iteration counter starts at 0 for the first iteration and goes up to max_ldpc_iterations - 1 for the last iteration. If it is equal to max_ldpc_iterations, it means that decoding failed. 2. A chain of useless returns in the UE DLSCH decoding call chain was removed.
This commit is contained in:
+1
-1
@@ -218,7 +218,7 @@ static void nr_process_decode_segment(void *arg)
|
||||
int decodeIterations =
|
||||
LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, rdata->abort_decode);
|
||||
|
||||
if (decodeIterations <= p_decoderParms->numMaxIter) {
|
||||
if (decodeIterations < p_decoderParms->numMaxIter) {
|
||||
memcpy(rdata->c, llrProcBuf, K >> 3);
|
||||
*rdata->decodeSuccess = true;
|
||||
} else {
|
||||
|
||||
@@ -277,8 +277,8 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int s
|
||||
|
||||
for (uint32_t job = 0; job < num_threads_prepare; job++) {
|
||||
args_fpga_decode_prepare_t *args = &arr[job];
|
||||
if (args->no_iteration_ldpc > TB_params->max_ldpc_iterations)
|
||||
no_iteration_ldpc = TB_params->max_ldpc_iterations + 1;
|
||||
if (args->no_iteration_ldpc >= TB_params->max_ldpc_iterations)
|
||||
no_iteration_ldpc = TB_params->max_ldpc_iterations;
|
||||
}
|
||||
|
||||
// launch decode with FPGA
|
||||
@@ -306,12 +306,12 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int s
|
||||
#ifdef DEBUG_CRC
|
||||
LOG_I(PHY, "segment %d CRC NOK\n", r);
|
||||
#endif
|
||||
no_iteration_ldpc = TB_params->max_ldpc_iterations + 1;
|
||||
no_iteration_ldpc = TB_params->max_ldpc_iterations;
|
||||
}
|
||||
for (int i = 0; i < out_CBoffset; i++) {
|
||||
segment_params->c[i] = multi_outdata[i + r * out_CBoffset];
|
||||
}
|
||||
segment_params->decodeSuccess = (no_iteration_ldpc <= TB_params->max_ldpc_iterations);
|
||||
segment_params->decodeSuccess = (no_iteration_ldpc < TB_params->max_ldpc_iterations);
|
||||
if (segment_params->decodeSuccess) {
|
||||
*TB_params->processedSegments = *TB_params->processedSegments + 1;
|
||||
}
|
||||
@@ -396,7 +396,7 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
|
||||
== -1) {
|
||||
stop_meas(&segment_params->ts_rate_unmatch);
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
|
||||
no_iteration_ldpc = max_ldpc_iterations + 1;
|
||||
no_iteration_ldpc = max_ldpc_iterations;
|
||||
arguments->no_iteration_ldpc = no_iteration_ldpc;
|
||||
return;
|
||||
} else {
|
||||
|
||||
@@ -187,7 +187,7 @@ int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams,
|
||||
|
||||
// Launch LDPC decoder core for one segment
|
||||
int numIter = nrLDPC_decoder_core(p_llr, p_out, numLLR, p_lut, p_decParams, p_profiler, ab);
|
||||
if (numIter > p_decParams->numMaxIter) {
|
||||
if (numIter >= p_decParams->numMaxIter) {
|
||||
LOG_D(PHY, "set abort: %d, %d\n", numIter, p_decParams->numMaxIter);
|
||||
set_abort(ab, true);
|
||||
}
|
||||
@@ -549,11 +549,11 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
// estimated after only one iteration
|
||||
|
||||
// First iteration finished
|
||||
uint32_t numIter = 1;
|
||||
uint32_t numIter = 0;
|
||||
int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful
|
||||
while ((numIter <= numMaxIter) && (pcRes != 0)) {
|
||||
while ((numIter < numMaxIter) && (pcRes != 0)) {
|
||||
if (check_abort(ab)) {
|
||||
numIter = numMaxIter + 2;
|
||||
numIter = numMaxIter;
|
||||
break;
|
||||
}
|
||||
// CN processing
|
||||
@@ -845,7 +845,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z);
|
||||
NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc));
|
||||
} else {
|
||||
if (numIter > 1) {
|
||||
if (numIter > 0) {
|
||||
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
|
||||
int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut;
|
||||
nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG);
|
||||
|
||||
@@ -59,14 +59,14 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
|
||||
|
||||
/*! \brief Prepare necessary parameters for nrLDPC_coding_interface
|
||||
*/
|
||||
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
int16_t **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids)
|
||||
void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
int16_t **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids)
|
||||
{
|
||||
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch];
|
||||
memset(TBs, 0, sizeof(TBs));
|
||||
@@ -100,7 +100,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n");
|
||||
return dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
|
||||
@@ -164,7 +164,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
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);
|
||||
return dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100))
|
||||
@@ -242,7 +242,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
|
||||
|
||||
if (ret_decoder != 0) {
|
||||
return dlsch->max_ldpc_iterations + 1;
|
||||
LOG_E(PHY, "nrLDPC_coding_decoder returned an error: %d\n", ret_decoder);
|
||||
return;
|
||||
}
|
||||
|
||||
// post decode
|
||||
@@ -316,11 +317,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
if (harq_process->decodeResult) {
|
||||
LOG_D(PHY, "DLSCH received ok \n");
|
||||
harq_process->status = SCH_IDLE;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
|
||||
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 + 1;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
|
||||
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
|
||||
}
|
||||
|
||||
@@ -355,5 +356,4 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
|
||||
}
|
||||
|
||||
return dlsch[0].last_iteration_cnt;
|
||||
}
|
||||
|
||||
@@ -81,14 +81,14 @@ void nr_conjch0_mult_ch1(int *ch0,
|
||||
@param[in] DLSCH_ids array of active downlink shared channels
|
||||
@returns 0 on success, 1 on unsuccessful decoding
|
||||
*/
|
||||
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
short **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids);
|
||||
void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
short **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids);
|
||||
|
||||
/** \brief This is the alternative top-level entry point for ULSCH encoding in UE.
|
||||
It handles all the HARQ processes in only one call. The routine first
|
||||
|
||||
@@ -147,7 +147,7 @@ typedef struct {
|
||||
/// Maximum number of LDPC iterations
|
||||
uint8_t max_ldpc_iterations;
|
||||
/// number of iterations used in last turbo decoding
|
||||
uint8_t last_iteration_cnt;
|
||||
int8_t last_iteration_cnt;
|
||||
/// bit mask of PT-RS ofdm symbol indicies
|
||||
uint16_t ptrs_symbols;
|
||||
// PTRS symbol index, to be updated every PTRS symbol within a slot.
|
||||
|
||||
@@ -239,7 +239,7 @@ typedef struct {
|
||||
/// Maximum number of LDPC iterations
|
||||
uint8_t max_ldpc_iterations;
|
||||
/// number of iterations used in last LDPC decoding
|
||||
uint8_t last_iteration_cnt;
|
||||
int8_t last_iteration_cnt;
|
||||
/// Status Flag indicating for this ULSCH
|
||||
bool active;
|
||||
/// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around
|
||||
|
||||
@@ -424,7 +424,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
|
||||
LOG_D(PHY, "ULSCH received ok \n");
|
||||
ulsch->active = false;
|
||||
ulsch_harq->round = 0;
|
||||
ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure
|
||||
ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations - 1; // Setting to max_ldpc_iterations - 1 is sufficient given that this variable is only used for checking for failure
|
||||
} else {
|
||||
LOG_D(PHY,
|
||||
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, "
|
||||
@@ -444,7 +444,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
|
||||
gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK");
|
||||
ulsch->handled = 1;
|
||||
LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id);
|
||||
ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations + 1; // Setting to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure
|
||||
ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -686,20 +686,18 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls
|
||||
|
||||
/*! \brief Process the whole DLSCH slot
|
||||
*/
|
||||
static bool 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,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t *llr[2]) {
|
||||
if (dlsch[0].active == false) {
|
||||
LOG_E(PHY, "DLSCH should be active when calling this function\n");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
bool dec = false;
|
||||
int harq_pid = dlsch[0].dlsch_config.harq_process_nbr;
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
uint32_t ret = UINT32_MAX;
|
||||
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];
|
||||
uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos);
|
||||
@@ -732,7 +730,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
const int ack_nack_slot_and_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]);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
int G[2];
|
||||
@@ -765,11 +763,9 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
ret = nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids);
|
||||
nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
|
||||
if (ret < ue->max_ldpc_iterations + 1) dec = true;
|
||||
|
||||
int ind_type = -1;
|
||||
switch (dlsch[0].rnti_type) {
|
||||
case TYPE_RA_RNTI_:
|
||||
@@ -829,7 +825,6 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
else if (ue->phy_sim_dlsch_b && is_cw1_active == ACTIVE)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes);
|
||||
|
||||
return dec;
|
||||
}
|
||||
|
||||
static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index)
|
||||
|
||||
@@ -123,7 +123,6 @@ int main(int argc, char **argv)
|
||||
NR_DL_FRAME_PARMS *frame_parms;
|
||||
double sigma;
|
||||
unsigned char qbits = 8;
|
||||
int ret;
|
||||
int loglvl = OAILOG_WARNING;
|
||||
uint8_t dlsch_threads = 0;
|
||||
float target_error_rate = 0.01;
|
||||
@@ -577,18 +576,18 @@ int main(int argc, char **argv)
|
||||
short *p_channel_output_fixed = channel_output_fixed;
|
||||
uint8_t *p_b = b;
|
||||
int available_bits_array[1] = { available_bits };
|
||||
ret = nr_dlsch_decoding(UE,
|
||||
&proc,
|
||||
dlsch0_ue,
|
||||
&p_channel_output_fixed,
|
||||
&p_b,
|
||||
available_bits_array,
|
||||
1,
|
||||
DLSCH_ids);
|
||||
nr_dlsch_decoding(UE,
|
||||
&proc,
|
||||
dlsch0_ue,
|
||||
&p_channel_output_fixed,
|
||||
&p_b,
|
||||
available_bits_array,
|
||||
1,
|
||||
DLSCH_ids);
|
||||
|
||||
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT);
|
||||
|
||||
if (ret > dlsch0_ue->max_ldpc_iterations)
|
||||
if (dlsch0_ue->last_iteration_cnt > dlsch0_ue->max_ldpc_iterations)
|
||||
n_errors++;
|
||||
|
||||
//count errors
|
||||
|
||||
@@ -1163,7 +1163,7 @@ printf("%d\n", slot);
|
||||
//---------------------- count errors ----------------------
|
||||
//----------------------------------------------------------
|
||||
|
||||
if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations+1)
|
||||
if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations)
|
||||
n_errors[round]++;
|
||||
|
||||
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
|
||||
|
||||
@@ -1420,7 +1420,7 @@ int main(int argc, char *argv[])
|
||||
0);
|
||||
}
|
||||
|
||||
if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations + 1) || ul_proc_error == 1) {
|
||||
if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) {
|
||||
error_flag = 1;
|
||||
n_errors[round]++;
|
||||
crc_status = 1;
|
||||
|
||||
Reference in New Issue
Block a user