mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 12:40:28 +00:00
Compare commits
4 Commits
oru
...
bugfix-ldp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c9a0dea27 | ||
|
|
b038ee0af8 | ||
|
|
7fc31d9ca9 | ||
|
|
6d66049e1f |
@@ -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 {
|
||||
|
||||
@@ -208,13 +208,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);
|
||||
@@ -224,24 +226,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;
|
||||
@@ -379,11 +382,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);
|
||||
}
|
||||
}
|
||||
@@ -839,6 +843,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 {
|
||||
|
||||
Reference in New Issue
Block a user