feat(nrLDPC_coding_interface): Use reworked interface in gNB
This commit is contained in:
@@ -403,7 +403,6 @@ void init_eNB_afterRU(void) {
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_inst; inst++) {
|
||||
gNB = RC.gNB[inst];
|
||||
gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
|
||||
|
||||
phy_init_nr_gNB(gNB);
|
||||
|
||||
|
||||
@@ -142,7 +142,6 @@ extern "C"
|
||||
#define EMULATE_L1 softmodem_params.emulate_l1
|
||||
#define CONTINUOUS_TX softmodem_params.continuous_tx
|
||||
#define SYNC_REF softmodem_params.sync_ref
|
||||
#define LDPC_OFFLOAD_FLAG softmodem_params.ldpc_offload_flag
|
||||
|
||||
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
|
||||
|
||||
@@ -321,7 +320,6 @@ typedef struct {
|
||||
int continuous_tx;
|
||||
uint32_t sync_ref;
|
||||
int no_itti;
|
||||
int ldpc_offload_flag;
|
||||
int threequarter_fs;
|
||||
} softmodem_params_t;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
@@ -40,6 +41,7 @@
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
#include <string.h>
|
||||
|
||||
int l1_north_init_gNB()
|
||||
{
|
||||
@@ -96,9 +98,6 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame)
|
||||
}
|
||||
}
|
||||
|
||||
// A global var to reduce the changes size
|
||||
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
|
||||
|
||||
void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
{
|
||||
// shortcuts
|
||||
@@ -134,15 +133,11 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
|
||||
nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH
|
||||
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
int ret_loader = load_nrLDPC_coding_interface(NULL, &gNB->nrLDPC_coding_interface);
|
||||
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
|
||||
|
||||
pthread_mutex_init(&gNB->UL_INFO.crc_rx_mutex, NULL);
|
||||
|
||||
if (gNB->ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
else
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
|
||||
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
|
||||
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
|
||||
|
||||
|
||||
@@ -65,6 +65,67 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats;
|
||||
time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats;
|
||||
|
||||
size_t size_output = 0;
|
||||
|
||||
for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n",
|
||||
rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize);
|
||||
|
||||
const int Qm = rel15->qamModOrder[0];
|
||||
|
||||
/* PTRS */
|
||||
uint16_t dlPtrsSymPos = 0;
|
||||
int n_ptrs = 0;
|
||||
uint32_t ptrsSymbPerSlot = 0;
|
||||
if(rel15->pduBitmap & 0x1) {
|
||||
set_ptrs_symb_idx(&dlPtrsSymPos,
|
||||
rel15->NrOfSymbols,
|
||||
rel15->StartSymbolIndex,
|
||||
1 << rel15->PTRSTimeDensity,
|
||||
rel15->dlDmrsSymbPos);
|
||||
n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity;
|
||||
ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||
}
|
||||
harq->unav_res = ptrsSymbPerSlot * n_ptrs;
|
||||
|
||||
/// CRC, coding, interleaving and rate matching
|
||||
AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
|
||||
|
||||
/* output and its parts for each dlsch should be aligned on 64 bytes
|
||||
* => size_output is a sum of parts sizes rounded up to a multiple of 64
|
||||
*/
|
||||
size_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers;
|
||||
size_output += (size_output_tb + 63 - ((size_output_tb + 63) % 64));
|
||||
}
|
||||
|
||||
unsigned char output[size_output] __attribute__((aligned(64)));
|
||||
|
||||
bzero(output, size_output);
|
||||
|
||||
size_t offset_output = 0;
|
||||
|
||||
start_meas(dlsch_encoding_stats);
|
||||
if (nr_dlsch_encoding(gNB,
|
||||
msgTx,
|
||||
frame,
|
||||
slot,
|
||||
frame_parms,
|
||||
output,
|
||||
tinput,
|
||||
tprep,
|
||||
tparity,
|
||||
toutput,
|
||||
dlsch_rate_matching_stats,
|
||||
dlsch_interleaving_stats,
|
||||
dlsch_segmentation_stats) == -1) {
|
||||
return;
|
||||
}
|
||||
stop_meas(dlsch_encoding_stats);
|
||||
|
||||
for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
|
||||
@@ -100,45 +161,24 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
}
|
||||
harq->unav_res = ptrsSymbPerSlot * n_ptrs;
|
||||
|
||||
/// CRC, coding, interleaving and rate matching
|
||||
AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
|
||||
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers] __attribute__((aligned(64)));
|
||||
bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers);
|
||||
start_meas(dlsch_encoding_stats);
|
||||
|
||||
if (nr_dlsch_encoding(gNB,
|
||||
frame,
|
||||
slot,
|
||||
harq,
|
||||
frame_parms,
|
||||
output,
|
||||
tinput,
|
||||
tprep,
|
||||
tparity,
|
||||
toutput,
|
||||
dlsch_rate_matching_stats,
|
||||
dlsch_interleaving_stats,
|
||||
dlsch_segmentation_stats) == -1)
|
||||
return;
|
||||
stop_meas(dlsch_encoding_stats);
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH encoding:\nPayload:\n");
|
||||
for (int i=0; i<harq->B>>7; i++) {
|
||||
for (int j=0; j<16; j++)
|
||||
printf("0x%02x\t", harq->pdu[(i<<4)+j]);
|
||||
for (int i = 0; i < (harq->B>>3); i += 16) {
|
||||
for (int j=0; j < 16; j++)
|
||||
printf("0x%02x\t", harq->pdu[i + j]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\nEncoded payload:\n");
|
||||
for (int i=0; i<encoded_length>>3; i++) {
|
||||
for (int j=0; j<8; j++)
|
||||
printf("%d", output[(i<<3)+j]);
|
||||
for (int i = 0; i < encoded_length; i += 8) {
|
||||
for (int j = 0; j < 8; j++)
|
||||
printf("%d", output[offset_output + i + j]);
|
||||
printf("\t");
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
if (IS_SOFTMODEM_DLSIM)
|
||||
memcpy(harq->f, output, encoded_length);
|
||||
memcpy(harq->f, &output[offset_output], encoded_length);
|
||||
|
||||
c16_t mod_symbs[rel15->NrOfCodewords][encoded_length];
|
||||
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
|
||||
@@ -147,7 +187,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
uint32_t scrambled_output[(encoded_length>>5)+4]; // modulator acces by 4 bytes in some cases
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
if ( encoded_length > rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers) abort();
|
||||
nr_pdsch_codeword_scrambling(output, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
|
||||
nr_pdsch_codeword_scrambling(&output[offset_output], encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output);
|
||||
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH scrambling:\n");
|
||||
@@ -176,6 +216,12 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
}
|
||||
/// Resource mapping
|
||||
|
||||
/* output and its parts for each dlsch should be aligned on 64 bytes
|
||||
* => offset_output should remain a multiple of 64 with enough offset to fit each dlsch
|
||||
*/
|
||||
uint32_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers;
|
||||
offset_output += (size_output_tb + 63) & ~63;
|
||||
|
||||
// Non interleaved VRB to PRB mapping
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart+rel15->BWPStart)*NR_NB_SC_PER_RB;
|
||||
if (start_sc >= frame_parms->ofdm_symbol_size)
|
||||
|
||||
@@ -44,18 +44,18 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx,
|
||||
int slot);
|
||||
|
||||
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
uint8_t slot,
|
||||
NR_DL_gNB_HARQ_t *harq,
|
||||
NR_DL_FRAME_PARMS* frame_parms,
|
||||
unsigned char * output,
|
||||
time_stats_t *tinput,
|
||||
time_stats_t *tprep,
|
||||
time_stats_t *tparity,
|
||||
time_stats_t *toutput,
|
||||
time_stats_t *dlsch_rate_matching_stats,
|
||||
time_stats_t *dlsch_interleaving_stats,
|
||||
time_stats_t *dlsch_segmentation_stats);
|
||||
processingData_L1tx_t *msgTx,
|
||||
int frame,
|
||||
uint8_t slot,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
unsigned char *output,
|
||||
time_stats_t *tinput,
|
||||
time_stats_t *tprep,
|
||||
time_stats_t *tparity,
|
||||
time_stats_t *toutput,
|
||||
time_stats_t *dlsch_rate_matching_stats,
|
||||
time_stats_t *dlsch_interleaving_stats,
|
||||
time_stats_t *dlsch_segmentation_stats);
|
||||
|
||||
void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size);
|
||||
|
||||
|
||||
@@ -19,21 +19,15 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/LTE_TRANSPORT/dlsch_coding.c
|
||||
/*! \file PHY/NR_TRANSPORT/nr_dlsch_coding_slot.c
|
||||
* \brief Top-level routines for implementing LDPC-coded (DLSCH) transport channels from 38-212, 15.2
|
||||
* \author H.Wang
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email:
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
@@ -117,130 +111,10 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB)
|
||||
return(dlsch);
|
||||
}
|
||||
|
||||
static void ldpc8blocks(void *p)
|
||||
{
|
||||
encoder_implemparams_t *impp=(encoder_implemparams_t *) p;
|
||||
NR_DL_gNB_HARQ_t *harq = (NR_DL_gNB_HARQ_t *)impp->harq;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
uint8_t mod_order = rel15->qamModOrder[0];
|
||||
uint16_t nb_rb = rel15->rbSize;
|
||||
uint8_t nb_symb_sch = rel15->NrOfSymbols;
|
||||
uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
|
||||
uint32_t A = rel15->TBSize[0]<<3;
|
||||
uint8_t nb_re_dmrs;
|
||||
|
||||
if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1)
|
||||
nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData;
|
||||
else
|
||||
nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData;
|
||||
|
||||
unsigned int G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq->unav_res, mod_order, rel15->nrOfLayers);
|
||||
LOG_D(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n",
|
||||
A,impp->K,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,(int)mod_order);
|
||||
// nrLDPC_encoder output is in "d"
|
||||
// let's make this interface happy!
|
||||
uint8_t tmp[8][68 * 384]__attribute__((aligned(32)));
|
||||
uint8_t *d[impp->n_segments];
|
||||
for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ )
|
||||
d[rr] = tmp[i];
|
||||
ldpc_interface.LDPCencoder(harq->c, d, impp);
|
||||
// Compute where to place in output buffer that is concatenation of all segments
|
||||
uint32_t r_offset=0;
|
||||
for (int i=0; i < impp->macro_num*8; i++ )
|
||||
r_offset+=nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, i);
|
||||
for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) {
|
||||
if (impp->F>0) {
|
||||
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
|
||||
memset(&d[rr][impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
|
||||
#endif
|
||||
uint32_t E = nr_get_E(G, impp->n_segments, mod_order, rel15->nrOfLayers, rr);
|
||||
//#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb "
|
||||
"%d,nrOfLayer %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
G,
|
||||
E,
|
||||
impp->F,
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
mod_order,
|
||||
nb_rb,
|
||||
rel15->nrOfLayers);
|
||||
|
||||
uint32_t Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
|
||||
uint8_t e[E];
|
||||
bzero (e, E);
|
||||
nr_rate_matching_ldpc(Tbslbrm,
|
||||
impp->BG,
|
||||
impp->Zc,
|
||||
d[rr],
|
||||
e,
|
||||
impp->n_segments,
|
||||
impp->F,
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
rel15->rvIndex[0],
|
||||
E);
|
||||
if (impp->K - impp->F - 2 * impp->Zc > E) {
|
||||
LOG_E(PHY,
|
||||
"dlsch coding A %d Kr %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n",
|
||||
A,
|
||||
impp->K,
|
||||
G,
|
||||
nb_rb,
|
||||
nb_symb_sch,
|
||||
nb_re_dmrs,
|
||||
length_dmrs,
|
||||
(int)mod_order);
|
||||
|
||||
LOG_E(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d mod_order %d, "
|
||||
"nb_rb %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
G,
|
||||
E,
|
||||
impp->K,
|
||||
impp->F,
|
||||
impp->K - impp->F - 2 * impp->Zc,
|
||||
mod_order,
|
||||
nb_rb);
|
||||
}
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output ratematching e[%d]= %d r_offset %u\n", i,e[i], r_offset);
|
||||
|
||||
#endif
|
||||
nr_interleaving_ldpc(E,
|
||||
mod_order,
|
||||
e,
|
||||
impp->output+r_offset);
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output interleaving f[%d]= %d r_offset %u\n", i,impp->output[i+r_offset], r_offset);
|
||||
|
||||
if (r==impp->n_segments-1)
|
||||
write_output("enc_output.m","enc",impp->output,G,1,4);
|
||||
|
||||
#endif
|
||||
r_offset += E;
|
||||
}
|
||||
|
||||
// Task running in // completed
|
||||
completed_task_ans(impp->ans);
|
||||
}
|
||||
|
||||
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
processingData_L1tx_t *msgTx,
|
||||
int frame,
|
||||
uint8_t slot,
|
||||
NR_DL_gNB_HARQ_t *harq,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
unsigned char *output,
|
||||
time_stats_t *tinput,
|
||||
@@ -251,145 +125,195 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
time_stats_t *dlsch_interleaving_stats,
|
||||
time_stats_t *dlsch_segmentation_stats)
|
||||
{
|
||||
encoder_implemparams_t impp;
|
||||
impp.output=output;
|
||||
unsigned int crc=1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
impp.Zc = harq->Z;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
uint32_t A = rel15->TBSize[0]<<3;
|
||||
unsigned char *a=harq->pdu;
|
||||
if (rel15->rnti != SI_RNTI) {
|
||||
ws_trace_t tmp = {.nr = true,
|
||||
.direction = DIRECTION_DOWNLINK,
|
||||
.pdu_buffer = a,
|
||||
.pdu_buffer_size = rel15->TBSize[0],
|
||||
.ueid = 0,
|
||||
.rntiType = WS_C_RNTI,
|
||||
.rnti = rel15->rnti,
|
||||
.sysFrame = frame,
|
||||
.subframe = slot,
|
||||
.harq_pid = 0, // difficult to find the harq pid here
|
||||
.oob_event = 0,
|
||||
.oob_event_value = 0};
|
||||
trace_pdu(&tmp);
|
||||
}
|
||||
|
||||
NR_gNB_PHY_STATS_t *phy_stats = NULL;
|
||||
if (rel15->rnti != 0xFFFF)
|
||||
phy_stats = get_phy_stats(gNB, rel15->rnti);
|
||||
nrLDPC_TB_encoding_parameters_t TBs[msgTx->num_pdsch_slot];
|
||||
memset(TBs, 0, sizeof(TBs));
|
||||
nrLDPC_slot_encoding_parameters_t slot_parameters = {
|
||||
.frame = frame,
|
||||
.slot = slot,
|
||||
.nb_TBs = msgTx->num_pdsch_slot,
|
||||
.threadPool = &gNB->threadPool,
|
||||
.tinput = tinput,
|
||||
.tprep = tprep,
|
||||
.tparity = tparity,
|
||||
.toutput = toutput,
|
||||
.TBs = TBs
|
||||
};
|
||||
|
||||
if (phy_stats) {
|
||||
phy_stats->frame = frame;
|
||||
phy_stats->dlsch_stats.total_bytes_tx += rel15->TBSize[0];
|
||||
phy_stats->dlsch_stats.current_RI = rel15->nrOfLayers;
|
||||
phy_stats->dlsch_stats.current_Qm = rel15->qamModOrder[0];
|
||||
}
|
||||
int num_segments = 0;
|
||||
|
||||
int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056;
|
||||
int B;
|
||||
if (A > NR_MAX_PDSCH_TBS) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
crc = crc24a(a,A)>>8;
|
||||
a[A>>3] = ((uint8_t *)&crc)[2];
|
||||
a[1+(A>>3)] = ((uint8_t *)&crc)[1];
|
||||
a[2+(A>>3)] = ((uint8_t *)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
|
||||
B = A + 24;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 4 <= max_bytes,
|
||||
"A %d is too big (A/8+4 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 4,
|
||||
max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
|
||||
} else {
|
||||
// Add 16-bit crc (polynomial A) to payload
|
||||
crc = crc16(a,A)>>16;
|
||||
a[A>>3] = ((uint8_t *)&crc)[1];
|
||||
a[1+(A>>3)] = ((uint8_t *)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
|
||||
B = A + 16;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 3 <= max_bytes,
|
||||
"A %d is too big (A/8+3 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 3,
|
||||
max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
|
||||
}
|
||||
for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
|
||||
impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph;
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
|
||||
start_meas(dlsch_segmentation_stats);
|
||||
impp.Kb = nr_segmentation(harq->b, harq->c, B, &impp.n_segments, &impp.K, &impp.Zc, &impp.F, impp.BG);
|
||||
stop_meas(dlsch_segmentation_stats);
|
||||
|
||||
if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B);
|
||||
return(-1);
|
||||
}
|
||||
for (int r=0; r<impp.n_segments; r++) {
|
||||
//d_tmp[r] = &harq->d[r][0];
|
||||
//channel_input[r] = &harq->d[r][0];
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, impp.F);
|
||||
LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,impp.n_segments);
|
||||
LOG_D(PHY,"input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2],harq->c[r][3], harq->c[r][4]);
|
||||
|
||||
for (int cnt =0 ; cnt < 22*(*impp.Zc)/8; cnt ++) {
|
||||
LOG_D(PHY,"%d ", harq->c[r][cnt]);
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
unsigned int crc=1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
uint32_t A = rel15->TBSize[0]<<3;
|
||||
unsigned char *a=harq->pdu;
|
||||
if (rel15->rnti != SI_RNTI) {
|
||||
ws_trace_t tmp = {.nr = true,
|
||||
.direction = DIRECTION_DOWNLINK,
|
||||
.pdu_buffer = a,
|
||||
.pdu_buffer_size = rel15->TBSize[0],
|
||||
.ueid = 0,
|
||||
.rntiType = WS_C_RNTI,
|
||||
.rnti = rel15->rnti,
|
||||
.sysFrame = frame,
|
||||
.subframe = slot,
|
||||
.harq_pid = 0, // difficult to find the harq pid here
|
||||
.oob_event = 0,
|
||||
.oob_event_value = 0};
|
||||
trace_pdu(&tmp);
|
||||
}
|
||||
|
||||
LOG_D(PHY,"\n");
|
||||
#endif
|
||||
//ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0);
|
||||
//ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL);
|
||||
NR_gNB_PHY_STATS_t *phy_stats = NULL;
|
||||
if (rel15->rnti != 0xFFFF)
|
||||
phy_stats = get_phy_stats(gNB, rel15->rnti);
|
||||
|
||||
if (phy_stats) {
|
||||
phy_stats->frame = frame;
|
||||
phy_stats->dlsch_stats.total_bytes_tx += rel15->TBSize[0];
|
||||
phy_stats->dlsch_stats.current_RI = rel15->nrOfLayers;
|
||||
phy_stats->dlsch_stats.current_Qm = rel15->qamModOrder[0];
|
||||
}
|
||||
|
||||
int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056;
|
||||
int B;
|
||||
if (A > NR_MAX_PDSCH_TBS) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
crc = crc24a(a,A)>>8;
|
||||
a[A>>3] = ((uint8_t *)&crc)[2];
|
||||
a[1+(A>>3)] = ((uint8_t *)&crc)[1];
|
||||
a[2+(A>>3)] = ((uint8_t *)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
|
||||
B = A + 24;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 4 <= max_bytes,
|
||||
"A %d is too big (A/8+4 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 4,
|
||||
max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
|
||||
} else {
|
||||
// Add 16-bit crc (polynomial A) to payload
|
||||
crc = crc16(a,A)>>16;
|
||||
a[A>>3] = ((uint8_t *)&crc)[1];
|
||||
a[1+(A>>3)] = ((uint8_t *)&crc)[0];
|
||||
//printf("CRC %x (A %d)\n",crc,A);
|
||||
//printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
|
||||
B = A + 16;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 3 <= max_bytes,
|
||||
"A %d is too big (A/8+3 = %d > %d)\n",
|
||||
A,
|
||||
(A / 8) + 3,
|
||||
max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
|
||||
}
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id];
|
||||
|
||||
// The harq_pid is not unique among the active HARQ processes in the instance so we use dlsch_id instead
|
||||
TB_parameters->harq_unique_pid = dlsch_id;
|
||||
TB_parameters->BG = rel15->maintenance_parms_v3.ldpcBaseGraph;
|
||||
TB_parameters->Z = harq->Z;
|
||||
TB_parameters->A = A;
|
||||
start_meas(dlsch_segmentation_stats);
|
||||
TB_parameters->Kb = nr_segmentation(harq->b,
|
||||
harq->c,
|
||||
B,
|
||||
&TB_parameters->C,
|
||||
&TB_parameters->K,
|
||||
&TB_parameters->Z,
|
||||
&TB_parameters->F,
|
||||
TB_parameters->BG);
|
||||
stop_meas(dlsch_segmentation_stats);
|
||||
|
||||
if (TB_parameters->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B);
|
||||
return(-1);
|
||||
}
|
||||
num_segments += TB_parameters->C;
|
||||
|
||||
}
|
||||
|
||||
impp.tprep = tprep;
|
||||
impp.tinput = tinput;
|
||||
impp.tparity = tparity;
|
||||
impp.toutput = toutput;
|
||||
impp.harq = harq;
|
||||
if (gNB->ldpc_offload_flag) {
|
||||
impp.Qm = rel15->qamModOrder[0];
|
||||
impp.Tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
impp.rv = rel15->rvIndex[0];
|
||||
nrLDPC_segment_encoding_parameters_t segments[num_segments];
|
||||
memset(segments, 0, sizeof(segments));
|
||||
size_t segments_offset = 0;
|
||||
size_t dlsch_offset = 0;
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id];
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
LOG_D(PHY, "Encoder: B %d F %d \n", harq->B, TB_parameters->F);
|
||||
LOG_D(PHY, "start ldpc encoder segment %d/%d\n", r, TB_parameters->C);
|
||||
LOG_D(PHY, "input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2], harq->c[r][3], harq->c[r][4]);
|
||||
for (int cnt = 0; cnt < 22 * (TB_parameters->Z) / 8; cnt++) {
|
||||
LOG_D(PHY, "%d ", harq->c[r][cnt]);
|
||||
}
|
||||
LOG_D(PHY, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
TB_parameters->nb_rb = rel15->rbSize;
|
||||
TB_parameters->Qm = rel15->qamModOrder[0];
|
||||
TB_parameters->mcs = rel15->mcsIndex[0];
|
||||
TB_parameters->nb_layers = rel15->nrOfLayers;
|
||||
TB_parameters->rv_index = rel15->rvIndex[0];
|
||||
|
||||
int nb_re_dmrs =
|
||||
(rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData);
|
||||
impp.G = nr_get_G(rel15->rbSize,
|
||||
rel15->NrOfSymbols,
|
||||
nb_re_dmrs,
|
||||
get_num_dmrs(rel15->dlDmrsSymbPos),
|
||||
harq->unav_res,
|
||||
rel15->qamModOrder[0],
|
||||
rel15->nrOfLayers);
|
||||
for (int r = 0; r < impp.n_segments; r++) {
|
||||
impp.perCB[r].E_cb = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r);
|
||||
}
|
||||
ldpc_interface_offload.LDPCencoder(harq->c, &impp.output, &impp);
|
||||
} else {
|
||||
size_t const n_seg = (impp.n_segments / 8 + ((impp.n_segments & 7) == 0 ? 0 : 1));
|
||||
TB_parameters->G = nr_get_G(rel15->rbSize,
|
||||
rel15->NrOfSymbols,
|
||||
nb_re_dmrs,
|
||||
get_num_dmrs(rel15->dlDmrsSymbPos),
|
||||
harq->unav_res,
|
||||
rel15->qamModOrder[0],
|
||||
rel15->nrOfLayers);
|
||||
|
||||
encoder_implemparams_t arr[n_seg];
|
||||
task_ans_t ans[n_seg];
|
||||
memset(ans, 0, n_seg * sizeof(task_ans_t));
|
||||
TB_parameters->tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
|
||||
for (int j = 0; j < n_seg; j++) {
|
||||
encoder_implemparams_t *perJobImpp = &arr[j];
|
||||
*perJobImpp = impp;
|
||||
perJobImpp->macro_num = j;
|
||||
perJobImpp->ans = &ans[j];
|
||||
TB_parameters->segments = &segments[segments_offset];
|
||||
|
||||
size_t r_offset = 0;
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
|
||||
segment_parameters->c = harq->c[r];
|
||||
segment_parameters->E = nr_get_E(TB_parameters->G,
|
||||
TB_parameters->C,
|
||||
TB_parameters->Qm,
|
||||
rel15->nrOfLayers,
|
||||
r);
|
||||
segment_parameters->output = &output[dlsch_offset + r_offset];
|
||||
r_offset += segment_parameters->E;
|
||||
|
||||
reset_meas(&segment_parameters->ts_interleave);
|
||||
reset_meas(&segment_parameters->ts_rate_match);
|
||||
reset_meas(&segment_parameters->ts_ldpc_encode);
|
||||
|
||||
task_t t = {.func = ldpc8blocks, .args = perJobImpp};
|
||||
pushTpool(&gNB->threadPool, t);
|
||||
}
|
||||
|
||||
join_task_ans(ans, n_seg);
|
||||
segments_offset += TB_parameters->C;
|
||||
|
||||
/* output and its parts for each dlsch should be aligned on 64 bytes
|
||||
* => dlsch_offset should remain a multiple of 64 with enough offset to fit each dlsch
|
||||
*/
|
||||
const size_t dlsch_size = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * rel15->qamModOrder[0] * rel15->nrOfLayers;
|
||||
dlsch_offset += (dlsch_size + 63 - ((dlsch_size + 63) % 64));
|
||||
}
|
||||
|
||||
gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,28 +42,23 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL);
|
||||
|
||||
NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL);
|
||||
|
||||
/*! \brief Perform PUSCH decoding. TS 38.212 V15.4.0 subclause 6.2
|
||||
/*! \brief Perform PUSCH decoding for the whole current received TTI. TS 38.212 V15.4.0 subclause 6.2
|
||||
@param phy_vars_gNB, Pointer to PHY data structure for gNB
|
||||
@param UE_id, ID of UE transmitting this PUSCH
|
||||
@param ulsch_llr, Pointer to received llr in ulsch
|
||||
@param frame_parms, Pointer to frame descriptor structure
|
||||
@param nb_symb_sch, number of symbols used in the uplink shared channel
|
||||
@param nb_re_dmrs, number of DMRS resource elements in one RB
|
||||
@param frame, current received frame
|
||||
@param nr_tti_rx, current received TTI
|
||||
@param harq_pid, harq process id
|
||||
@param is_crnti
|
||||
@param G
|
||||
@param ULSCH_ids, array of ULSCH ids
|
||||
@param nb_pusch, number of uplink shared channels
|
||||
*/
|
||||
|
||||
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
uint8_t UE_id,
|
||||
short *ulsch_llr,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
uint32_t frame,
|
||||
uint8_t nr_tti_rx,
|
||||
uint8_t harq_pid,
|
||||
uint32_t G,
|
||||
thread_info_tm_t *t_info);
|
||||
uint32_t *G,
|
||||
uint8_t *ULSCH_ids,
|
||||
int nb_pusch);
|
||||
|
||||
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
|
||||
@param llr, Pointer to llr bits
|
||||
|
||||
@@ -19,15 +19,8 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding.c
|
||||
/*! \file PHY/NR_TRANSPORT/nr_ulsch_decoding_slot.c
|
||||
* \brief Top-level routines for decoding LDPC (ULSCH) transport channels from 38.212, V15.4.0 2018-12
|
||||
* \author Ahmed Hussein
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company Fraunhofer IIS
|
||||
* \email: ahmed.hussein@iis.fraunhofer.de
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
@@ -36,6 +29,7 @@
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
@@ -50,10 +44,6 @@
|
||||
//#define DEBUG_ULSCH_DECODING
|
||||
//#define gNB_DEBUG_TRACE
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <stdalign.h>
|
||||
|
||||
#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
|
||||
//#define DEBUG_CRC
|
||||
#ifdef DEBUG_CRC
|
||||
@@ -123,361 +113,215 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
|
||||
return(ulsch);
|
||||
}
|
||||
|
||||
static void nr_processULSegment(void *arg)
|
||||
{
|
||||
ldpcDecode_t *rdata = (ldpcDecode_t *)arg;
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
|
||||
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||
const int Kr = ulsch_harq->K;
|
||||
const int Kr_bytes = Kr >> 3;
|
||||
const int K_bits_F = Kr - ulsch_harq->F;
|
||||
const int r = rdata->segment_r;
|
||||
const int A = rdata->A;
|
||||
const int E = rdata->E;
|
||||
const int Qm = rdata->Qm;
|
||||
const int rv_index = rdata->rv_index;
|
||||
const int r_offset = rdata->r_offset;
|
||||
const uint8_t kc = rdata->Kc;
|
||||
short *ulsch_llr = rdata->ulsch_llr;
|
||||
const int max_ldpc_iterations = p_decoderParms->numMaxIter;
|
||||
int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32)));
|
||||
|
||||
t_nrLDPC_time_stats procTime = {0};
|
||||
t_nrLDPC_time_stats *p_procTime = &procTime;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////// ulsch_llr =====> ulsch_harq->e //////////////////////////////
|
||||
|
||||
/// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
|
||||
int16_t harq_e[E];
|
||||
|
||||
nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr + r_offset);
|
||||
|
||||
// for (int i =0; i<16; i++)
|
||||
// printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
|
||||
|
||||
|
||||
if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
|
||||
p_decoderParms->BG,
|
||||
p_decoderParms->Z,
|
||||
ulsch_harq->d[r],
|
||||
harq_e,
|
||||
ulsch_harq->C,
|
||||
rv_index,
|
||||
ulsch_harq->d_to_be_cleared[r],
|
||||
E,
|
||||
ulsch_harq->F,
|
||||
Kr - ulsch_harq->F - 2 * (p_decoderParms->Z))
|
||||
== -1) {
|
||||
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
|
||||
rdata->decodeIterations = max_ldpc_iterations + 1;
|
||||
set_abort(&ulsch_harq->abort_decode, true);
|
||||
|
||||
// Task completed
|
||||
completed_task_ans(rdata->ans);
|
||||
return;
|
||||
}
|
||||
|
||||
ulsch_harq->d_to_be_cleared[r] = false;
|
||||
|
||||
memset(ulsch_harq->c[r], 0, Kr_bytes);
|
||||
p_decoderParms->crc_type = crcType(ulsch_harq->C, A);
|
||||
p_decoderParms->E = lenWithCrc(ulsch_harq->C, A);
|
||||
|
||||
// set first 2*Z_c bits to zeros
|
||||
|
||||
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
|
||||
memset(z, 0, 2 * ulsch_harq->Z * sizeof(*z));
|
||||
// set Filler bits
|
||||
memset(z + K_bits_F, 127, ulsch_harq->F * sizeof(*z));
|
||||
// Move coded bits before filler bits
|
||||
memcpy(z + 2 * ulsch_harq->Z, ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(*z));
|
||||
// skip filler bits
|
||||
memcpy(z + Kr, ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(*z));
|
||||
// Saturate coded bits before decoding into 8 bits values
|
||||
simde__m128i *pv = (simde__m128i *)&z;
|
||||
int8_t l[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
simde__m128i *pl = (simde__m128i *)&l;
|
||||
for (int i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl[j] = simde_mm_packs_epi16(pv[i], pv[i + 1]);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
|
||||
rdata->decodeIterations =
|
||||
ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, &ulsch_harq->abort_decode);
|
||||
|
||||
if (rdata->decodeIterations <= p_decoderParms->numMaxIter)
|
||||
memcpy(ulsch_harq->c[r],llrProcBuf, Kr>>3);
|
||||
|
||||
// Task completed
|
||||
completed_task_ans(rdata->ans);
|
||||
}
|
||||
|
||||
int decode_offload(PHY_VARS_gNB *phy_vars_gNB,
|
||||
uint8_t ULSCH_id,
|
||||
short *ulsch_llr,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
t_nrLDPC_dec_params *decParams,
|
||||
uint8_t harq_pid,
|
||||
uint32_t G)
|
||||
{
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
int16_t z_ol[LDPC_MAX_CB_SIZE] __attribute__((aligned(16)));
|
||||
int8_t l_ol[NR_LDPC_MAX_NUM_CB * LDPC_MAX_CB_SIZE] __attribute__((aligned(16)));
|
||||
const int kc = decParams->BG == 2 ? 52 : 68;
|
||||
uint32_t A = (harq_process->TBS) << 3;
|
||||
const int Kr = harq_process->K;
|
||||
const int Kr_bytes = Kr >> 3;
|
||||
int8_t decodeIterations = 0;
|
||||
int r_offset = 0;
|
||||
int offset = 0;
|
||||
// new data received, set processedSegments to 0
|
||||
if (!decParams->setCombIn)
|
||||
harq_process->processedSegments = 0;
|
||||
|
||||
for (int r = 0; r < harq_process->C; r++) {
|
||||
decParams->perCB[r].E_cb = nr_get_E(G, harq_process->C, decParams->Qm, pusch_pdu->nrOfLayers, r);
|
||||
memcpy(z_ol, ulsch_llr + r_offset, decParams->perCB[r].E_cb * sizeof(int16_t));
|
||||
simde__m128i *pv_ol128 = (simde__m128i *)z_ol;
|
||||
simde__m128i *pl_ol128 = (simde__m128i *)&l_ol[offset];
|
||||
for (int i = 0, j = 0; j < ((kc * harq_process->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl_ol128[j] = simde_mm_packs_epi16(pv_ol128[i], pv_ol128[i + 1]);
|
||||
}
|
||||
decParams->F = harq_process->F;
|
||||
r_offset += decParams->perCB[r].E_cb;
|
||||
offset += LDPC_MAX_CB_SIZE;
|
||||
}
|
||||
|
||||
int8_t p_outDec[harq_process->C * Kr_bytes];
|
||||
memset(p_outDec, 0, sizeof(p_outDec));
|
||||
decodeIterations =
|
||||
ldpc_interface_offload.LDPCdecoder(decParams, harq_pid, ULSCH_id, harq_process->C, (int8_t *)l_ol, p_outDec, NULL, NULL);
|
||||
|
||||
if (decodeIterations < 0) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in LDPC decoder offload\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int offset_b = 0;
|
||||
for (int r = 0; r < harq_process->C; r++) {
|
||||
if (decParams->perCB[r].status_cb == 0 || harq_process->C == 1) {
|
||||
memcpy(harq_process->b + offset_b, &p_outDec[offset_b], Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
harq_process->processedSegments++;
|
||||
}
|
||||
offset_b += (Kr_bytes - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
}
|
||||
|
||||
bool crc_valid = false;
|
||||
// CRC check made by the T2, no need to perform CRC check for a single code block twice
|
||||
if (harq_process->processedSegments == harq_process->C) {
|
||||
crc_valid = check_crc(harq_process->b, lenWithCrc(1, A), crcType(1, A));
|
||||
if (harq_process->C == 1 && !crc_valid) {
|
||||
harq_process->processedSegments--;
|
||||
}
|
||||
}
|
||||
|
||||
if (crc_valid) {
|
||||
LOG_D(PHY, "ULSCH: Setting ACK for slot %d TBS %d\n", ulsch->slot, harq_process->TBS);
|
||||
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0);
|
||||
ulsch->active = false;
|
||||
harq_process->round = 0;
|
||||
} else {
|
||||
LOG_D(PHY,
|
||||
"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n",
|
||||
phy_vars_gNB->Mod_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
harq_pid,
|
||||
ulsch->active,
|
||||
harq_process->round,
|
||||
harq_process->TBS);
|
||||
nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0);
|
||||
ulsch->handled = 1;
|
||||
decodeIterations = ulsch->max_ldpc_iterations + 1;
|
||||
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
|
||||
}
|
||||
|
||||
ulsch->last_iteration_cnt = decodeIterations;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
|
||||
uint8_t ULSCH_id,
|
||||
short *ulsch_llr,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
uint32_t frame,
|
||||
uint8_t nr_tti_rx,
|
||||
uint8_t harq_pid,
|
||||
uint32_t G,
|
||||
thread_info_tm_t *t_info)
|
||||
uint32_t *G,
|
||||
uint8_t *ULSCH_ids,
|
||||
int nb_pusch)
|
||||
{
|
||||
if (!ulsch_llr) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1);
|
||||
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
nrLDPC_TB_decoding_parameters_t TBs[nb_pusch];
|
||||
memset(TBs, 0, sizeof(TBs));
|
||||
nrLDPC_slot_decoding_parameters_t slot_parameters = {
|
||||
.frame = frame,
|
||||
.slot = nr_tti_rx,
|
||||
.nb_TBs = nb_pusch,
|
||||
.threadPool = &phy_vars_gNB->threadPool,
|
||||
.TBs = TBs
|
||||
};
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n");
|
||||
return -1;
|
||||
}
|
||||
int max_num_segments = 0;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
const uint16_t nb_rb = pusch_pdu->rb_size;
|
||||
const uint8_t Qm = pusch_pdu->qam_mod_order;
|
||||
const uint8_t mcs = pusch_pdu->mcs_index;
|
||||
const uint8_t n_layers = pusch_pdu->nrOfLayers;
|
||||
// ------------------------------------------------------------------
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
|
||||
|
||||
harq_process->TBS = pusch_pdu->pusch_data.tb_size;
|
||||
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id];
|
||||
|
||||
t_nrLDPC_dec_params decParams = {.check_crc = check_crc};
|
||||
decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
|
||||
const uint32_t A = (harq_process->TBS) << 3;
|
||||
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti);
|
||||
if (stats) {
|
||||
stats->frame = frame;
|
||||
stats->ulsch_stats.round_trials[harq_process->round]++;
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
stats->ulsch_stats.power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]);
|
||||
stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]);
|
||||
TB_parameters->G = G[pusch_id];
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n");
|
||||
return -1;
|
||||
}
|
||||
if (!harq_process->harq_to_be_cleared) {
|
||||
stats->ulsch_stats.current_Qm = Qm;
|
||||
stats->ulsch_stats.current_RI = n_layers;
|
||||
stats->ulsch_stats.total_bytes_tx += harq_process->TBS;
|
||||
|
||||
// The harq_pid is not unique among the active HARQ processes in the instance so we use ULSCH_id instead
|
||||
TB_parameters->harq_unique_pid = ULSCH_id;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
TB_parameters->nb_rb = pusch_pdu->rb_size;
|
||||
TB_parameters->Qm = pusch_pdu->qam_mod_order;
|
||||
TB_parameters->mcs = pusch_pdu->mcs_index;
|
||||
TB_parameters->nb_layers = pusch_pdu->nrOfLayers;
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
TB_parameters->processedSegments = &harq_process->processedSegments;
|
||||
harq_process->TBS = pusch_pdu->pusch_data.tb_size;
|
||||
|
||||
TB_parameters->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
|
||||
TB_parameters->A = (harq_process->TBS) << 3;
|
||||
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti);
|
||||
if (stats) {
|
||||
stats->frame = frame;
|
||||
stats->ulsch_stats.round_trials[harq_process->round]++;
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
stats->ulsch_stats.power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]);
|
||||
stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]);
|
||||
}
|
||||
if (!harq_process->harq_to_be_cleared) {
|
||||
stats->ulsch_stats.current_Qm = TB_parameters->Qm;
|
||||
stats->ulsch_stats.current_RI = TB_parameters->nb_layers;
|
||||
stats->ulsch_stats.total_bytes_tx += harq_process->TBS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(PHY,
|
||||
"ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n",
|
||||
harq_pid,
|
||||
ulsch->rnti,
|
||||
A,
|
||||
G,
|
||||
mcs,
|
||||
n_layers,
|
||||
nb_rb,
|
||||
Qm,
|
||||
pusch_pdu->target_code_rate / 10240.0f,
|
||||
pusch_pdu->pusch_data.rv_index,
|
||||
harq_process->round,
|
||||
harq_process->harq_to_be_cleared);
|
||||
|
||||
// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F)
|
||||
nr_segmentation(NULL,
|
||||
NULL,
|
||||
lenWithCrc(1, A), // size in case of 1 segment
|
||||
&harq_process->C,
|
||||
&harq_process->K,
|
||||
&harq_process->Z, // [hna] Z is Zc
|
||||
&harq_process->F,
|
||||
decParams.BG);
|
||||
|
||||
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * n_layers; // number of segments to be allocated
|
||||
if (harq_process->C > a_segments) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A);
|
||||
return(-1);
|
||||
}
|
||||
if (nb_rb != 273) {
|
||||
a_segments = a_segments*nb_rb;
|
||||
a_segments = a_segments/273 +1;
|
||||
}
|
||||
if (harq_process->C > a_segments) {
|
||||
LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t harq_pid = ulsch->harq_pid;
|
||||
LOG_D(PHY,
|
||||
"ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n",
|
||||
harq_pid,
|
||||
ulsch->rnti,
|
||||
TB_parameters->A,
|
||||
TB_parameters->G,
|
||||
TB_parameters->mcs,
|
||||
TB_parameters->nb_layers,
|
||||
TB_parameters->nb_rb,
|
||||
TB_parameters->Qm,
|
||||
pusch_pdu->target_code_rate / 10240.0f,
|
||||
pusch_pdu->pusch_data.rv_index,
|
||||
harq_process->round,
|
||||
harq_process->harq_to_be_cleared);
|
||||
|
||||
// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F)
|
||||
nr_segmentation(NULL,
|
||||
NULL,
|
||||
lenWithCrc(1, TB_parameters->A), // size in case of 1 segment
|
||||
&TB_parameters->C,
|
||||
&TB_parameters->K,
|
||||
&TB_parameters->Z, // [hna] Z is Zc
|
||||
&TB_parameters->F,
|
||||
TB_parameters->BG);
|
||||
harq_process->C = TB_parameters->C;
|
||||
harq_process->K = TB_parameters->K;
|
||||
harq_process->Z = TB_parameters->Z;
|
||||
harq_process->F = TB_parameters->F;
|
||||
|
||||
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers; // number of segments to be allocated
|
||||
if (TB_parameters->C > a_segments) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A);
|
||||
return(-1);
|
||||
}
|
||||
if (TB_parameters->nb_rb != 273) {
|
||||
a_segments = a_segments*TB_parameters->nb_rb;
|
||||
a_segments = a_segments/273 +1;
|
||||
}
|
||||
if (TB_parameters->C > a_segments) {
|
||||
LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments);
|
||||
return -1;
|
||||
}
|
||||
max_num_segments = max(max_num_segments, TB_parameters->C);
|
||||
|
||||
#ifdef DEBUG_ULSCH_DECODING
|
||||
printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z);
|
||||
if (!frame % 100)
|
||||
printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z);
|
||||
printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
|
||||
printf("ulsch decoding nr segmentation Z %d\n", TB_parameters->Z);
|
||||
if (!frame % 100)
|
||||
printf("K %d C %d Z %d \n",
|
||||
TB_parameters->K,
|
||||
TB_parameters->C,
|
||||
TB_parameters->Z);
|
||||
printf("Segmentation: C %d, K %d\n",
|
||||
TB_parameters->C,
|
||||
TB_parameters->K);
|
||||
#endif
|
||||
|
||||
TB_parameters->max_ldpc_iterations = ulsch->max_ldpc_iterations;
|
||||
TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index;
|
||||
TB_parameters->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
TB_parameters->abort_decode = &harq_process->abort_decode;
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
|
||||
decParams.Z = harq_process->Z;
|
||||
decParams.numMaxIter = ulsch->max_ldpc_iterations;
|
||||
decParams.Qm = Qm;
|
||||
decParams.rv = pusch_pdu->pusch_data.rv_index;
|
||||
decParams.outMode = 0;
|
||||
decParams.setCombIn = !harq_process->harq_to_be_cleared;
|
||||
if (harq_process->harq_to_be_cleared) {
|
||||
for (int r = 0; r < harq_process->C; r++)
|
||||
harq_process->d_to_be_cleared[r] = true;
|
||||
harq_process->harq_to_be_cleared = false;
|
||||
}
|
||||
|
||||
if (phy_vars_gNB->ldpc_offload_flag)
|
||||
return decode_offload(phy_vars_gNB, ULSCH_id, ulsch_llr, pusch_pdu, &decParams, harq_pid, G);
|
||||
harq_process->processedSegments = 0;
|
||||
uint32_t offset = 0, r_offset = 0;
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
for (int r = 0; r < harq_process->C; r++) {
|
||||
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
|
||||
nrLDPC_segment_decoding_parameters_t segments[nb_pusch][max_num_segments];
|
||||
memset(segments, 0, sizeof(segments));
|
||||
|
||||
ldpcDecode_t *rdata = &((ldpcDecode_t *)t_info->buf)[t_info->len];
|
||||
DevAssert(t_info->len < t_info->cap);
|
||||
rdata->ans = &t_info->ans[t_info->len];
|
||||
t_info->len += 1;
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
short *ulsch_llr = phy_vars_gNB->pusch_vars[ULSCH_id].llr;
|
||||
|
||||
decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index,
|
||||
E,
|
||||
decParams.BG,
|
||||
decParams.Z,
|
||||
&harq_process->llrLen,
|
||||
harq_process->round);
|
||||
rdata->gNB = phy_vars_gNB;
|
||||
rdata->ulsch_harq = harq_process;
|
||||
rdata->decoderParms = decParams;
|
||||
rdata->ulsch_llr = ulsch_llr;
|
||||
rdata->Kc = decParams.BG == 2 ? 52 : 68;
|
||||
rdata->harq_pid = harq_pid;
|
||||
rdata->segment_r = r;
|
||||
rdata->nbSegments = harq_process->C;
|
||||
rdata->E = E;
|
||||
rdata->A = A;
|
||||
rdata->Qm = Qm;
|
||||
rdata->r_offset = r_offset;
|
||||
rdata->Kr_bytes = harq_process->K >> 3;
|
||||
rdata->rv_index = pusch_pdu->pusch_data.rv_index;
|
||||
rdata->offset = offset;
|
||||
rdata->ulsch = ulsch;
|
||||
rdata->ulsch_id = ULSCH_id;
|
||||
rdata->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
|
||||
if (!ulsch_llr) {
|
||||
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
task_t t = {.func = &nr_processULSegment, .args = rdata};
|
||||
pushTpool(&phy_vars_gNB->threadPool, t);
|
||||
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id];
|
||||
TB_parameters->segments = segments[pusch_id];
|
||||
|
||||
uint32_t r_offset = 0;
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
|
||||
segment_parameters->E = nr_get_E(TB_parameters->G,
|
||||
TB_parameters->C,
|
||||
TB_parameters->Qm,
|
||||
TB_parameters->nb_layers,
|
||||
r);
|
||||
segment_parameters->R = nr_get_R_ldpc_decoder(TB_parameters->rv_index,
|
||||
segment_parameters->E,
|
||||
TB_parameters->BG,
|
||||
TB_parameters->Z,
|
||||
&harq_process->llrLen,
|
||||
harq_process->round);
|
||||
segment_parameters->llr = ulsch_llr + r_offset;
|
||||
segment_parameters->d = harq_process->d[r];
|
||||
segment_parameters->d_to_be_cleared = &harq_process->d_to_be_cleared[r];
|
||||
segment_parameters->c = harq_process->c[r];
|
||||
segment_parameters->decodeSuccess = false;
|
||||
|
||||
reset_meas(&segment_parameters->ts_deinterleave);
|
||||
reset_meas(&segment_parameters->ts_rate_unmatch);
|
||||
reset_meas(&segment_parameters->ts_ldpc_decode);
|
||||
|
||||
r_offset += segment_parameters->E;
|
||||
}
|
||||
if (harq_process->harq_to_be_cleared) {
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
harq_process->d_to_be_cleared[r] = true;
|
||||
}
|
||||
harq_process->harq_to_be_cleared = false;
|
||||
}
|
||||
|
||||
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
|
||||
r_offset += E;
|
||||
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
}
|
||||
return harq_process->C;
|
||||
|
||||
int ret_decoder = phy_vars_gNB->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
|
||||
|
||||
// post decode
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t TB_parameters = TBs[pusch_id];
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (int r = 0; r < TB_parameters.C; r++) {
|
||||
nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters = TB_parameters.segments[r];
|
||||
// Copy c to b in case of decoding success
|
||||
if (nrLDPC_segment_decoding_parameters.decodeSuccess) {
|
||||
memcpy(harq_process->b + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
} else {
|
||||
LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C);
|
||||
LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
|
||||
}
|
||||
offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
return ret_decoder;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
|
||||
#include "PHY/impl_defs_top.h"
|
||||
#include "PHY/defs_common.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
|
||||
#include "executables/rt_profiling.h"
|
||||
@@ -494,9 +495,10 @@ typedef struct PHY_VARS_gNB_s {
|
||||
/// OFDM symbol offset divisor for UL
|
||||
uint32_t ofdm_offset_divisor;
|
||||
|
||||
int ldpc_offload_flag;
|
||||
|
||||
/// NR LDPC coding related
|
||||
nrLDPC_coding_interface_t nrLDPC_coding_interface;
|
||||
int max_ldpc_iterations;
|
||||
|
||||
/// indicate the channel estimation technique in time domain
|
||||
int chest_time;
|
||||
/// indicate the channel estimation technique in freq domain
|
||||
|
||||
@@ -305,187 +305,144 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 0);
|
||||
}
|
||||
|
||||
static void nr_postDecode(PHY_VARS_gNB *gNB, ldpcDecode_t *rdata)
|
||||
static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, bool *ulsch_to_decode)
|
||||
{
|
||||
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_process->ulsch_pdu;
|
||||
bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
|
||||
ulsch_harq->processedSegments++;
|
||||
LOG_D(PHY,
|
||||
"processing result of segment: %d, processed %d/%d, %s\n",
|
||||
rdata->segment_r,
|
||||
ulsch_harq->processedSegments,
|
||||
rdata->nbSegments,
|
||||
decodeSuccess ? "Decoded Successfully" : "Decoding Unsuccessful");
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
|
||||
if (decodeSuccess) {
|
||||
memcpy(ulsch_harq->b + rdata->offset, ulsch_harq->c[r], rdata->Kr_bytes - (ulsch_harq->F >> 3) - ((ulsch_harq->C > 1) ? 3 : 0));
|
||||
|
||||
} else {
|
||||
LOG_D(PHY, "ULSCH %d in error\n", rdata->ulsch_id);
|
||||
int nb_pusch = 0;
|
||||
for (uint8_t ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
|
||||
if (ulsch_to_decode[ULSCH_id]) {
|
||||
nb_pusch++;
|
||||
}
|
||||
}
|
||||
|
||||
//int dumpsig=0;
|
||||
// if all segments are done
|
||||
if (ulsch_harq->processedSegments == ulsch_harq->C) {
|
||||
// When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the
|
||||
// CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block
|
||||
bool crc_valid = true;
|
||||
if (ulsch_harq->C > 1) {
|
||||
crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, rdata->A), crcType(1, rdata->A));
|
||||
if (nb_pusch == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ULSCH_ids[nb_pusch];
|
||||
uint32_t G[nb_pusch];
|
||||
int pusch_id = 0;
|
||||
for (uint8_t ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
|
||||
|
||||
if (ulsch_to_decode[ULSCH_id]) {
|
||||
|
||||
ULSCH_ids[pusch_id] = ULSCH_id;
|
||||
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
|
||||
|
||||
uint16_t nb_re_dmrs;
|
||||
uint16_t start_symbol = pusch_pdu->start_symbol_index;
|
||||
uint16_t number_symbols = pusch_pdu->nr_of_symbols;
|
||||
|
||||
uint8_t number_dmrs_symbols = 0;
|
||||
for (int l = start_symbol; l < start_symbol + number_symbols; l++)
|
||||
number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01;
|
||||
|
||||
if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1)
|
||||
nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
else
|
||||
nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
|
||||
G[pusch_id] = nr_get_G(pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
gNB->ulsch[ULSCH_id].unav_res,
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
AssertFatal(G[pusch_id]>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
|
||||
pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
|
||||
pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
pusch_pdu->ul_dmrs_symb_pos,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
pusch_id++;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//--------------------- ULSCH decoding ---------------------
|
||||
//----------------------------------------------------------
|
||||
|
||||
int ret_nr_ulsch_decoding =
|
||||
nr_ulsch_decoding(gNB, frame_parms, frame_rx, slot_rx, G, ULSCH_ids, nb_pusch);
|
||||
|
||||
// CRC check per uplink shared channel
|
||||
for (pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &ulsch_harq->ulsch_pdu;
|
||||
|
||||
bool crc_valid = false;
|
||||
|
||||
// if all segments are done
|
||||
if (ulsch_harq->processedSegments == ulsch_harq->C) {
|
||||
if (ulsch_harq->C > 1) {
|
||||
crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, (ulsch_harq->TBS) << 3), crcType(1, (ulsch_harq->TBS) << 3));
|
||||
} else {
|
||||
// When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the
|
||||
// CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block
|
||||
crc_valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !gNB->pusch_vars[rdata->ulsch_id].DTX) {
|
||||
if (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !pusch->DTX) {
|
||||
LOG_D(NR_PHY,
|
||||
"[gNB %d] ULSCH %d: Setting ACK for SFN/SF %d.%d (rnti %x, pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
|
||||
"(all seg) %d)\n",
|
||||
gNB->Mod_id,
|
||||
rdata->ulsch_id,
|
||||
ULSCH_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
ulsch->rnti,
|
||||
rdata->harq_pid,
|
||||
ulsch->harq_pid,
|
||||
pusch_pdu->pusch_data.new_data_indicator,
|
||||
ulsch->active,
|
||||
ulsch_harq->round,
|
||||
ulsch_harq->TBS,
|
||||
rdata->decodeIterations);
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 0, 0);
|
||||
ulsch->max_ldpc_iterations);
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 0, 0);
|
||||
LOG_D(PHY, "ULSCH received ok \n");
|
||||
ulsch->active = false;
|
||||
ulsch_harq->round = 0;
|
||||
//dumpsig=1;
|
||||
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
|
||||
} 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, "
|
||||
"TBS %d) r %d\n",
|
||||
"TBS %d)\n",
|
||||
gNB->Mod_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
rdata->harq_pid,
|
||||
ulsch->harq_pid,
|
||||
pusch_pdu->pusch_data.new_data_indicator,
|
||||
ulsch->active,
|
||||
ulsch_harq->round,
|
||||
ulsch_harq->ulsch_pdu.pusch_data.rv_index,
|
||||
ulsch_harq->ulsch_pdu.rb_start,
|
||||
ulsch_harq->ulsch_pdu.rb_size,
|
||||
ulsch_harq->TBS,
|
||||
r);
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0);
|
||||
ulsch_harq->TBS);
|
||||
nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0);
|
||||
ulsch->handled = 1;
|
||||
LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
|
||||
// dumpsig=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 = rdata->decodeIterations;
|
||||
/*
|
||||
if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) {
|
||||
int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0;
|
||||
|
||||
LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][0][(ulsch_harq->slot%RU_RX_SLOT_DEPTH)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
|
||||
LOG_M("rxsigF0_ext.m","rxsF0_ext",
|
||||
&gNB->pusch_vars[0].rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF0.m","chF0",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
|
||||
LOG_M("rxsigF0_comp.m","rxsF0_comp",
|
||||
&gNB->pusch_vars[0].rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_llr.m","rxsF0_llr",
|
||||
&gNB->pusch_vars[0].llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size *
|
||||
ulsch_harq->ulsch_pdu.qam_mod_order,1,0); if (gNB->frame_parms.nb_antennas_rx > 1) {
|
||||
|
||||
LOG_M("rxsigF1_ext.m","rxsF0_ext",
|
||||
&gNB->pusch_vars[0].rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF1.m","chF1",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1);
|
||||
LOG_M("rxsigF1_comp.m","rxsF1_comp",
|
||||
&gNB->pusch_vars[0].rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size)),1,1);
|
||||
}
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
*/
|
||||
ulsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
|
||||
}
|
||||
|
||||
return ret_nr_ulsch_decoding;
|
||||
}
|
||||
|
||||
static int nr_ulsch_procedures(PHY_VARS_gNB *gNB,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
int ULSCH_id,
|
||||
uint8_t harq_pid,
|
||||
thread_info_tm_t *t_info)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
|
||||
|
||||
uint16_t nb_re_dmrs;
|
||||
uint16_t start_symbol = pusch_pdu->start_symbol_index;
|
||||
uint16_t number_symbols = pusch_pdu->nr_of_symbols;
|
||||
|
||||
uint8_t number_dmrs_symbols = 0;
|
||||
for (int l = start_symbol; l < start_symbol + number_symbols; l++)
|
||||
number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01;
|
||||
|
||||
if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1)
|
||||
nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
else
|
||||
nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
|
||||
uint32_t G = nr_get_G(pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
gNB->ulsch[ULSCH_id].unav_res,
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
|
||||
AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
|
||||
pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
|
||||
pusch_pdu->rb_size,
|
||||
number_symbols,
|
||||
nb_re_dmrs,
|
||||
pusch_pdu->ul_dmrs_symb_pos,
|
||||
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
|
||||
pusch_pdu->qam_mod_order,
|
||||
pusch_pdu->nrOfLayers);
|
||||
|
||||
//----------------------------------------------------------
|
||||
//--------------------- ULSCH decoding ---------------------
|
||||
//----------------------------------------------------------
|
||||
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
|
||||
* (valid for unitary physical simulators). ULSCH processing lopp is then executed
|
||||
* only once, which ensures exactly one start and stop of the ULSCH decoding time
|
||||
* measurement per processed TB.*/
|
||||
if (gNB->max_nb_pusch == 1)
|
||||
start_meas(&gNB->ulsch_decoding_stats);
|
||||
|
||||
int const nbDecode = nr_ulsch_decoding(gNB,
|
||||
ULSCH_id,
|
||||
gNB->pusch_vars[ULSCH_id].llr,
|
||||
frame_parms,
|
||||
pusch_pdu,
|
||||
frame_rx,
|
||||
slot_rx,
|
||||
harq_pid,
|
||||
G,
|
||||
t_info);
|
||||
return nbDecode;
|
||||
}
|
||||
|
||||
|
||||
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag)
|
||||
{
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
@@ -840,12 +797,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
}
|
||||
}
|
||||
|
||||
ldpcDecode_t arr[64];
|
||||
task_ans_t ans[64] = {0};
|
||||
thread_info_tm_t t_info = {.buf = (uint8_t *)arr, .len = 0, .cap = 64, .ans = ans};
|
||||
|
||||
// int64_t const t0 = time_now_ns();
|
||||
int totalDecode = 0;
|
||||
bool ulsch_to_decode[gNB->max_nb_pusch];
|
||||
bzero((void *)ulsch_to_decode, sizeof(ulsch_to_decode));
|
||||
for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
|
||||
@@ -937,25 +890,26 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
|
||||
pusch_vars->DTX = 0;
|
||||
}
|
||||
ulsch_to_decode[ULSCH_id] = true;
|
||||
stop_meas(&gNB->rx_pusch_stats);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 0);
|
||||
// LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1);
|
||||
// LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1);
|
||||
int const tasks_added = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, &t_info);
|
||||
if (tasks_added > 0)
|
||||
totalDecode += tasks_added;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
DevAssert(totalDecode == t_info.len);
|
||||
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
|
||||
* (valid for unitary physical simulators). ULSCH processing lopp is then executed
|
||||
* only once, which ensures exactly one start and stop of the ULSCH decoding time
|
||||
* measurement per processed TB.*/
|
||||
if (gNB->max_nb_pusch == 1)
|
||||
start_meas(&gNB->ulsch_decoding_stats);
|
||||
|
||||
join_task_ans(t_info.ans, t_info.len);
|
||||
for (int i = 0; i < t_info.len; ++i) {
|
||||
nr_postDecode(gNB, &arr[i]);
|
||||
int const ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_to_decode);
|
||||
if (ret_nr_ulsch_procedures != 0) {
|
||||
LOG_E(PHY,"Error in nr_ulsch_procedures, returned %d\n",ret_nr_ulsch_procedures);
|
||||
}
|
||||
|
||||
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
|
||||
* (valid for unitary physical simulators). ULSCH processing loop is then executed
|
||||
* only once, which ensures exactly one start and stop of the ULSCH decoding time
|
||||
|
||||
Reference in New Issue
Block a user