mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-21 00:20:30 +00:00
Compare commits
4 Commits
config_api
...
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]->c);
|
||||||
free_and_zero(ulsch->harq_processes[i]->d);
|
free_and_zero(ulsch->harq_processes[i]->d);
|
||||||
|
free_and_zero(ulsch->harq_processes[i]->crc_ok);
|
||||||
free_and_zero(ulsch->harq_processes[i]);
|
free_and_zero(ulsch->harq_processes[i]);
|
||||||
ulsch->harq_processes[i] = NULL;
|
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 = (NR_gNB_ULSCH_t *)malloc16_clear(sizeof(NR_gNB_ULSCH_t));
|
||||||
|
|
||||||
ulsch->max_ldpc_iterations = max_ldpc_iterations;
|
ulsch->max_ldpc_iterations = max_ldpc_iterations;
|
||||||
|
ulsch->a_segments = a_segments;
|
||||||
|
|
||||||
for (i=0; i<NR_MAX_ULSCH_HARQ_PROCESSES; i++) {
|
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] = (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]->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]->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 *));
|
ulsch->harq_processes[i]->d = (int16_t**)malloc16_clear(a_segments*sizeof(int16_t *));
|
||||||
for (r=0; r<a_segments; r++) {
|
for (r=0; r<a_segments; r++) {
|
||||||
ulsch->harq_processes[i]->c[r] = (uint8_t*)malloc16_clear(8448*sizeof(uint8_t));
|
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;
|
ldpcDecode_t *rdata = (ldpcDecode_t*) arg;
|
||||||
PHY_VARS_gNB *phy_vars_gNB = rdata->gNB;
|
PHY_VARS_gNB *phy_vars_gNB = rdata->gNB;
|
||||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
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;
|
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||||
int length_dec;
|
int length_dec;
|
||||||
int no_iteration_ldpc;
|
int no_iteration_ldpc;
|
||||||
@@ -252,6 +260,15 @@ void nr_processULSegment(void* arg) {
|
|||||||
stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
|
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);
|
memset(ulsch_harq->c[r],0,Kr_bytes);
|
||||||
|
|
||||||
if (ulsch_harq->C == 1) {
|
if (ulsch_harq->C == 1) {
|
||||||
@@ -302,11 +319,15 @@ void nr_processULSegment(void* arg) {
|
|||||||
#endif
|
#endif
|
||||||
rdata->decodeIterations = no_iteration_ldpc;
|
rdata->decodeIterations = no_iteration_ldpc;
|
||||||
if (rdata->decodeIterations > p_decoderParms->numMaxIter) rdata->decodeIterations--;
|
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 {
|
} else {
|
||||||
#ifdef PRINT_CRC_CHECK
|
#ifdef PRINT_CRC_CHECK
|
||||||
LOG_I(PHY,"CRC NOK\n");
|
LOG_I(PHY,"CRC NOK\n");
|
||||||
#endif
|
#endif
|
||||||
rdata->decodeIterations = max_ldpc_iterations + 1;
|
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 ++) {
|
for (int m=0; m < Kr>>3; m ++) {
|
||||||
@@ -623,6 +644,9 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
|||||||
else {
|
else {
|
||||||
dtx_det = 0;
|
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++) {
|
for (int r = 0; r < harq_process->C; r++) {
|
||||||
int E = nr_get_E(G, harq_process->C, Qm, n_layers, 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}};
|
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 = ulsch;
|
||||||
rdata->ulsch_id = ULSCH_id;
|
rdata->ulsch_id = ULSCH_id;
|
||||||
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
|
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);
|
pushTpool(&phy_vars_gNB->threadPool, req);
|
||||||
phy_vars_gNB->nbDecode++;
|
phy_vars_gNB->nbDecode++;
|
||||||
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", 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;
|
uint32_t B;
|
||||||
/// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2)
|
/// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2)
|
||||||
uint8_t **c;
|
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)
|
/// Number of bits in each code block (38.212 V15.4.0 section 5.2.2)
|
||||||
uint32_t K;
|
uint32_t K;
|
||||||
/// Number of "Filler" bits added in the code block segmentation (38.212 V15.4.0 section 5.2.2)
|
/// 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.
|
/// Last index of LLR buffer that contains information.
|
||||||
/// Used for computing LDPC decoder R
|
/// Used for computing LDPC decoder R
|
||||||
int llrLen;
|
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;
|
} NR_UL_gNB_HARQ_t;
|
||||||
|
|
||||||
@@ -261,6 +268,8 @@ typedef struct {
|
|||||||
uint8_t max_ldpc_iterations;
|
uint8_t max_ldpc_iterations;
|
||||||
/// number of iterations used in last LDPC decoding
|
/// number of iterations used in last LDPC decoding
|
||||||
uint8_t last_iteration_cnt;
|
uint8_t last_iteration_cnt;
|
||||||
|
/// max number of segments for LDPC decoding
|
||||||
|
int a_segments;
|
||||||
} NR_gNB_ULSCH_t;
|
} NR_gNB_ULSCH_t;
|
||||||
|
|
||||||
typedef struct {
|
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);
|
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);
|
ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
|
||||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
||||||
NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
|
NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
|
||||||
int r = rdata->segment_r;
|
int r = rdata->segment_r;
|
||||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[rdata->ulsch_id]->harq_processes[rdata->harq_pid]->ulsch_pdu;
|
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);
|
bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
|
||||||
|
if (decodeSuccess)
|
||||||
|
(*decodeSuccessCount)++;
|
||||||
ulsch_harq->processedSegments++;
|
ulsch_harq->processedSegments++;
|
||||||
LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n",
|
LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n",
|
||||||
rdata->segment_r, ulsch_harq->processedSegments, rdata->nbSegments);
|
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,
|
memcpy(ulsch_harq->b+rdata->offset,
|
||||||
ulsch_harq->c[r],
|
ulsch_harq->c[r],
|
||||||
rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
|
rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
|
LOG_D(PHY,"uplink segment error %d/%d\n",rdata->segment_r,rdata->nbSegments);
|
||||||
int nb = abortTpoolJob(&gNB->threadPool, req->key);
|
LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//int dumpsig=0;
|
//int dumpsig=0;
|
||||||
// if all segments are done
|
// if all segments are done
|
||||||
if (rdata->nbSegments == ulsch_harq->processedSegments) {
|
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",
|
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);
|
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;
|
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,
|
harq_pid,
|
||||||
G);
|
G);
|
||||||
if (enable_ldpc_offload ==0) {
|
if (enable_ldpc_offload ==0) {
|
||||||
|
int decodeSuccessCount = 0;
|
||||||
while (gNB->nbDecode > 0) {
|
while (gNB->nbDecode > 0) {
|
||||||
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
|
notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool);
|
||||||
if (req == NULL)
|
if (req == NULL)
|
||||||
break; // Tpool has been stopped
|
break; // Tpool has been stopped
|
||||||
nr_postDecode(gNB, req);
|
nr_postDecode(gNB, req, &decodeSuccessCount);
|
||||||
delNotifiedFIFO_elt(req);
|
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 */
|
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);
|
nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1);
|
||||||
pusch_DTX++;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user