Commit 00e1ad12 authored by Romain Beurdouche's avatar Romain Beurdouche

feat(nrLDPC_coding_interface): Use reworked interface in gNB

parent 5f22b056
...@@ -403,7 +403,6 @@ void init_eNB_afterRU(void) { ...@@ -403,7 +403,6 @@ void init_eNB_afterRU(void) {
for (inst=0; inst<RC.nb_nr_inst; inst++) { for (inst=0; inst<RC.nb_nr_inst; inst++) {
gNB = RC.gNB[inst]; gNB = RC.gNB[inst];
gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
phy_init_nr_gNB(gNB); phy_init_nr_gNB(gNB);
......
...@@ -142,7 +142,6 @@ extern "C" ...@@ -142,7 +142,6 @@ extern "C"
#define EMULATE_L1 softmodem_params.emulate_l1 #define EMULATE_L1 softmodem_params.emulate_l1
#define CONTINUOUS_TX softmodem_params.continuous_tx #define CONTINUOUS_TX softmodem_params.continuous_tx
#define SYNC_REF softmodem_params.sync_ref #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"; #define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
...@@ -321,7 +320,6 @@ typedef struct { ...@@ -321,7 +320,6 @@ typedef struct {
int continuous_tx; int continuous_tx;
uint32_t sync_ref; uint32_t sync_ref;
int no_itti; int no_itti;
int ldpc_offload_flag;
int threequarter_fs; int threequarter_fs;
} softmodem_params_t; } softmodem_params_t;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "PHY/defs_gNB.h" #include "PHY/defs_gNB.h"
#include "PHY/NR_REFSIG/nr_refsig.h" #include "PHY/NR_REFSIG/nr_refsig.h"
#include "PHY/INIT/nr_phy_init.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/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
...@@ -40,6 +41,7 @@ ...@@ -40,6 +41,7 @@
#include "PHY/NR_REFSIG/nr_refsig.h" #include "PHY/NR_REFSIG/nr_refsig.h"
#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/fapi_nr_l1.h"
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
#include <string.h>
int l1_north_init_gNB() int l1_north_init_gNB()
{ {
...@@ -96,9 +98,6 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame) ...@@ -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) void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
{ {
// shortcuts // shortcuts
...@@ -134,15 +133,11 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) ...@@ -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 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); 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; 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); init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
......
...@@ -65,25 +65,17 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) ...@@ -65,25 +65,17 @@ 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_interleaving_stats=&gNB->dlsch_interleaving_stats;
time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_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++) { for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB;
const int dmrs_Type = rel15->dmrsConfigType;
const int nb_re_dmrs = rel15->numDmrsCdmGrpsNoData * (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4);
const int amp_dmrs = (int)((double)amp * sqrt(rel15->numDmrsCdmGrpsNoData)); // 3GPP TS 38.214 Section 4.1: Table 4.1-1
LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n", LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n",
rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize); rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize);
const int n_dmrs = (rel15->BWPStart + rel15->rbStart + rel15->rbSize) * nb_re_dmrs;
const int dmrs_symbol_map = rel15->dlDmrsSymbPos; // single DMRS: 010000100 Double DMRS 110001100
const int xOverhead = 0;
const int nb_re =
(12 * rel15->NrOfSymbols - nb_re_dmrs * get_num_dmrs(rel15->dlDmrsSymbPos) - xOverhead) * rel15->rbSize * rel15->nrOfLayers;
const int Qm = rel15->qamModOrder[0]; const int Qm = rel15->qamModOrder[0];
const int encoded_length = nb_re * Qm;
/* PTRS */ /* PTRS */
uint16_t dlPtrsSymPos = 0; uint16_t dlPtrsSymPos = 0;
...@@ -102,14 +94,25 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) ...@@ -102,14 +94,25 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
/// CRC, coding, interleaving and rate matching /// CRC, coding, interleaving and rate matching
AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); 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);
/* 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, if (nr_dlsch_encoding(gNB,
msgTx,
frame, frame,
slot, slot,
harq,
frame_parms, frame_parms,
output, output,
tinput, tinput,
...@@ -118,27 +121,64 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) ...@@ -118,27 +121,64 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
toutput, toutput,
dlsch_rate_matching_stats, dlsch_rate_matching_stats,
dlsch_interleaving_stats, dlsch_interleaving_stats,
dlsch_segmentation_stats) == -1) dlsch_segmentation_stats) == -1) {
return; return;
}
stop_meas(dlsch_encoding_stats); 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];
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB;
const int dmrs_Type = rel15->dmrsConfigType;
const int nb_re_dmrs = rel15->numDmrsCdmGrpsNoData * (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4);
const int amp_dmrs = (int)((double)amp * sqrt(rel15->numDmrsCdmGrpsNoData)); // 3GPP TS 38.214 Section 4.1: Table 4.1-1
LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n",
rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize);
const int n_dmrs = (rel15->BWPStart + rel15->rbStart + rel15->rbSize) * nb_re_dmrs;
const int dmrs_symbol_map = rel15->dlDmrsSymbPos; // single DMRS: 010000100 Double DMRS 110001100
const int xOverhead = 0;
const int nb_re =
(12 * rel15->NrOfSymbols - nb_re_dmrs * get_num_dmrs(rel15->dlDmrsSymbPos) - xOverhead) * rel15->rbSize * rel15->nrOfLayers;
const int Qm = rel15->qamModOrder[0];
const int encoded_length = nb_re * Qm;
/* 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;
#ifdef DEBUG_DLSCH #ifdef DEBUG_DLSCH
printf("PDSCH encoding:\nPayload:\n"); printf("PDSCH encoding:\nPayload:\n");
for (int i=0; i<harq->B>>7; i++) { for (int i = 0; i < (harq->B>>3); i += 16) {
for (int j=0; j<16; j++) for (int j=0; j < 16; j++)
printf("0x%02x\t", harq->pdu[(i<<4)+j]); printf("0x%02x\t", harq->pdu[i + j]);
printf("\n"); printf("\n");
} }
printf("\nEncoded payload:\n"); printf("\nEncoded payload:\n");
for (int i=0; i<encoded_length>>3; i++) { for (int i = 0; i < encoded_length; i += 8) {
for (int j=0; j<8; j++) for (int j = 0; j < 8; j++)
printf("%d", output[(i<<3)+j]); printf("%d", output[offset_output + i + j]);
printf("\t"); printf("\t");
} }
printf("\n"); printf("\n");
#endif #endif
if (IS_SOFTMODEM_DLSIM) 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]; c16_t mod_symbs[rel15->NrOfCodewords][encoded_length];
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) { for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
...@@ -147,7 +187,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) ...@@ -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 uint32_t scrambled_output[(encoded_length>>5)+4]; // modulator acces by 4 bytes in some cases
memset(scrambled_output, 0, sizeof(scrambled_output)); 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(); 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 #ifdef DEBUG_DLSCH
printf("PDSCH scrambling:\n"); printf("PDSCH scrambling:\n");
...@@ -176,6 +216,12 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) ...@@ -176,6 +216,12 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
} }
/// Resource mapping /// 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 // Non interleaved VRB to PRB mapping
uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart+rel15->BWPStart)*NR_NB_SC_PER_RB; 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) if (start_sc >= frame_parms->ofdm_symbol_size)
......
...@@ -44,11 +44,11 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, ...@@ -44,11 +44,11 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx,
int slot); int slot);
int nr_dlsch_encoding(PHY_VARS_gNB *gNB, int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
processingData_L1tx_t *msgTx,
int frame, int frame,
uint8_t slot, uint8_t slot,
NR_DL_gNB_HARQ_t *harq, NR_DL_FRAME_PARMS *frame_parms,
NR_DL_FRAME_PARMS* frame_parms, unsigned char *output,
unsigned char * output,
time_stats_t *tinput, time_stats_t *tinput,
time_stats_t *tprep, time_stats_t *tprep,
time_stats_t *tparity, time_stats_t *tparity,
......
...@@ -19,21 +19,15 @@ ...@@ -19,21 +19,15 @@
* contact@openairinterface.org * 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 * \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/defs_gNB.h"
#include "PHY/CODING/coding_extern.h" #include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/coding_defs.h" #include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/lte_interleaver_inline.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/CODING/nrLDPC_extern.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_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) ...@@ -117,130 +111,10 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB)
return(dlsch); 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, int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
processingData_L1tx_t *msgTx,
int frame, int frame,
uint8_t slot, uint8_t slot,
NR_DL_gNB_HARQ_t *harq,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
unsigned char *output, unsigned char *output,
time_stats_t *tinput, time_stats_t *tinput,
...@@ -251,12 +125,32 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, ...@@ -251,12 +125,32 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
time_stats_t *dlsch_interleaving_stats, time_stats_t *dlsch_interleaving_stats,
time_stats_t *dlsch_segmentation_stats) time_stats_t *dlsch_segmentation_stats)
{ {
encoder_implemparams_t impp;
impp.output=output; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
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
};
int num_segments = 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;
unsigned int crc=1; unsigned int crc=1;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; 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; uint32_t A = rel15->TBSize[0]<<3;
unsigned char *a=harq->pdu; unsigned char *a=harq->pdu;
if (rel15->rnti != SI_RNTI) { if (rel15->rnti != SI_RNTI) {
...@@ -321,75 +215,105 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, ...@@ -321,75 +215,105 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
} }
impp.BG = rel15->maintenance_parms_v3.ldpcBaseGraph; 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); 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); 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); stop_meas(dlsch_segmentation_stats);
if (impp.n_segments>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers) { 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", impp.n_segments, B); LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B);
return(-1); return(-1);
} }
for (int r=0; r<impp.n_segments; r++) { num_segments += TB_parameters->C;
//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]);
} }
LOG_D(PHY,"\n"); nrLDPC_segment_encoding_parameters_t segments[num_segments];
#endif memset(segments, 0, sizeof(segments));
//ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0); size_t segments_offset = 0;
//ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL); 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];
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];
int nb_re_dmrs = int nb_re_dmrs =
(rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData); (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData);
impp.G = nr_get_G(rel15->rbSize, TB_parameters->G = nr_get_G(rel15->rbSize,
rel15->NrOfSymbols, rel15->NrOfSymbols,
nb_re_dmrs, nb_re_dmrs,
get_num_dmrs(rel15->dlDmrsSymbPos), get_num_dmrs(rel15->dlDmrsSymbPos),
harq->unav_res, harq->unav_res,
rel15->qamModOrder[0], rel15->qamModOrder[0],
rel15->nrOfLayers); 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));
encoder_implemparams_t arr[n_seg]; TB_parameters->tbslbrm = rel15->maintenance_parms_v3.tbSizeLbrmBytes;
task_ans_t ans[n_seg];
memset(ans, 0, n_seg * sizeof(task_ans_t));
for (int j = 0; j < n_seg; j++) { TB_parameters->segments = &segments[segments_offset];
encoder_implemparams_t *perJobImpp = &arr[j];
*perJobImpp = impp; size_t r_offset = 0;
perJobImpp->macro_num = j; for (int r = 0; r < TB_parameters->C; r++) {
perJobImpp->ans = &ans[j]; 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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
return 0; return 0;
} }
...@@ -42,28 +42,23 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL); ...@@ -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); 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 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 frame_parms, Pointer to frame descriptor structure
@param nb_symb_sch, number of symbols used in the uplink shared channel @param frame, current received frame
@param nb_re_dmrs, number of DMRS resource elements in one RB
@param nr_tti_rx, current received TTI @param nr_tti_rx, current received TTI
@param harq_pid, harq process id @param G
@param is_crnti @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, int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint8_t UE_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame, uint32_t frame,
uint8_t nr_tti_rx, uint8_t nr_tti_rx,
uint8_t harq_pid, uint32_t *G,
uint32_t G, uint8_t *ULSCH_ids,
thread_info_tm_t *t_info); int nb_pusch);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 /*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
@param llr, Pointer to llr bits @param llr, Pointer to llr bits
......
...@@ -19,15 +19,8 @@ ...@@ -19,15 +19,8 @@
* contact@openairinterface.org * 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 * \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 @@ ...@@ -36,6 +29,7 @@
#include "PHY/CODING/coding_extern.h" #include "PHY/CODING/coding_extern.h"
#include "PHY/CODING/coding_defs.h" #include "PHY/CODING/coding_defs.h"
#include "PHY/CODING/lte_interleaver_inline.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/CODING/nrLDPC_extern.h"
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h"
...@@ -50,10 +44,6 @@ ...@@ -50,10 +44,6 @@
//#define DEBUG_ULSCH_DECODING //#define DEBUG_ULSCH_DECODING
//#define gNB_DEBUG_TRACE //#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 OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
//#define DEBUG_CRC //#define DEBUG_CRC
#ifdef DEBUG_CRC #ifdef DEBUG_CRC
...@@ -123,244 +113,60 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) ...@@ -123,244 +113,60 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL)
return(ulsch); 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, int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
uint8_t ULSCH_id,
short *ulsch_llr,
NR_DL_FRAME_PARMS *frame_parms, NR_DL_FRAME_PARMS *frame_parms,
nfapi_nr_pusch_pdu_t *pusch_pdu,
uint32_t frame, uint32_t frame,
uint8_t nr_tti_rx, uint8_t nr_tti_rx,
uint8_t harq_pid, uint32_t *G,
uint32_t G, uint8_t *ULSCH_ids,
thread_info_tm_t *t_info) 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); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 1);
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
};
int max_num_segments = 0;
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_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id];
TB_parameters->G = G[pusch_id];
if (!harq_process) { if (!harq_process) {
LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n"); LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n");
return -1; return -1;
} }
// 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;
// ------------------------------------------------------------------ // ------------------------------------------------------------------
const uint16_t nb_rb = pusch_pdu->rb_size; TB_parameters->nb_rb = pusch_pdu->rb_size;
const uint8_t Qm = pusch_pdu->qam_mod_order; TB_parameters->Qm = pusch_pdu->qam_mod_order;
const uint8_t mcs = pusch_pdu->mcs_index; TB_parameters->mcs = pusch_pdu->mcs_index;
const uint8_t n_layers = pusch_pdu->nrOfLayers; TB_parameters->nb_layers = pusch_pdu->nrOfLayers;
// ------------------------------------------------------------------ // ------------------------------------------------------------------
TB_parameters->processedSegments = &harq_process->processedSegments;
harq_process->TBS = pusch_pdu->pusch_data.tb_size; harq_process->TBS = pusch_pdu->pusch_data.tb_size;
t_nrLDPC_dec_params decParams = {.check_crc = check_crc}; TB_parameters->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; TB_parameters->A = (harq_process->TBS) << 3;
const uint32_t A = (harq_process->TBS) << 3;
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti);
if (stats) { if (stats) {
stats->frame = frame; stats->frame = frame;
...@@ -370,22 +176,23 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -370,22 +176,23 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]); stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]);
} }
if (!harq_process->harq_to_be_cleared) { if (!harq_process->harq_to_be_cleared) {
stats->ulsch_stats.current_Qm = Qm; stats->ulsch_stats.current_Qm = TB_parameters->Qm;
stats->ulsch_stats.current_RI = n_layers; stats->ulsch_stats.current_RI = TB_parameters->nb_layers;
stats->ulsch_stats.total_bytes_tx += harq_process->TBS; stats->ulsch_stats.total_bytes_tx += harq_process->TBS;
} }
} }
uint8_t harq_pid = ulsch->harq_pid;
LOG_D(PHY, 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", "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, harq_pid,
ulsch->rnti, ulsch->rnti,
A, TB_parameters->A,
G, TB_parameters->G,
mcs, TB_parameters->mcs,
n_layers, TB_parameters->nb_layers,
nb_rb, TB_parameters->nb_rb,
Qm, TB_parameters->Qm,
pusch_pdu->target_code_rate / 10240.0f, pusch_pdu->target_code_rate / 10240.0f,
pusch_pdu->pusch_data.rv_index, pusch_pdu->pusch_data.rv_index,
harq_process->round, harq_process->round,
...@@ -394,90 +201,127 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, ...@@ -394,90 +201,127 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F) // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (C, K, Z, F)
nr_segmentation(NULL, nr_segmentation(NULL,
NULL, NULL,
lenWithCrc(1, A), // size in case of 1 segment lenWithCrc(1, TB_parameters->A), // size in case of 1 segment
&harq_process->C, &TB_parameters->C,
&harq_process->K, &TB_parameters->K,
&harq_process->Z, // [hna] Z is Zc &TB_parameters->Z, // [hna] Z is Zc
&harq_process->F, &TB_parameters->F,
decParams.BG); TB_parameters->BG);
harq_process->C = TB_parameters->C;
uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * n_layers; // number of segments to be allocated harq_process->K = TB_parameters->K;
if (harq_process->C > a_segments) { harq_process->Z = TB_parameters->Z;
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A); 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); return(-1);
} }
if (nb_rb != 273) { if (TB_parameters->nb_rb != 273) {
a_segments = a_segments*nb_rb; a_segments = a_segments*TB_parameters->nb_rb;
a_segments = a_segments/273 +1; a_segments = a_segments/273 +1;
} }
if (harq_process->C > a_segments) { if (TB_parameters->C > a_segments) {
LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments); LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments);
return -1; return -1;
} }
max_num_segments = max(max_num_segments, TB_parameters->C);
#ifdef DEBUG_ULSCH_DECODING #ifdef DEBUG_ULSCH_DECODING
printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z); printf("ulsch decoding nr segmentation Z %d\n", TB_parameters->Z);
if (!frame % 100) if (!frame % 100)
printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z); printf("K %d C %d Z %d \n",
printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); TB_parameters->K,
TB_parameters->C,
TB_parameters->Z);
printf("Segmentation: C %d, K %d\n",
TB_parameters->C,
TB_parameters->K);
#endif #endif
decParams.Z = harq_process->Z; TB_parameters->max_ldpc_iterations = ulsch->max_ldpc_iterations;
decParams.numMaxIter = ulsch->max_ldpc_iterations; TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index;
decParams.Qm = Qm; TB_parameters->tbslbrm = pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes;
decParams.rv = pusch_pdu->pusch_data.rv_index; TB_parameters->abort_decode = &harq_process->abort_decode;
decParams.outMode = 0; set_abort(&harq_process->abort_decode, false);
decParams.setCombIn = !harq_process->harq_to_be_cleared;
}
nrLDPC_segment_decoding_parameters_t segments[nb_pusch][max_num_segments];
memset(segments, 0, sizeof(segments));
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;
if (!ulsch_llr) {
LOG_E(PHY, "ulsch_decoding.c: NULL ulsch_llr pointer\n");
return -1;
}
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) { if (harq_process->harq_to_be_cleared) {
for (int r = 0; r < harq_process->C; r++) for (int r = 0; r < TB_parameters->C; r++) {
harq_process->d_to_be_cleared[r] = true; harq_process->d_to_be_cleared[r] = true;
}
harq_process->harq_to_be_cleared = false; 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; int ret_decoder = phy_vars_gNB->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
uint32_t offset = 0, r_offset = 0;
set_abort(&harq_process->abort_decode, false); // post decode
for (int r = 0; r < harq_process->C; r++) { for (uint8_t pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
int E = nr_get_E(G, harq_process->C, Qm, n_layers, r); uint8_t ULSCH_id = ULSCH_ids[pusch_id];
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
ldpcDecode_t *rdata = &((ldpcDecode_t *)t_info->buf)[t_info->len]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
DevAssert(t_info->len < t_info->cap);
rdata->ans = &t_info->ans[t_info->len]; nrLDPC_TB_decoding_parameters_t TB_parameters = TBs[pusch_id];
t_info->len += 1;
uint32_t offset = 0;
decParams.R = nr_get_R_ldpc_decoder(pusch_pdu->pusch_data.rv_index, for (int r = 0; r < TB_parameters.C; r++) {
E, nrLDPC_segment_decoding_parameters_t nrLDPC_segment_decoding_parameters = TB_parameters.segments[r];
decParams.BG, // Copy c to b in case of decoding success
decParams.Z, if (nrLDPC_segment_decoding_parameters.decodeSuccess) {
&harq_process->llrLen, memcpy(harq_process->b + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
harq_process->round); } else {
rdata->gNB = phy_vars_gNB; LOG_D(PHY, "uplink segment error %d/%d\n", r, harq_process->C);
rdata->ulsch_harq = harq_process; LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id);
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;
task_t t = {.func = &nr_processULSegment, .args = rdata};
pushTpool(&phy_vars_gNB->threadPool, t);
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)); offset += ((harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
} }
return harq_process->C; }
return ret_decoder;
} }
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/impl_defs_top.h" #include "PHY/impl_defs_top.h"
#include "PHY/defs_common.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_extern.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#include "executables/rt_profiling.h" #include "executables/rt_profiling.h"
...@@ -494,9 +495,10 @@ typedef struct PHY_VARS_gNB_s { ...@@ -494,9 +495,10 @@ typedef struct PHY_VARS_gNB_s {
/// OFDM symbol offset divisor for UL /// OFDM symbol offset divisor for UL
uint32_t ofdm_offset_divisor; uint32_t ofdm_offset_divisor;
int ldpc_offload_flag; /// NR LDPC coding related
nrLDPC_coding_interface_t nrLDPC_coding_interface;
int max_ldpc_iterations; int max_ldpc_iterations;
/// indicate the channel estimation technique in time domain /// indicate the channel estimation technique in time domain
int chest_time; int chest_time;
/// indicate the channel estimation technique in freq domain /// indicate the channel estimation technique in freq domain
......
...@@ -305,124 +305,30 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, ...@@ -305,124 +305,30 @@ 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); 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_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
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");
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 { int nb_pusch = 0;
LOG_D(PHY, "ULSCH %d in error\n", rdata->ulsch_id); 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 (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !gNB->pusch_vars[rdata->ulsch_id].DTX) { if (nb_pusch == 0) {
LOG_D(NR_PHY, return 0;
"[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->frame,
ulsch->slot,
ulsch->rnti,
rdata->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);
LOG_D(PHY, "ULSCH received ok \n");
ulsch->active = false;
ulsch_harq->round = 0;
//dumpsig=1;
} 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",
gNB->Mod_id,
ulsch->frame,
ulsch->slot,
rdata->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->handled = 1;
LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
// dumpsig=1;
}
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);
} uint8_t ULSCH_ids[nb_pusch];
*/ uint32_t G[nb_pusch];
ulsch->last_iteration_cnt = rdata->decodeIterations; int pusch_id = 0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,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;
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; nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
uint16_t nb_re_dmrs; uint16_t nb_re_dmrs;
...@@ -438,15 +344,14 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, ...@@ -438,15 +344,14 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB,
else else
nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data; nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data;
uint32_t G = nr_get_G(pusch_pdu->rb_size, G[pusch_id] = nr_get_G(pusch_pdu->rb_size,
number_symbols, number_symbols,
nb_re_dmrs, nb_re_dmrs,
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
gNB->ulsch[ULSCH_id].unav_res, gNB->ulsch[ULSCH_id].unav_res,
pusch_pdu->qam_mod_order, pusch_pdu->qam_mod_order,
pusch_pdu->nrOfLayers); 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",
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, pusch_pdu->rb_size,
number_symbols, number_symbols,
nb_re_dmrs, nb_re_dmrs,
...@@ -461,30 +366,82 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, ...@@ -461,30 +366,82 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB,
number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
pusch_pdu->qam_mod_order, pusch_pdu->qam_mod_order,
pusch_pdu->nrOfLayers); pusch_pdu->nrOfLayers);
pusch_id++;
}
}
//---------------------------------------------------------- //----------------------------------------------------------
//--------------------- ULSCH decoding --------------------- //--------------------- 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, 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) && !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,
ULSCH_id, ULSCH_id,
gNB->pusch_vars[ULSCH_id].llr, ulsch->frame,
frame_parms, ulsch->slot,
pusch_pdu, ulsch->rnti,
frame_rx, ulsch->harq_pid,
slot_rx, pusch_pdu->pusch_data.new_data_indicator,
harq_pid, ulsch->active,
G, ulsch_harq->round,
t_info); ulsch_harq->TBS,
return nbDecode; 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;
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)\n",
gNB->Mod_id,
ulsch->frame,
ulsch->slot,
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);
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",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
}
}
return ret_nr_ulsch_decoding;
}
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) 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)
{ {
...@@ -840,12 +797,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) ...@@ -840,12 +797,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
} }
} }
ldpcDecode_t arr[64]; bool ulsch_to_decode[gNB->max_nb_pusch];
task_ans_t ans[64] = {0}; bzero((void *)ulsch_to_decode, sizeof(ulsch_to_decode));
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;
for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; 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) ...@@ -937,25 +890,26 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
pusch_vars->DTX = 0; pusch_vars->DTX = 0;
} }
ulsch_to_decode[ULSCH_id] = true;
stop_meas(&gNB->rx_pusch_stats); stop_meas(&gNB->rx_pusch_stats);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 0); 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_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); // 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); int const ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_to_decode);
for (int i = 0; i < t_info.len; ++i) { if (ret_nr_ulsch_procedures != 0) {
nr_postDecode(gNB, &arr[i]); 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 /* 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 * (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 * only once, which ensures exactly one start and stop of the ULSCH decoding time
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment