Commit 830ceac0 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/fix_numIter' into integration_2025_w11 (!3296)

fix(nrLDPC_decoder): fix numIter increment

The logs of ./nr_ulsim -n100 -m19 -s12 -S12 -z2 -L4 were showing that sometimes
the decoding of one segment was failing while the CRC check succeeded. This was
happening because the iteration counter numIter was not properly managed so that
when the last iteration was successful to decode the segment still numIter at
the exit was equal to numMaxIter plus 1 so that decoding was considered to have
failed. In other words the last iteration if it occured was always wasted.

This commit offers to solve this problem by simply moving the iteration counter
increment at the end of the iteration loop while remaining careful at fixing the
tests relying on this counter.

Post-Scriptum:
After a first review, we decided to make the counter more standard from a C code
perspective. The counter now counts from 0 to numMaxIter minus 1. If it reaches
numMaxIter, it means that decoding was unsuccessful.
parents 950ee0a4 6b660e40
......@@ -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,13 +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)) {
// Increase iteration counter
numIter++;
while ((numIter < numMaxIter) && (pcRes != 0)) {
if (check_abort(ab)) {
numIter = numMaxIter + 2;
numIter = numMaxIter;
break;
}
// CN processing
......@@ -847,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 > 2) {
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);
......@@ -861,6 +859,8 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
}
}
}
// Increase iteration counter
numIter++;
}
if (!p_decParams->check_crc) {
int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0};
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment