Commit 006c47df authored by Raymond Knopp's avatar Raymond Knopp

Merge remote-tracking branch 'origin/bugfix-ldpc-processing' into use_msgq

parents a8e6cae7 6c9a0dea
......@@ -78,6 +78,7 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr, uint16_t N_RB_UL)
}
free_and_zero(ulsch->harq_processes[i]->c);
free_and_zero(ulsch->harq_processes[i]->d);
free_and_zero(ulsch->harq_processes[i]->crc_ok);
free_and_zero(ulsch->harq_processes[i]);
ulsch->harq_processes[i] = NULL;
}
......@@ -102,11 +103,13 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
ulsch = (NR_gNB_ULSCH_t *)malloc16_clear(sizeof(NR_gNB_ULSCH_t));
ulsch->max_ldpc_iterations = max_ldpc_iterations;
ulsch->a_segments = a_segments;
for (i=0; i<NR_MAX_ULSCH_HARQ_PROCESSES; i++) {
ulsch->harq_processes[i] = (NR_UL_gNB_HARQ_t *)malloc16_clear(sizeof(NR_UL_gNB_HARQ_t));
ulsch->harq_processes[i]->b = (uint8_t*)malloc16_clear(ulsch_bytes);
ulsch->harq_processes[i]->c = (uint8_t**)malloc16_clear(a_segments*sizeof(uint8_t *));
ulsch->harq_processes[i]->crc_ok = malloc16_clear(a_segments*sizeof(bool));
ulsch->harq_processes[i]->d = (int16_t**)malloc16_clear(a_segments*sizeof(int16_t *));
for (r=0; r<a_segments; r++) {
ulsch->harq_processes[i]->c[r] = (uint8_t*)malloc16_clear(8448*sizeof(uint8_t));
......@@ -165,6 +168,11 @@ void nr_processULSegment(void* arg) {
ldpcDecode_t *rdata = (ldpcDecode_t*) arg;
PHY_VARS_gNB *phy_vars_gNB = rdata->gNB;
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
if (ulsch_harq->crc_ok[rdata->segment_r]) {
LOG_D(PHY, "segment %d already decoded in a previous transmission, do nothing\n", rdata->segment_r);
rdata->decodeIterations = 0;
return;
}
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
int length_dec;
int no_iteration_ldpc;
......@@ -252,6 +260,15 @@ void nr_processULSegment(void* arg) {
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
}
/* don't run LDPC decoding if some other thread had a failure */
/* nr_rate_matching_ldpc_rx() must be called to feed d[r] in all cases
* so this test has to come after the call to nr_rate_matching_ldpc_rx()
*/
if (__atomic_load_n(&ulsch_harq->skip_ldpc_decoding, __ATOMIC_SEQ_CST)) {
LOG_D(PHY, "skipping nrLDPC_decoder() for r %d because decoding of some other segment failed\n", r);
return;
}
memset(ulsch_harq->c[r],0,Kr_bytes);
if (ulsch_harq->C == 1) {
......@@ -302,11 +319,15 @@ void nr_processULSegment(void* arg) {
#endif
rdata->decodeIterations = no_iteration_ldpc;
if (rdata->decodeIterations > p_decoderParms->numMaxIter) rdata->decodeIterations--;
/* remember that the data is ok to not decode it again in case of retransmission */
ulsch_harq->crc_ok[r] = true;
} else {
#ifdef PRINT_CRC_CHECK
LOG_I(PHY,"CRC NOK\n");
#endif
rdata->decodeIterations = max_ldpc_iterations + 1;
/* set skip_ldpc_decoding to 1 to indicate to remaining threads that they shall not run LDPC decoding */
__atomic_store_n(&ulsch_harq->skip_ldpc_decoding, 1, __ATOMIC_SEQ_CST);
}
for (int m=0; m < Kr>>3; m ++) {
......@@ -623,6 +644,9 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
else {
dtx_det = 0;
/* tell to the threads that LDPC decoding has to be done */
__atomic_store_n(&harq_process->skip_ldpc_decoding, 0, __ATOMIC_SEQ_CST);
for (int r = 0; r < harq_process->C; r++) {
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
union ldpcReqUnion id = {.s = {ulsch->rnti, frame, nr_tti_rx, 0, 0}};
......@@ -647,6 +671,9 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
rdata->ulsch = ulsch;
rdata->ulsch_id = ULSCH_id;
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
/* in case of a new rx, tell nr_processULSegment() to process the data, so set crc_ok[r] to false */
if (harq_process->new_rx)
harq_process->crc_ok[r] = false;
pushTpool(&phy_vars_gNB->threadPool, req);
phy_vars_gNB->nbDecode++;
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", phy_vars_gNB->nbDecode);
......
......@@ -227,6 +227,8 @@ typedef struct {
uint32_t B;
/// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2)
uint8_t **c;
/// array to indicate that a segment has a valid CRC from a previous transmission to not run LDPC decoder again in a retransmission
bool *crc_ok;
/// Number of bits in each code block (38.212 V15.4.0 section 5.2.2)
uint32_t K;
/// Number of "Filler" bits added in the code block segmentation (38.212 V15.4.0 section 5.2.2)
......@@ -244,6 +246,11 @@ typedef struct {
/// Last index of LLR buffer that contains information.
/// Used for computing LDPC decoder R
int llrLen;
/// used to indicate to remaining threads that LDPC decoding has to be skipped
/// this is set to true when a crc fails to avoid unnecessary computation
/// all accesses must be done with __atomic operations
/// (we can't use bool, it does not work with __atomic operations)
uint8_t skip_ldpc_decoding;
//////////////////////////////////////////////////////////////
} NR_UL_gNB_HARQ_t;
......@@ -261,6 +268,8 @@ typedef struct {
uint8_t max_ldpc_iterations;
/// number of iterations used in last LDPC decoding
uint8_t last_iteration_cnt;
/// max number of segments for LDPC decoding
int a_segments;
} NR_gNB_ULSCH_t;
typedef struct {
......
......@@ -210,13 +210,15 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0);
}
void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req, int *decodeSuccessCount) {
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
int r = rdata->segment_r;
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[rdata->ulsch_id]->harq_processes[rdata->harq_pid]->ulsch_pdu;
bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
if (decodeSuccess)
(*decodeSuccessCount)++;
ulsch_harq->processedSegments++;
LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n",
rdata->segment_r, ulsch_harq->processedSegments, rdata->nbSegments);
......@@ -226,24 +228,25 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
memcpy(ulsch_harq->b+rdata->offset,
ulsch_harq->c[r],
rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
} else {
if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
int nb = abortTpoolJob(&gNB->threadPool, req->key);
nb += abortNotifiedFIFOJob(&gNB->respDecode, req->key);
gNB->nbDecode-=nb;
LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb);
LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n",
ulsch_harq->processedSegments, nb, rdata->nbSegments);
ulsch_harq->processedSegments=rdata->nbSegments;
}
LOG_D(PHY,"uplink segment error %d/%d\n",rdata->segment_r,rdata->nbSegments);
LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
}
//int dumpsig=0;
// if all segments are done
if (rdata->nbSegments == ulsch_harq->processedSegments) {
if (decodeSuccess && !gNB->pusch_vars[rdata->ulsch_id]->DTX) {
/* check global CRC */
if (*decodeSuccessCount == rdata->nbSegments && rdata->nbSegments > 1) {
int A = ulsch_harq->TBS * 8;
int crc_length = A > 3824 ? 3 : 2;
int crc_type = A > 3824 ? CRC24_A : CRC16;
if (!check_crc(ulsch_harq->b, A + crc_length*8, 0 /* F - unused */, crc_type)) {
*decodeSuccessCount = 0;
LOG_E(PHY, "LDPC global CRC fails, but individual LDPC CRC succeeded\n");
}
}
if (*decodeSuccessCount == rdata->nbSegments && !gNB->pusch_vars[rdata->ulsch_id]->DTX) {
LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation (all seg) %d)\n",
gNB->Mod_id,ulsch_harq->frame,ulsch_harq->slot,rdata->harq_pid,pusch_pdu->pusch_data.new_data_indicator,ulsch_harq->status,ulsch_harq->round,ulsch_harq->TBS,rdata->decodeIterations);
ulsch_harq->status = SCH_IDLE;
......@@ -381,11 +384,12 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH
harq_pid,
G);
if (enable_ldpc_offload ==0) {
int decodeSuccessCount = 0;
while (gNB->nbDecode > 0) {
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
if (req == NULL)
break; // Tpool has been stopped
nr_postDecode(gNB, req);
nr_postDecode(gNB, req, &decodeSuccessCount);
delNotifiedFIFO_elt(req);
}
}
......@@ -851,6 +855,15 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
Therefore, we don't yet call nr_fill_indication, it will be called later */
nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1);
pusch_DTX++;
/* if round == 0 we need to clear some data because nr_ulsch_decoding() won't do it for the retransmissions */
if (ulsch_harq->round == 0) {
int r;
LOG_D(PHY, "DTX for round 0, clear mandatory data\n");
for (r = 0; r < ulsch->a_segments; r++) {
ulsch_harq->crc_ok[r] = false;
memset(ulsch_harq->d[r], 0, (68*384)*sizeof(int16_t));
}
}
continue;
}
} else {
......
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