feat(nrLDPC_coding_interface): Use reworked interface in UE
This commit is contained in:
committed by
Romain Beurdouche
parent
00e1ad124d
commit
80c406693f
@@ -42,6 +42,7 @@
|
||||
|
||||
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/phy_vars_nr_ue.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
@@ -219,7 +220,6 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
UE->rf_map.card = 0;
|
||||
UE->rf_map.chain = CC_id + 0;
|
||||
UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations;
|
||||
UE->ldpc_offload_enable = nrUE_params.ldpc_offload_flag;
|
||||
UE->UE_scan_carrier = nrUE_params.UE_scan_carrier;
|
||||
UE->UE_fo_compensation = nrUE_params.UE_fo_compensation;
|
||||
UE->if_freq = nrUE_params.if_freq;
|
||||
@@ -388,6 +388,7 @@ configmodule_interface_t *uniqCfg = NULL;
|
||||
|
||||
// A global var to reduce the changes size
|
||||
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
|
||||
nrLDPC_coding_interface_t nrLDPC_coding_interface = {0};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -427,10 +428,8 @@ int main(int argc, char **argv)
|
||||
|
||||
init_opt();
|
||||
|
||||
if (nrUE_params.ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
|
||||
load_LDPClib(NULL, &ldpc_interface);
|
||||
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface);
|
||||
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
|
||||
|
||||
if (ouput_vcd) {
|
||||
vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd");
|
||||
@@ -445,6 +444,8 @@ int main(int argc, char **argv)
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
PHY_vars_UE_g[inst][CC_id] = malloc(sizeof(*PHY_vars_UE_g[inst][CC_id]));
|
||||
memset(PHY_vars_UE_g[inst][CC_id], 0, sizeof(*PHY_vars_UE_g[inst][CC_id]));
|
||||
// All instances use the same coding interface
|
||||
PHY_vars_UE_g[inst][CC_id]->nrLDPC_coding_interface = nrLDPC_coding_interface;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
{"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, .uptr=&nrUE_params.ofdm_offset_divisor, .defuintval=8, TYPE_UINT32, 0}, \
|
||||
{"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .iptr=&nrUE_params.max_ldpc_iterations, .defuintval=8, TYPE_UINT8, 0}, \
|
||||
{"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&(nrUE_params.ldpc_offload_flag), .defintval=0, TYPE_INT, 0}, \
|
||||
{"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, .iptr=&nrUE_params.vcdflag, .defintval=0, TYPE_INT, 0}, \
|
||||
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&nrUE_params.uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
|
||||
{"reconfig-file", CONFIG_HLP_RE_CFG_FILE, 0, .strptr=&nrUE_params.reconfig_file, .defstrval="./reconfig.raw", TYPE_STRING, 0}, \
|
||||
@@ -91,7 +90,6 @@ typedef struct {
|
||||
int nb_antennas_tx;
|
||||
int N_RB_DL;
|
||||
int ssb_start_subcarrier;
|
||||
int ldpc_offload_flag;
|
||||
double time_sync_P;
|
||||
double time_sync_I;
|
||||
unsigned int ntn_koffset;
|
||||
|
||||
@@ -108,7 +108,6 @@ extern "C"
|
||||
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
|
||||
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
|
||||
#define CONFIG_HLP_NOITTI "Do not start itti threads, call queue processing in place, inside the caller thread"
|
||||
#define CONFIG_HLP_LDPC_OFFLOAD "Enable LDPC offload to AMD Xilinx T2 telco card\n"
|
||||
#define CONFIG_HLP_SYNC_REF "UE acts a Sync Reference in Sidelink. 0-none 1-GNB 2-GNSS 4-localtiming\n"
|
||||
#define CONFIG_HLP_TADV \
|
||||
"Set RF board timing_advance to compensate fix delay inside the RF board between Rx and Tx timestamps (RF board internal " \
|
||||
@@ -181,7 +180,6 @@ extern int usrp_tx_thread;
|
||||
{"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \
|
||||
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
|
||||
{"no-itti-threads", CONFIG_HLP_NOITTI, PARAMFLAG_BOOL, .iptr=&softmodem_params.no_itti, .defintval=0, TYPE_INT, 0}, \
|
||||
{"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&LDPC_OFFLOAD_FLAG, .defstrval=0, TYPE_INT, 0}, \
|
||||
{"sync-ref", CONFIG_HLP_SYNC_REF, 0, .uptr=&SYNC_REF, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"A" , CONFIG_HLP_TADV, 0, .iptr=&softmodem_params.command_line_sample_advance,.defintval=0, TYPE_INT, 0}, \
|
||||
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \
|
||||
@@ -231,7 +229,6 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -356,6 +356,7 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES
|
||||
free_and_zero(harq_list[j][i].c[r]);
|
||||
free_and_zero(harq_list[j][i].d[r]);
|
||||
}
|
||||
free_and_zero(harq_list[j][i].b);
|
||||
free_and_zero(harq_list[j][i].c);
|
||||
free_and_zero(harq_list[j][i].d);
|
||||
}
|
||||
@@ -406,6 +407,7 @@ void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PR
|
||||
memset(harq_list[j] + i, 0, sizeof(NR_DL_UE_HARQ_t));
|
||||
init_downlink_harq_status(harq_list[j] + i);
|
||||
|
||||
harq_list[j][i].b = malloc16_clear(a_segments * 1056);
|
||||
harq_list[j][i].c = malloc16(a_segments*sizeof(uint8_t *));
|
||||
harq_list[j][i].d = malloc16(a_segments*sizeof(int16_t *));
|
||||
const int sz=5*8448*sizeof(int16_t);
|
||||
|
||||
@@ -19,16 +19,8 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
|
||||
* \brief Top-level routines for decoding Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03
|
||||
* \author R. Knopp
|
||||
* \date 2011
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
/*! \file PHY/NR_UE_TRANSPORT/nr_dlsch_decoding_slot.c
|
||||
*/
|
||||
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
@@ -36,6 +28,7 @@
|
||||
#include "PHY/phy_extern_nr_ue.h"
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
#include "SIMULATION/TOOLS/sim.h"
|
||||
@@ -45,11 +38,6 @@
|
||||
#include "openair1/PHY/TOOLS/phy_scope_interface.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
//#define ENABLE_PHY_PAYLOAD_DEBUG 1
|
||||
|
||||
#define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
|
||||
//#define OAI_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX
|
||||
|
||||
static extended_kpi_ue kpiStructure = {0};
|
||||
|
||||
extended_kpi_ue* getKPIUE(void) {
|
||||
@@ -69,371 +57,302 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
|
||||
nr_codeword_unscrambling(llr, size, q, Nid, n_RNTI);
|
||||
}
|
||||
|
||||
static bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
ldpcDecode_ue_t *rdata,
|
||||
bool last,
|
||||
int b_size,
|
||||
uint8_t b[b_size],
|
||||
int *num_seg_ok,
|
||||
const UE_nr_rxtx_proc_t *proc)
|
||||
/*! \brief Prepare necessary parameters for nrLDPC_coding_interface
|
||||
*/
|
||||
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
int16_t **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids)
|
||||
{
|
||||
NR_DL_UE_HARQ_t *harq_process = rdata->harq_process;
|
||||
NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch;
|
||||
int r = rdata->segment_r;
|
||||
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch];
|
||||
memset(TBs, 0, sizeof(TBs));
|
||||
nrLDPC_slot_decoding_parameters_t slot_parameters = {
|
||||
.frame = proc->frame_rx,
|
||||
.slot = proc->nr_slot_rx,
|
||||
.nb_TBs = nb_dlsch,
|
||||
.threadPool = &get_nrUE_params()->Tpool,
|
||||
.TBs = TBs
|
||||
};
|
||||
|
||||
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &rdata->ts_deinterleave);
|
||||
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &rdata->ts_rate_unmatch);
|
||||
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &rdata->ts_ldpc_decode);
|
||||
int max_num_segments = 0;
|
||||
|
||||
bool decodeSuccess = (rdata->decodeIterations < (1+dlsch->max_ldpc_iterations));
|
||||
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
|
||||
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
|
||||
int harq_pid = dlsch_config->harq_process_nbr;
|
||||
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
|
||||
if (decodeSuccess) {
|
||||
memcpy(b+rdata->offset,
|
||||
harq_process->c[r],
|
||||
rdata->Kr_bytes - (harq_process->F>>3) -((harq_process->C>1)?3:0));
|
||||
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
|
||||
uint8_t nb_re_dmrs;
|
||||
|
||||
(*num_seg_ok)++;
|
||||
} else {
|
||||
LOG_D(PHY, "DLSCH %d in error\n", rdata->dlsch_id);
|
||||
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv);
|
||||
|
||||
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
|
||||
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
|
||||
else
|
||||
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
|
||||
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n");
|
||||
return dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
|
||||
|
||||
/* Neither harq_pid nor DLSCH_id are unique in the instance
|
||||
* but their combination is.
|
||||
* Since DLSCH_id < 2
|
||||
* then 2 * harq_pid + DLSCH_id is unique.
|
||||
*/
|
||||
TB_parameters->harq_unique_pid = 2 * harq_pid + DLSCH_id;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
TB_parameters->G = G[DLSCH_id];
|
||||
TB_parameters->nb_rb = dlsch_config->number_rbs;
|
||||
TB_parameters->Qm = dlsch_config->qamModOrder;
|
||||
TB_parameters->mcs = dlsch_config->mcs;
|
||||
TB_parameters->nb_layers = dlsch[DLSCH_id].Nl;
|
||||
TB_parameters->BG = dlsch_config->ldpcBaseGraph;
|
||||
TB_parameters->A = dlsch_config->TBS;
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
TB_parameters->processedSegments = &harq_process->processedSegments;
|
||||
|
||||
float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f;
|
||||
|
||||
LOG_D(
|
||||
PHY,
|
||||
"%d.%d DLSCH %d Decoding, harq_pid %d TBS %d G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d Qm %d "
|
||||
"Coderate %f\n",
|
||||
slot_parameters.frame,
|
||||
slot_parameters.slot,
|
||||
DLSCH_id,
|
||||
harq_pid,
|
||||
dlsch_config->TBS,
|
||||
TB_parameters->G,
|
||||
nb_re_dmrs,
|
||||
dmrs_length,
|
||||
TB_parameters->mcs,
|
||||
TB_parameters->nb_layers,
|
||||
dlsch_config->number_symbols,
|
||||
TB_parameters->nb_rb,
|
||||
TB_parameters->Qm,
|
||||
Coderate);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN);
|
||||
|
||||
if (harq_process->first_rx == 1) {
|
||||
// This is a new packet, so compute quantities regarding segmentation
|
||||
nr_segmentation(NULL,
|
||||
NULL,
|
||||
lenWithCrc(1, TB_parameters->A), // We give a max 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;
|
||||
|
||||
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A);
|
||||
return dlsch[DLSCH_id].max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100))
|
||||
LOG_I(PHY, "K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, TB_parameters->nb_layers);
|
||||
// clear HARQ buffer
|
||||
for (int i = 0; i < harq_process->C; i++)
|
||||
memset(harq_process->d[i], 0, 5 * 8448 * sizeof(int16_t));
|
||||
} else {
|
||||
// This is not a new packet, so retrieve previously computed quantities regarding segmentation
|
||||
TB_parameters->C = harq_process->C;
|
||||
TB_parameters->K = harq_process->K;
|
||||
TB_parameters->Z = harq_process->Z;
|
||||
TB_parameters->F = harq_process->F;
|
||||
}
|
||||
max_num_segments = max(max_num_segments, TB_parameters->C);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT);
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
|
||||
LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K);
|
||||
|
||||
TB_parameters->max_ldpc_iterations = dlsch[DLSCH_id].max_ldpc_iterations;
|
||||
TB_parameters->rv_index = dlsch_config->rv;
|
||||
TB_parameters->tbslbrm = dlsch_config->tbslbrm;
|
||||
TB_parameters->abort_decode = &harq_process->abort_decode;
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
}
|
||||
|
||||
if (!last)
|
||||
return false; // continue decoding
|
||||
nrLDPC_segment_decoding_parameters_t segments[nb_dlsch][max_num_segments];
|
||||
memset(segments, 0, sizeof(segments));
|
||||
bool d_to_be_cleared[nb_dlsch][max_num_segments];
|
||||
memset(d_to_be_cleared, 0, sizeof(d_to_be_cleared));
|
||||
|
||||
// all segments are done
|
||||
kpiStructure.nb_total++;
|
||||
kpiStructure.blockSize = dlsch->dlsch_config.TBS;
|
||||
kpiStructure.dl_mcs = dlsch->dlsch_config.mcs;
|
||||
kpiStructure.nofRBs = dlsch->dlsch_config.number_rbs;
|
||||
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
|
||||
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
int harq_pid = dlsch_config->harq_process_nbr;
|
||||
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
|
||||
harq_process->decodeResult = *num_seg_ok == harq_process->C;
|
||||
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
|
||||
TB_parameters->segments = segments[pdsch_id];
|
||||
|
||||
if (harq_process->decodeResult && harq_process->C > 1) {
|
||||
/* check global CRC */
|
||||
int A = dlsch->dlsch_config.TBS;
|
||||
// we have regrouped the transport block
|
||||
if (!check_crc(b, lenWithCrc(1, A), crcType(1, A))) {
|
||||
LOG_E(PHY,
|
||||
" Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n",
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
harq_process->C);
|
||||
harq_process->decodeResult = false;
|
||||
uint32_t r_offset = 0;
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
if (harq_process->first_rx == 1)
|
||||
d_to_be_cleared[pdsch_id][r] = true;
|
||||
else
|
||||
d_to_be_cleared[pdsch_id][r] = false;
|
||||
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->DLround);
|
||||
segment_parameters->llr = dlsch_llr[DLSCH_id] + r_offset;
|
||||
segment_parameters->d = harq_process->d[r];
|
||||
segment_parameters->d_to_be_cleared = &d_to_be_cleared[pdsch_id][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->decodeResult) {
|
||||
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we
|
||||
const int sz = dlsch->dlsch_config.TBS / 8;
|
||||
if (b[sz] == 0 && b[sz + 1] == 0) {
|
||||
// do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24)
|
||||
int i = 0;
|
||||
while (b[i] == 0 && i < sz)
|
||||
i++;
|
||||
if (i == sz) {
|
||||
int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
|
||||
|
||||
if (ret_decoder != 0) {
|
||||
return dlsch->max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
// post decode
|
||||
for (uint8_t pdsch_id = 0; pdsch_id < nb_dlsch; pdsch_id++) {
|
||||
uint8_t DLSCH_id = DLSCH_ids[pdsch_id];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
int harq_pid = dlsch_config->harq_process_nbr;
|
||||
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id];
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
nrLDPC_segment_decoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
|
||||
if (segment_parameters->decodeSuccess) {
|
||||
memcpy(b[DLSCH_id] + offset,
|
||||
harq_process->c[r],
|
||||
(harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
} else {
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
LOG_D(PHY, "frame=%d, slot=%d, first_rx=%d, rv_index=%d\n", proc->frame_rx, proc->nr_slot_rx, harq_process->first_rx, dlsch_config->rv);
|
||||
LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C);
|
||||
LOG_D(PHY, "DLSCH %d in error\n", DLSCH_id);
|
||||
}
|
||||
offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0);
|
||||
|
||||
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_DEINTERLEAVING_STATS], &segment_parameters->ts_deinterleave);
|
||||
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_RATE_UNMATCHING_STATS], &segment_parameters->ts_rate_unmatch);
|
||||
merge_meas(&phy_vars_ue->phy_cpu_stats.cpu_time_stats[DLSCH_LDPC_DECODING_STATS], &segment_parameters->ts_ldpc_decode);
|
||||
|
||||
}
|
||||
|
||||
kpiStructure.nb_total++;
|
||||
kpiStructure.blockSize = dlsch_config->TBS;
|
||||
kpiStructure.dl_mcs = dlsch_config->mcs;
|
||||
kpiStructure.nofRBs = dlsch_config->number_rbs;
|
||||
|
||||
harq_process->decodeResult = harq_process->processedSegments == harq_process->C;
|
||||
|
||||
if (harq_process->decodeResult && harq_process->C > 1) {
|
||||
/* check global CRC */
|
||||
int A = dlsch->dlsch_config.TBS;
|
||||
// we have regrouped the transport block
|
||||
if (!check_crc(b[DLSCH_id], lenWithCrc(1, A), crcType(1, A))) {
|
||||
LOG_E(PHY,
|
||||
"received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the "
|
||||
"corresponding CRC, and nothing prevents to have a all 0 packet\n");
|
||||
" Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n",
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
harq_process->C);
|
||||
harq_process->decodeResult = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (harq_process->decodeResult) {
|
||||
LOG_D(PHY, "DLSCH received ok \n");
|
||||
harq_process->status = SCH_IDLE;
|
||||
dlsch->last_iteration_cnt = rdata->decodeIterations;
|
||||
} else {
|
||||
LOG_D(PHY, "DLSCH received nok \n");
|
||||
kpiStructure.nb_nack++;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1;
|
||||
}
|
||||
return true; // end TB decoding
|
||||
}
|
||||
|
||||
static void nr_processDLSegment(void *arg)
|
||||
{
|
||||
ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) arg;
|
||||
NR_UE_DLSCH_t *dlsch = rdata->dlsch;
|
||||
NR_DL_UE_HARQ_t *harq_process= rdata->harq_process;
|
||||
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||
int r = rdata->segment_r;
|
||||
int E = rdata->E;
|
||||
int Qm = rdata->Qm;
|
||||
int r_offset = rdata->r_offset;
|
||||
uint8_t kc = rdata->Kc;
|
||||
uint32_t Tbslbrm = rdata->Tbslbrm;
|
||||
short* dlsch_llr = rdata->dlsch_llr;
|
||||
int8_t LDPCoutput[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32)));
|
||||
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
int8_t l [68*384 + 16] __attribute__ ((aligned(16)));
|
||||
|
||||
const int Kr = harq_process->K;
|
||||
const int K_bits_F = Kr - harq_process->F;
|
||||
|
||||
t_nrLDPC_time_stats procTime = {0};
|
||||
|
||||
//if we return before LDPC decoder run, the block is in error
|
||||
rdata->decodeIterations = dlsch->max_ldpc_iterations + 1;
|
||||
|
||||
start_meas(&rdata->ts_deinterleave);
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_IN);
|
||||
int16_t w[E];
|
||||
nr_deinterleaving_ldpc(E,
|
||||
Qm,
|
||||
w, // [hna] w is e
|
||||
dlsch_llr+r_offset);
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_OUT);
|
||||
stop_meas(&rdata->ts_deinterleave);
|
||||
|
||||
start_meas(&rdata->ts_rate_unmatch);
|
||||
/* LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,E %d, F %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n",
|
||||
harq_pid,r, G,E,harq_process->F,
|
||||
Kr*3,
|
||||
harq_process->TBS,
|
||||
Qm,
|
||||
harq_process->nb_rb,
|
||||
harq_process->Nl,
|
||||
harq_process->rvidx,
|
||||
harq_process->round); */
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_IN);
|
||||
|
||||
if (nr_rate_matching_ldpc_rx(Tbslbrm,
|
||||
p_decoderParms->BG,
|
||||
p_decoderParms->Z,
|
||||
harq_process->d[r],
|
||||
w,
|
||||
harq_process->C,
|
||||
dlsch->dlsch_config.rv,
|
||||
harq_process->first_rx,
|
||||
E,
|
||||
harq_process->F,
|
||||
Kr-harq_process->F-2*(p_decoderParms->Z))==-1) {
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT);
|
||||
stop_meas(&rdata->ts_rate_unmatch);
|
||||
LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n");
|
||||
return;
|
||||
}
|
||||
stop_meas(&rdata->ts_rate_unmatch);
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) {
|
||||
LOG_D(PHY,"decoder input(segment %u) :",r);
|
||||
|
||||
for (int i=0; i<E; i++)
|
||||
LOG_D(PHY,"%d : %d\n",i,harq_process->d[r][i]);
|
||||
|
||||
LOG_D(PHY,"\n");
|
||||
}
|
||||
{
|
||||
start_meas(&rdata->ts_ldpc_decode);
|
||||
//set first 2*Z_c bits to zeros
|
||||
memset(z,0,2*harq_process->Z*sizeof(int16_t));
|
||||
//set Filler bits
|
||||
memset((z+K_bits_F),127,harq_process->F*sizeof(int16_t));
|
||||
//Move coded bits before filler bits
|
||||
memcpy((z+2*harq_process->Z),harq_process->d[r],(K_bits_F-2*harq_process->Z)*sizeof(int16_t));
|
||||
//skip filler bits
|
||||
memcpy((z+Kr),harq_process->d[r]+(Kr-2*harq_process->Z),(kc*harq_process->Z-Kr)*sizeof(int16_t));
|
||||
|
||||
//Saturate coded bits before decoding into 8 bits values
|
||||
simde__m128i *pv = (simde__m128i*)&z;
|
||||
simde__m128i *pl = (simde__m128i*)&l;
|
||||
for (int i=0, j=0; j < ((kc*harq_process->Z)>>4)+1; i+=2, j++) {
|
||||
pl[j] = simde_mm_packs_epi16(pv[i],pv[i+1]);
|
||||
if (harq_process->decodeResult) {
|
||||
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we
|
||||
const int sz = dlsch->dlsch_config.TBS / 8;
|
||||
if (b[DLSCH_id][sz] == 0 && b[DLSCH_id][sz + 1] == 0) {
|
||||
// do the check only if the 2 first bytes of the CRC are 0 (it can be CRC16 or CRC24)
|
||||
int i = 0;
|
||||
while (b[DLSCH_id][i] == 0 && i < sz)
|
||||
i++;
|
||||
if (i == sz) {
|
||||
LOG_E(PHY,
|
||||
"received all 0 pdu, consider it false reception, even if the TS 38.212 7.2.1 says only we should attach the "
|
||||
"corresponding CRC, and nothing prevents to have a all 0 packet\n");
|
||||
harq_process->decodeResult = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_IN);
|
||||
uint32_t A = dlsch->dlsch_config.TBS;
|
||||
p_decoderParms->E = lenWithCrc(harq_process->C, A);
|
||||
p_decoderParms->crc_type = crcType(harq_process->C, A);
|
||||
rdata->decodeIterations =
|
||||
ldpc_interface.LDPCdecoder(p_decoderParms, 0, 0, 0, l, LDPCoutput, &procTime, &harq_process->abort_decode);
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_LDPC, VCD_FUNCTION_OUT);
|
||||
|
||||
if (rdata->decodeIterations <= dlsch->max_ldpc_iterations)
|
||||
memcpy(harq_process->c[r], LDPCoutput, Kr >> 3);
|
||||
stop_meas(&rdata->ts_ldpc_decode);
|
||||
}
|
||||
completed_task_ans(rdata->ans);
|
||||
}
|
||||
|
||||
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int eNB_id,
|
||||
short *dlsch_llr,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
NR_DL_UE_HARQ_t *harq_process,
|
||||
uint32_t frame,
|
||||
uint16_t nb_symb_sch,
|
||||
uint8_t nr_slot_rx,
|
||||
uint8_t harq_pid,
|
||||
int b_size,
|
||||
uint8_t b[b_size],
|
||||
int G)
|
||||
{
|
||||
uint32_t ret,offset;
|
||||
uint32_t r,r_offset=0,Kr=8424,Kr_bytes;
|
||||
t_nrLDPC_dec_params decParams;
|
||||
decParams.check_crc = check_crc;
|
||||
|
||||
if (!harq_process) {
|
||||
LOG_E(PHY,"dlsch_decoding.c: NULL harq_process pointer\n");
|
||||
return(dlsch->max_ldpc_iterations + 1);
|
||||
}
|
||||
|
||||
// HARQ stats
|
||||
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, dlsch->dlsch_config.rv);
|
||||
uint16_t nb_rb;// = 30;
|
||||
uint8_t dmrs_Type = dlsch->dlsch_config.dmrsConfigType;
|
||||
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
|
||||
uint8_t nb_re_dmrs;
|
||||
|
||||
if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) {
|
||||
nb_re_dmrs = 6*dlsch->dlsch_config.n_dmrs_cdm_groups;
|
||||
} else {
|
||||
nb_re_dmrs = 4*dlsch->dlsch_config.n_dmrs_cdm_groups;
|
||||
}
|
||||
|
||||
uint16_t dmrs_length = get_num_dmrs(dlsch->dlsch_config.dlDmrsSymbPos);
|
||||
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_IN);
|
||||
|
||||
//NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[0];
|
||||
|
||||
if (!dlsch_llr) {
|
||||
LOG_E(PHY,"dlsch_decoding.c: NULL dlsch_llr pointer\n");
|
||||
return(dlsch->max_ldpc_iterations + 1);
|
||||
}
|
||||
|
||||
if (!frame_parms) {
|
||||
LOG_E(PHY,"dlsch_decoding.c: NULL frame_parms pointer\n");
|
||||
return(dlsch->max_ldpc_iterations + 1);
|
||||
}
|
||||
|
||||
nb_rb = dlsch->dlsch_config.number_rbs;
|
||||
uint32_t A = dlsch->dlsch_config.TBS;
|
||||
ret = dlsch->max_ldpc_iterations + 1;
|
||||
dlsch->last_iteration_cnt = ret;
|
||||
|
||||
// target_code_rate is in 0.1 units
|
||||
float Coderate = (float) dlsch->dlsch_config.targetCodeRate / 10240.0f;
|
||||
|
||||
decParams.BG = dlsch->dlsch_config.ldpcBaseGraph;
|
||||
unsigned int kc = decParams.BG == 2 ? 52 : 68;
|
||||
|
||||
if (harq_process->first_rx == 1) {
|
||||
// This is a new packet, so compute quantities regarding segmentation
|
||||
nr_segmentation(NULL,
|
||||
NULL,
|
||||
lenWithCrc(1, A), // We give a max size in case of 1 segment
|
||||
&harq_process->C,
|
||||
&harq_process->K,
|
||||
&harq_process->Z, // [hna] Z is Zc
|
||||
&harq_process->F,
|
||||
decParams.BG);
|
||||
|
||||
if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * dlsch->Nl) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, A);
|
||||
return(-1);
|
||||
if (harq_process->decodeResult) {
|
||||
LOG_D(PHY, "DLSCH received ok \n");
|
||||
harq_process->status = SCH_IDLE;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
|
||||
} else {
|
||||
LOG_D(PHY, "DLSCH received nok \n");
|
||||
kpiStructure.nb_nack++;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1;
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!frame%100))
|
||||
LOG_I(PHY,"K %d C %d Z %d nl %d \n", harq_process->K, harq_process->C, harq_process->Z, dlsch->Nl);
|
||||
// clear HARQ buffer
|
||||
for (int i=0; i <harq_process->C; i++)
|
||||
memset(harq_process->d[i],0,5*8448*sizeof(int16_t));
|
||||
uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
|
||||
uint8_t nb_re_dmrs;
|
||||
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
|
||||
nb_re_dmrs = 6 * dlsch_config->n_dmrs_cdm_groups;
|
||||
else
|
||||
nb_re_dmrs = 4 * dlsch_config->n_dmrs_cdm_groups;
|
||||
uint16_t dmrs_length = get_num_dmrs(dlsch_config->dlDmrsSymbPos);
|
||||
float Coderate = (float)dlsch->dlsch_config.targetCodeRate / 10240.0f;
|
||||
LOG_D(PHY,
|
||||
"%d.%d DLSCH Decoded, harq_pid %d, round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d "
|
||||
"nb_symb_sch %d "
|
||||
"nb_rb %d Qm %d Coderate %f\n",
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
harq_pid,
|
||||
harq_process->DLround,
|
||||
harq_process->decodeResult,
|
||||
dlsch->dlsch_config.TBS,
|
||||
dlsch->dlsch_config.TBS / 8,
|
||||
G[DLSCH_id],
|
||||
nb_re_dmrs,
|
||||
dmrs_length,
|
||||
dlsch->dlsch_config.mcs,
|
||||
dlsch->Nl,
|
||||
dlsch_config->number_symbols,
|
||||
dlsch_config->number_rbs,
|
||||
dlsch_config->qamModOrder,
|
||||
Coderate);
|
||||
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_SEGMENTATION, VCD_FUNCTION_OUT);
|
||||
decParams.Z = harq_process->Z;
|
||||
decParams.numMaxIter = dlsch->max_ldpc_iterations;
|
||||
decParams.outMode = 0;
|
||||
r_offset = 0;
|
||||
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * dlsch->Nl; //number of segments to be allocated
|
||||
|
||||
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+dlsch->max_ldpc_iterations));
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
|
||||
LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
|
||||
|
||||
Kr = harq_process->K;
|
||||
Kr_bytes = Kr>>3;
|
||||
offset = 0;
|
||||
|
||||
ldpcDecode_ue_t arr[harq_process->C];
|
||||
task_ans_t ans[harq_process->C];
|
||||
memset(ans, 0, harq_process->C * sizeof(task_ans_t));
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
for (r=0; r<harq_process->C; r++) {
|
||||
//printf("start rx segment %d\n",r);
|
||||
uint32_t E = nr_get_E(G, harq_process->C, dlsch->dlsch_config.qamModOrder, dlsch->Nl, r);
|
||||
decParams.R = nr_get_R_ldpc_decoder(dlsch->dlsch_config.rv, E, decParams.BG, decParams.Z, &harq_process->llrLen, harq_process->DLround);
|
||||
ldpcDecode_ue_t *rdata = &arr[r];
|
||||
rdata->ans = &ans[r];
|
||||
|
||||
rdata->phy_vars_ue = phy_vars_ue;
|
||||
rdata->harq_process = harq_process;
|
||||
rdata->decoderParms = decParams;
|
||||
rdata->dlsch_llr = dlsch_llr;
|
||||
rdata->Kc = kc;
|
||||
rdata->segment_r = r;
|
||||
rdata->E = E;
|
||||
rdata->Qm = dlsch->dlsch_config.qamModOrder;
|
||||
rdata->r_offset = r_offset;
|
||||
rdata->Kr_bytes = Kr_bytes;
|
||||
rdata->rv_index = dlsch->dlsch_config.rv;
|
||||
rdata->Tbslbrm = dlsch->dlsch_config.tbslbrm;
|
||||
rdata->offset = offset;
|
||||
rdata->dlsch = dlsch;
|
||||
rdata->dlsch_id = harq_pid;
|
||||
reset_meas(&rdata->ts_deinterleave);
|
||||
reset_meas(&rdata->ts_rate_unmatch);
|
||||
reset_meas(&rdata->ts_ldpc_decode);
|
||||
task_t t = {.args = rdata, .func = nr_processDLSegment};
|
||||
pushTpool(&get_nrUE_params()->Tpool, t);
|
||||
LOG_D(PHY, "Added a block to decode, in pipe: %d\n", r);
|
||||
r_offset += E;
|
||||
offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
int num_seg_ok = 0;
|
||||
int nbDecode = harq_process->C;
|
||||
if (nbDecode > 0) {
|
||||
join_task_ans(ans, nbDecode);
|
||||
for (size_t i = 0; i < nbDecode; ++i) {
|
||||
nr_ue_postDecode(phy_vars_ue, &arr[i], i == nbDecode - 1, b_size, b, &num_seg_ok, proc);
|
||||
}
|
||||
}
|
||||
LOG_D(PHY,
|
||||
"%d.%d DLSCH Decoded, harq_pid %d, round %d, result: %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d "
|
||||
"nb_symb_sch %d "
|
||||
"nb_rb %d Qm %d Coderate %f\n",
|
||||
frame,
|
||||
nr_slot_rx,
|
||||
harq_pid,
|
||||
harq_process->DLround,
|
||||
harq_process->decodeResult,
|
||||
A,
|
||||
A / 8,
|
||||
G,
|
||||
nb_re_dmrs,
|
||||
dmrs_length,
|
||||
dlsch->dlsch_config.mcs,
|
||||
dlsch->Nl,
|
||||
nb_symb_sch,
|
||||
nb_rb,
|
||||
dlsch->dlsch_config.qamModOrder,
|
||||
Coderate);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_COMBINE_SEG, VCD_FUNCTION_OUT);
|
||||
ret = dlsch->last_iteration_cnt;
|
||||
return(ret);
|
||||
return dlsch[0].last_iteration_cnt;
|
||||
}
|
||||
|
||||
@@ -65,50 +65,51 @@ void nr_conjch0_mult_ch1(int *ch0,
|
||||
unsigned short nb_rb,
|
||||
unsigned char output_shift0);
|
||||
|
||||
/** \brief This is the top-level entry point for DLSCH decoding in UE. It should be replicated on several
|
||||
threads (on multi-core machines) corresponding to different HARQ processes. The routine first
|
||||
computes the segmentation information, followed by rate dematching and sub-block deinterleaving the of the
|
||||
received LLRs computed by dlsch_demodulation for each transport block segment. It then calls the
|
||||
turbo-decoding algorithm for each segment and stops after either after unsuccesful decoding of at least
|
||||
one segment or correct decoding of all segments. Only the segment CRCs are check for the moment, the
|
||||
overall CRC is ignored. Finally transport block reassembly is performed.
|
||||
@param phy_vars_ue Pointer to ue variables
|
||||
@param proc
|
||||
@param eNB_id
|
||||
@param dlsch_llr Pointer to LLR values computed by dlsch_demodulation
|
||||
@param frame_parms Pointer to frame descriptor
|
||||
@param dlsch Pointer to DLSCH descriptor
|
||||
@param harq_process
|
||||
@param frame Frame number
|
||||
@param nb_symb_sch
|
||||
@param nr_slot_rx Slot number
|
||||
@param harq_pid
|
||||
@param b_size
|
||||
@param b
|
||||
/** \brief This is the alternative top-level entry point for DLSCH decoding in UE.
|
||||
It handles all the HARQ processes in only one call. The routine first
|
||||
computes the segmentation information and then call LDPC decoder on the
|
||||
received LLRs computed by dlsch_demodulation.
|
||||
It stops after either unsuccesful decoding of at least
|
||||
one segment or correct decoding of all segments. Only the segment CRCs are checked for the moment, the
|
||||
overall CRC is ignored. Finally transport block reassembly is performed.
|
||||
@param[in] phy_vars_ue Pointer to ue variables
|
||||
@param[in] proc
|
||||
@param[in] dlsch_llr Pointers to LLR values computed by dlsch_demodulation
|
||||
@param[in] b
|
||||
@param[in] G array of Gs
|
||||
@param[in] nb_dlsch number of active downlink shared channels
|
||||
@param[in] DLSCH_ids array of active downlink shared channels
|
||||
@returns 0 on success, 1 on unsuccessful decoding
|
||||
*/
|
||||
|
||||
uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
int eNB_id,
|
||||
short *dlsch_llr,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
NR_DL_UE_HARQ_t *harq_process,
|
||||
uint32_t frame,
|
||||
uint16_t nb_symb_sch,
|
||||
uint8_t nr_slot_rx,
|
||||
uint8_t harq_pid,
|
||||
int b_size,
|
||||
uint8_t b[b_size],
|
||||
int G);
|
||||
short **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
uint8_t *DLSCH_ids);
|
||||
|
||||
/** \brief This is the alternative top-level entry point for ULSCH encoding in UE.
|
||||
It handles all the HARQ processes in only one call. The routine first
|
||||
computes the segmentation information, followed by LDPC encoding algorithm of the
|
||||
Transport Block.
|
||||
@param[in] phy_vars_ue pointer to ue variables
|
||||
@param[in] ulsch Pointer to ULSCH descriptor
|
||||
@param[in] frame frame index
|
||||
@param[in] slot slot index
|
||||
@param[in] G array of Gs
|
||||
@param[in] nb_ulsch number of uplink shared channels
|
||||
@param[in] ULSCH_ids array of uplink shared channel ids
|
||||
@returns 0 on success, -1 on unsuccessful decoding
|
||||
*/
|
||||
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
NR_DL_FRAME_PARMS* frame_parms,
|
||||
uint8_t harq_pid,
|
||||
uint32_t tb_size,
|
||||
unsigned int G);
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
unsigned int *G,
|
||||
int nb_ulsch,
|
||||
uint8_t *ULSCH_ids);
|
||||
|
||||
/*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
|
||||
@param[in] in Pointer to input bits
|
||||
@@ -125,18 +126,23 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
|
||||
bool uci_on_pusch,
|
||||
uint32_t* out);
|
||||
|
||||
/** \brief Perform the following functionalities:
|
||||
|
||||
/** \brief Alternative entry point to UE uplink shared channels procedures.
|
||||
It handles all the HARQ processes in only one call.
|
||||
Performs the following functionalities:
|
||||
- encoding
|
||||
- scrambling
|
||||
- modulation
|
||||
- transform precoding
|
||||
@param[in] UE pointer to ue variables
|
||||
@param[in] frame frame index
|
||||
@param[in] slot slot index
|
||||
@param[in] phy_data PHY layer informations
|
||||
@param[in] c16_t
|
||||
*/
|
||||
|
||||
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
const unsigned char harq_pid,
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
const int gNB_id,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
c16_t **txdataF);
|
||||
|
||||
|
||||
@@ -104,6 +104,8 @@ typedef struct {
|
||||
uint8_t first_rx;
|
||||
/// DLSCH status flag indicating
|
||||
SCH_status_t status;
|
||||
/// Pointer to the payload (38.212 V15.4.0 section 5.1)
|
||||
uint8_t *b;
|
||||
/// Pointers to transport block segments
|
||||
uint8_t **c;
|
||||
/// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
|
||||
@@ -126,6 +128,8 @@ typedef struct {
|
||||
/// Last index of LLR buffer that contains information.
|
||||
/// Used for computing LDPC decoder R
|
||||
int llrLen;
|
||||
/// Number of segments processed so far
|
||||
uint32_t processedSegments;
|
||||
decode_abort_t abort_decode;
|
||||
} NR_DL_UE_HARQ_t;
|
||||
|
||||
|
||||
@@ -19,16 +19,8 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
|
||||
* \brief Top-level routines for coding the ULSCH transport channel as described in 38.212 V15.4 2018-12
|
||||
* \author Khalid Ahmed
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company Fraunhofer IIS
|
||||
* \email: khalid.ahmed@iis.fraunhofer.de
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
/*! \file PHY/NR_UE_TRANSPORT/nr_ulsch_coding_slot.c
|
||||
*/
|
||||
|
||||
#include "PHY/defs_UE.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
@@ -36,54 +28,68 @@
|
||||
#include "PHY/CODING/coding_extern.h"
|
||||
#include "PHY/CODING/lte_interleaver_inline.h"
|
||||
#include "PHY/CODING/nrLDPC_extern.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
//#define DEBUG_ULSCH_CODING
|
||||
|
||||
int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_ULSCH_t *ulsch,
|
||||
NR_DL_FRAME_PARMS* frame_parms,
|
||||
uint8_t harq_pid,
|
||||
uint32_t tb_size,
|
||||
unsigned int G)
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
unsigned int *G,
|
||||
int nb_ulsch,
|
||||
uint8_t *ULSCH_ids)
|
||||
{
|
||||
start_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS);
|
||||
|
||||
/////////////////////////parameters and variables initialization/////////////////////////
|
||||
|
||||
unsigned int crc = 1;
|
||||
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
|
||||
uint16_t nb_rb = ulsch->pusch_pdu.rb_size;
|
||||
uint32_t A = tb_size << 3;
|
||||
uint32_t r_offset = 0;
|
||||
// target_code_rate is in 0.1 units
|
||||
float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f;
|
||||
encoder_implemparams_t impp = {.n_segments = harq_process->C,
|
||||
.macro_num = 0,
|
||||
.K = harq_process->K,
|
||||
.Kr = harq_process->K,
|
||||
.Zc = harq_process->Z,
|
||||
.BG = harq_process->BG,
|
||||
.F = harq_process->F,
|
||||
.rv = ulsch->pusch_pdu.pusch_data.rv_index,
|
||||
.Qm = ulsch->pusch_pdu.qam_mod_order,
|
||||
.tinput = NULL,
|
||||
.tprep = NULL,
|
||||
.tparity = NULL,
|
||||
.toutput = NULL};
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers);
|
||||
LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, impp.Qm, Coderate);
|
||||
LOG_D(NR_PHY, "harq_pid %d, pusch_data.new_data_indicator %d\n", harq_pid, ulsch->pusch_pdu.pusch_data.new_data_indicator);
|
||||
if (ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
printf("encoding thinks this is a new packet \n");
|
||||
#endif
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t TBs[nb_ulsch];
|
||||
memset(TBs, 0, sizeof(TBs));
|
||||
nrLDPC_slot_encoding_parameters_t slot_parameters = {
|
||||
.frame = frame,
|
||||
.slot = slot,
|
||||
.nb_TBs = nb_ulsch,
|
||||
.threadPool = &get_nrUE_params()->Tpool,
|
||||
.tinput = NULL,
|
||||
.tprep = NULL,
|
||||
.tparity = NULL,
|
||||
.toutput = NULL,
|
||||
.TBs = TBs
|
||||
};
|
||||
|
||||
int max_num_segments = 0;
|
||||
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id];
|
||||
/* Neither harq_pid nor ULSCH_id are unique in the instance
|
||||
* but their combination is.
|
||||
* Since ULSCH_id < 2
|
||||
* then 2 * harq_pid + ULSCH_id is unique.
|
||||
*/
|
||||
TB_parameters->harq_unique_pid = 2 * harq_pid + ULSCH_id;
|
||||
|
||||
/////////////////////////parameters and variables initialization/////////////////////////
|
||||
|
||||
unsigned int crc = 1;
|
||||
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
|
||||
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch->pusch_pdu;
|
||||
uint16_t nb_rb = pusch_pdu->rb_size;
|
||||
uint32_t A = pusch_pdu->pusch_data.tb_size << 3;
|
||||
uint8_t Qm = pusch_pdu->qam_mod_order;
|
||||
// target_code_rate is in 0.1 units
|
||||
float Coderate = (float)pusch_pdu->target_code_rate / 10240.0f;
|
||||
|
||||
LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, pusch_pdu->nrOfLayers);
|
||||
LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G[pusch_id], Qm, Coderate);
|
||||
LOG_D(NR_PHY, "harq_pid %d, pusch_data.new_data_indicator %d\n", harq_pid, pusch_pdu->pusch_data.new_data_indicator);
|
||||
|
||||
///////////////////////// a---->| add CRC |---->b /////////////////////////
|
||||
int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056;
|
||||
|
||||
int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers * 1056;
|
||||
int B;
|
||||
if (A > NR_MAX_PDSCH_TBS) {
|
||||
// Add 24-bit crc (polynomial A) to payload
|
||||
@@ -104,137 +110,90 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
||||
|
||||
///////////////////////// b---->| block segmentation |---->c /////////////////////////
|
||||
|
||||
harq_process->BG = ulsch->pusch_pdu.ldpcBaseGraph;
|
||||
harq_process->BG = pusch_pdu->ldpcBaseGraph;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN);
|
||||
start_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS);
|
||||
impp.Kb = nr_segmentation(harq_process->payload_AB,
|
||||
harq_process->c,
|
||||
B,
|
||||
&harq_process->C,
|
||||
&harq_process->K,
|
||||
&harq_process->Z,
|
||||
&harq_process->F,
|
||||
harq_process->BG);
|
||||
TB_parameters->Kb = nr_segmentation(harq_process->payload_AB,
|
||||
harq_process->c,
|
||||
B,
|
||||
&harq_process->C,
|
||||
&harq_process->K,
|
||||
&harq_process->Z,
|
||||
&harq_process->F,
|
||||
harq_process->BG);
|
||||
TB_parameters->C = harq_process->C;
|
||||
TB_parameters->K = harq_process->K;
|
||||
TB_parameters->Z = harq_process->Z;
|
||||
TB_parameters->F = harq_process->F;
|
||||
TB_parameters->BG = harq_process->BG;
|
||||
if (TB_parameters->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * pusch_pdu->nrOfLayers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", TB_parameters->C, B);
|
||||
return (-1);
|
||||
}
|
||||
stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS);
|
||||
impp.n_segments = harq_process->C;
|
||||
impp.K = harq_process->K;
|
||||
impp.Kr = impp.K;
|
||||
impp.Zc = harq_process->Z;
|
||||
impp.F = harq_process->F;
|
||||
impp.BG = harq_process->BG;
|
||||
if (impp.n_segments > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * ulsch->pusch_pdu.nrOfLayers) {
|
||||
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B);
|
||||
return(-1);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT);
|
||||
max_num_segments = max(max_num_segments, TB_parameters->C);
|
||||
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
uint16_t Kr_bytes;
|
||||
Kr_bytes = impp.Kr >> 3;
|
||||
#endif
|
||||
TB_parameters->nb_rb = nb_rb;
|
||||
TB_parameters->Qm = Qm;
|
||||
TB_parameters->mcs = pusch_pdu->mcs_index;
|
||||
TB_parameters->nb_layers = pusch_pdu->nrOfLayers;
|
||||
TB_parameters->rv_index = pusch_pdu->pusch_data.rv_index;
|
||||
TB_parameters->G = G[pusch_id];
|
||||
TB_parameters->tbslbrm = pusch_pdu->tbslbrm;
|
||||
TB_parameters->A = A;
|
||||
} // pusch_id
|
||||
|
||||
///////////////////////// c---->| LDCP coding |---->d ////////////////////////////////////
|
||||
for (int r = 0; r < impp.n_segments; r++) {
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
printf("Encoder: B %d F %d \n", B, impp.F);
|
||||
printf("start ldpc encoder segment %d/%d\n", r, impp.n_segments);
|
||||
printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]);
|
||||
for (int cnt = 0; cnt < 22 * impp.Zc / 8; cnt++) {
|
||||
printf("%d ", harq_process->c[r][cnt]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
|
||||
}
|
||||
nrLDPC_segment_encoding_parameters_t segments[nb_ulsch][max_num_segments];
|
||||
memset(segments, 0, sizeof(segments));
|
||||
|
||||
if (ldpc_interface_offload.LDPCencoder) {
|
||||
for (int j = 0; j < impp.n_segments; j++) {
|
||||
impp.perCB[j].E_cb = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, j);
|
||||
}
|
||||
start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
|
||||
ldpc_interface_offload.LDPCencoder(harq_process->c, &harq_process->f, &impp);
|
||||
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
|
||||
} else {
|
||||
if (ulsch->pusch_pdu.pusch_data.new_data_indicator) {
|
||||
start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
|
||||
for (int j = 0; j < (impp.n_segments / 8 + 1); j++) {
|
||||
impp.macro_num = j;
|
||||
impp.Kr = impp.K;
|
||||
ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp);
|
||||
}
|
||||
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT);
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
|
||||
uint8_t ULSCH_id = ULSCH_ids[pusch_id];
|
||||
uint8_t harq_pid = ulsch[ULSCH_id].pusch_pdu.pusch_data.harq_process_id;
|
||||
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
write_output("ulsch_enc_input0.m", "enc_in0", &harq_process->c[0][0], Kr_bytes, 1, 4);
|
||||
write_output("ulsch_enc_output0.m", "enc0", &harq_process->d[0][0], (3 * 8 * Kr_bytes) + 12, 1, 4);
|
||||
#endif
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
for (int r = 0; r < impp.n_segments; r++) { // looping over C segments
|
||||
if (impp.F > 0) {
|
||||
for (int k = impp.Kr - impp.F - 2 * impp.Zc; k < impp.Kr - 2 * impp.Zc; k++) {
|
||||
harq_process->d[r][k] = NR_NULL;
|
||||
}
|
||||
}
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id];
|
||||
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
|
||||
TB_parameters->segments = segments[pusch_id];
|
||||
|
||||
LOG_D(PHY,
|
||||
"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb "
|
||||
"%d, "
|
||||
"rvidx %d)...\n",
|
||||
r,
|
||||
G,
|
||||
impp.Kr * 3,
|
||||
impp.Qm,
|
||||
nb_rb,
|
||||
ulsch->pusch_pdu.pusch_data.rv_index);
|
||||
int 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_process->c[r];
|
||||
segment_parameters->E = nr_get_E(TB_parameters->G,
|
||||
TB_parameters->C,
|
||||
TB_parameters->Qm,
|
||||
TB_parameters->nb_layers,
|
||||
r);
|
||||
segment_parameters->output = harq_process->f + r_offset;
|
||||
r_offset += segment_parameters->E;
|
||||
|
||||
///////////////////////// d---->| Rate matching bit selection |---->e /////////////////////////
|
||||
impp.perCB[r].E_cb = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, r);
|
||||
reset_meas(&segment_parameters->ts_interleave);
|
||||
reset_meas(&segment_parameters->ts_rate_match);
|
||||
reset_meas(&segment_parameters->ts_ldpc_encode);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN);
|
||||
start_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_RATE_MATCHING_STATS]);
|
||||
if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm,
|
||||
impp.BG,
|
||||
impp.Zc,
|
||||
harq_process->d[r],
|
||||
harq_process->e + r_offset,
|
||||
impp.n_segments,
|
||||
impp.F,
|
||||
impp.Kr - impp.F - 2 * impp.Zc,
|
||||
impp.rv,
|
||||
impp.perCB[r].E_cb)
|
||||
== -1)
|
||||
return -1;
|
||||
} // TB_parameters->C
|
||||
} // pusch_id
|
||||
|
||||
stop_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_RATE_MATCHING_STATS]);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_OUT);
|
||||
///////////////////////// | LDCP coding | ////////////////////////////////////
|
||||
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
for (int i = 0; i < 16; i++)
|
||||
printf("output ratematching e[%d]= %d r_offset %u\n", i, harq_process->e[i + r_offset], r_offset);
|
||||
#endif
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
|
||||
|
||||
///////////////////////// e---->| Rate matching bit interleaving |---->f /////////////////////////
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_IN);
|
||||
start_meas_nr_ue_phy(ue, ULSCH_INTERLEAVING_STATS);
|
||||
nr_interleaving_ldpc(impp.perCB[r].E_cb, impp.Qm, harq_process->e + r_offset, harq_process->f + r_offset);
|
||||
stop_meas_nr_ue_phy(ue, ULSCH_INTERLEAVING_STATS);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_OUT);
|
||||
#ifdef DEBUG_ULSCH_CODING
|
||||
for (int i = 0; i < 16; i++)
|
||||
printf("output interleaving f[%d]= %d r_offset %u\n", i, harq_process->f[i+r_offset], r_offset);
|
||||
if (r == impp.n_segments - 1)
|
||||
write_output("enc_output.m","enc", harq_process->f, G, 1, 4);
|
||||
#endif
|
||||
r_offset += impp.perCB[r].E_cb;
|
||||
ue->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters);
|
||||
|
||||
for (uint8_t pusch_id = 0; pusch_id < nb_ulsch; pusch_id++) {
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[pusch_id];
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
|
||||
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_INTERLEAVING_STATS], &segment_parameters->ts_interleave);
|
||||
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_RATE_MATCHING_STATS], &segment_parameters->ts_rate_match);
|
||||
merge_meas(&ue->phy_cpu_stats.cpu_time_stats[ULSCH_LDPC_ENCODING_STATS], &segment_parameters->ts_ldpc_encode);
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_OUT);
|
||||
stop_meas_nr_ue_phy(ue, ULSCH_ENCODING_STATS);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -462,65 +462,49 @@ static void map_symbols(const nr_phy_pxsch_params_t p,
|
||||
}
|
||||
|
||||
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
const unsigned char harq_pid,
|
||||
const uint32_t frame,
|
||||
const uint8_t slot,
|
||||
const int gNB_id,
|
||||
nr_phy_data_tx_t *phy_data,
|
||||
c16_t **txdataF)
|
||||
{
|
||||
LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot);
|
||||
|
||||
int l_prime[2];
|
||||
uint8_t nb_dmrs_re_per_rb;
|
||||
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
||||
if (UE->ul_harq_processes[harq_pid].ULstatus != ACTIVE)
|
||||
return;
|
||||
|
||||
int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
|
||||
uint16_t number_dmrs_symbols = 0;
|
||||
start_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
|
||||
|
||||
uint8_t ULSCH_ids[1];
|
||||
unsigned int G[1];
|
||||
uint8_t pusch_id = 0;
|
||||
ULSCH_ids[pusch_id] = 0;
|
||||
LOG_D(PHY, "nr_ue_ulsch_procedures_slot hard_id %d %d.%d prepare for coding\n", harq_pid, frame, slot);
|
||||
|
||||
NR_UE_ULSCH_t *ulsch_ue = &phy_data->ulsch;
|
||||
NR_UL_UE_HARQ_t *harq_process_ul_ue = &UE->ul_harq_processes[harq_pid];
|
||||
const nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch_ue->pusch_pdu;
|
||||
|
||||
uint32_t tb_size = pusch_pdu->pusch_data.tb_size;
|
||||
AssertFatal(pusch_pdu->pusch_uci.harq_ack_bit_length == 0 &&
|
||||
pusch_pdu->pusch_uci.csi_part1_bit_length == 0 &&
|
||||
pusch_pdu->pusch_uci.csi_part2_bit_length == 0,
|
||||
"UCI on PUSCH not supported at PHY\n");
|
||||
uint16_t number_dmrs_symbols = 0;
|
||||
|
||||
int start_symbol = pusch_pdu->start_symbol_index;
|
||||
uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos;
|
||||
uint16_t nb_rb = pusch_pdu->rb_size;
|
||||
uint8_t number_of_symbols = pusch_pdu->nr_of_symbols;
|
||||
uint8_t dmrs_type = pusch_pdu->dmrs_config_type;
|
||||
uint16_t start_rb = pusch_pdu->rb_start;
|
||||
uint16_t nb_rb = pusch_pdu->rb_size;
|
||||
uint8_t Nl = pusch_pdu->nrOfLayers;
|
||||
uint8_t mod_order = pusch_pdu->qam_mod_order;
|
||||
uint16_t rnti = pusch_pdu->rnti;
|
||||
uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb+pusch_pdu->bwp_start)*NR_NB_SC_PER_RB;
|
||||
|
||||
if (start_sc >= frame_parms->ofdm_symbol_size)
|
||||
start_sc -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
ulsch_ue->Nid_cell = frame_parms->Nid_cell;
|
||||
uint8_t dmrs_type = pusch_pdu->dmrs_config_type;
|
||||
uint8_t cdm_grps_no_data = pusch_pdu->num_dmrs_cdm_grps_no_data;
|
||||
uint8_t nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6 : 4) * cdm_grps_no_data;
|
||||
int start_symbol = pusch_pdu->start_symbol_index;
|
||||
uint16_t ul_dmrs_symb_pos = pusch_pdu->ul_dmrs_symb_pos;
|
||||
uint8_t mod_order = pusch_pdu->qam_mod_order;
|
||||
uint8_t Nl = pusch_pdu->nrOfLayers;
|
||||
uint32_t tb_size = pusch_pdu->pusch_data.tb_size;
|
||||
uint16_t rnti = pusch_pdu->rnti;
|
||||
|
||||
for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) {
|
||||
if((ul_dmrs_symb_pos >> i) & 0x01)
|
||||
if ((ul_dmrs_symb_pos >> i) & 0x01)
|
||||
number_dmrs_symbols += 1;
|
||||
}
|
||||
|
||||
nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data;
|
||||
|
||||
LOG_D(PHY,"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",
|
||||
rnti,start_rb,nb_rb,mod_order,Nl,pusch_pdu->Tpmi,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
|
||||
// TbD num_of_mod_symbols is set but never used
|
||||
const uint32_t N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh;
|
||||
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
|
||||
|
||||
/////////////////////////PTRS parameters' initialization/////////////////////////
|
||||
///////////
|
||||
///////////////////////PTRS parameters' initialization///////////////////
|
||||
|
||||
unsigned int K_ptrs = 0, k_RE_ref = 0;
|
||||
uint32_t unav_res = 0;
|
||||
@@ -531,32 +515,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
ulsch_ue->ptrs_symbols = 0;
|
||||
|
||||
set_ptrs_symb_idx(&ulsch_ue->ptrs_symbols,
|
||||
number_of_symbols,
|
||||
start_symbol,
|
||||
L_ptrs,
|
||||
ul_dmrs_symb_pos);
|
||||
set_ptrs_symb_idx(&ulsch_ue->ptrs_symbols, number_of_symbols, start_symbol, L_ptrs, ul_dmrs_symb_pos);
|
||||
int n_ptrs = (nb_rb + K_ptrs - 1) / K_ptrs;
|
||||
int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ulsch_ue->ptrs_symbols,
|
||||
start_symbol,
|
||||
number_of_symbols);
|
||||
int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ulsch_ue->ptrs_symbols, start_symbol, number_of_symbols);
|
||||
unav_res = n_ptrs * ptrsSymbPerSlot;
|
||||
}
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
G[pusch_id] = nr_get_G(nb_rb, number_of_symbols, nb_dmrs_re_per_rb, number_dmrs_symbols, unav_res, mod_order, Nl);
|
||||
|
||||
|
||||
/////////////////////////ULSCH coding/////////////////////////
|
||||
///////////
|
||||
|
||||
unsigned int G = nr_get_G(nb_rb,
|
||||
number_of_symbols,
|
||||
nb_dmrs_re_per_rb,
|
||||
number_dmrs_symbols,
|
||||
unav_res,
|
||||
mod_order,
|
||||
Nl);
|
||||
ws_trace_t tmp = {.nr = true,
|
||||
.direction = DIRECTION_UPLINK,
|
||||
.pdu_buffer = harq_process_ul_ue->payload_AB,
|
||||
@@ -571,19 +537,59 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
.oob_event_value = 0};
|
||||
trace_pdu(&tmp);
|
||||
|
||||
if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1) {
|
||||
/////////////////////////ULSCH coding/////////////////////////
|
||||
|
||||
if (nr_ulsch_encoding(UE, &phy_data->ulsch, frame, slot, G, 1, ULSCH_ids) == -1) {
|
||||
NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
|
||||
harq_process_ulsch->ULstatus = SCH_IDLE;
|
||||
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
|
||||
return;
|
||||
}
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LOG_D(PHY, "nr_ue_ulsch_procedures_slot hard_id %d %d.%d\n", harq_pid, frame, slot);
|
||||
|
||||
int l_prime[2];
|
||||
|
||||
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
||||
|
||||
int N_PRB_oh = 0; // higher layer (RRC) parameter xOverhead in PUSCH-ServingCellConfig
|
||||
|
||||
AssertFatal(pusch_pdu->pusch_uci.harq_ack_bit_length == 0 && pusch_pdu->pusch_uci.csi_part1_bit_length == 0
|
||||
&& pusch_pdu->pusch_uci.csi_part2_bit_length == 0,
|
||||
"UCI on PUSCH not supported at PHY\n");
|
||||
|
||||
uint16_t start_rb = pusch_pdu->rb_start;
|
||||
uint16_t start_sc = frame_parms->first_carrier_offset + (start_rb + pusch_pdu->bwp_start) * NR_NB_SC_PER_RB;
|
||||
|
||||
if (start_sc >= frame_parms->ofdm_symbol_size)
|
||||
start_sc -= frame_parms->ofdm_symbol_size;
|
||||
|
||||
ulsch_ue->Nid_cell = frame_parms->Nid_cell;
|
||||
|
||||
LOG_D(PHY,
|
||||
"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d "
|
||||
"cdmgrpsnodata %d "
|
||||
"num_dmrs %d dmrs_re_per_rb %d\n",
|
||||
rnti,
|
||||
start_rb,
|
||||
nb_rb,
|
||||
mod_order,
|
||||
Nl,
|
||||
pusch_pdu->Tpmi,
|
||||
pusch_pdu->bwp_start,
|
||||
start_sc,
|
||||
start_symbol,
|
||||
number_of_symbols,
|
||||
cdm_grps_no_data,
|
||||
number_dmrs_symbols,
|
||||
nb_dmrs_re_per_rb);
|
||||
// TbD num_of_mod_symbols is set but never used
|
||||
const uint32_t N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh;
|
||||
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime * nb_rb;
|
||||
|
||||
/////////////////////////ULSCH scrambling/////////////////////////
|
||||
///////////
|
||||
|
||||
uint32_t available_bits = G;
|
||||
uint32_t available_bits = G[pusch_id];
|
||||
// +1 because size can be not modulo 4
|
||||
uint32_t scrambled_output[available_bits / (8 * sizeof(uint32_t)) + 1];
|
||||
memset(scrambled_output, 0, sizeof(scrambled_output));
|
||||
@@ -595,13 +601,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
false,
|
||||
scrambled_output);
|
||||
|
||||
/////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////ULSCH modulation/////////////////////////
|
||||
///////////
|
||||
|
||||
int max_num_re = Nl*number_of_symbols*nb_rb*NR_NB_SC_PER_RB;
|
||||
int max_num_re = Nl * number_of_symbols * nb_rb * NR_NB_SC_PER_RB;
|
||||
c16_t d_mod[max_num_re] __attribute__((aligned(16)));
|
||||
|
||||
nr_modulation(scrambled_output, // assume one codeword for the moment
|
||||
@@ -609,23 +611,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
mod_order,
|
||||
(int16_t *)d_mod);
|
||||
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////ULSCH layer mapping/////////////////////////
|
||||
///////////
|
||||
|
||||
const int sz = available_bits / mod_order / Nl;
|
||||
c16_t ulsch_mod[Nl][sz];
|
||||
|
||||
nr_ue_layer_mapping(d_mod, Nl, sz, ulsch_mod);
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////// ULSCH transform precoding ////////////////////////
|
||||
///////////
|
||||
|
||||
l_prime[0] = 0; // single symbol ap 0
|
||||
|
||||
@@ -636,10 +629,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
memset(ulsch_mod_tp, 0, sizeof(ulsch_mod_tp));
|
||||
|
||||
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
||||
|
||||
uint32_t nb_re_pusch=nb_rb * NR_NB_SC_PER_RB;
|
||||
uint32_t nb_re_pusch = nb_rb * NR_NB_SC_PER_RB;
|
||||
uint32_t y_offset = 0;
|
||||
uint16_t num_dmrs_res_per_symbol = nb_rb*(NR_NB_SC_PER_RB/2);
|
||||
uint16_t num_dmrs_res_per_symbol = nb_rb * (NR_NB_SC_PER_RB / 2);
|
||||
|
||||
// Calculate index to dmrs seq array based on number of DMRS Subcarriers on this symbol
|
||||
int index = get_index_for_dmrs_lowpapr_seq(num_dmrs_res_per_symbol);
|
||||
@@ -647,14 +639,16 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
v = pusch_pdu->dfts_ofdm.low_papr_sequence_number;
|
||||
dmrs_seq = dmrs_lowpaprtype1_ul_ref_sig[u][v][index];
|
||||
|
||||
AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n");
|
||||
AssertFatal(index >= 0,
|
||||
"Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs "
|
||||
"cannot be multiple "
|
||||
"of any other primenumber other than 2,3,5\n");
|
||||
AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
|
||||
|
||||
LOG_D(PHY,"Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index);
|
||||
LOG_D(PHY, "Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index);
|
||||
|
||||
for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) {
|
||||
|
||||
if((ul_dmrs_symb_pos >> l) & 0x01)
|
||||
if ((ul_dmrs_symb_pos >> l) & 0x01)
|
||||
/* In the symbol with DMRS no data would be transmitted CDM groups is 2*/
|
||||
continue;
|
||||
|
||||
@@ -662,43 +656,35 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
y_offset = y_offset + nb_re_pusch;
|
||||
|
||||
LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset);
|
||||
LOG_D(PHY, "Transform precoding being done on data- symbol: %d, nb_re_pusch: %d, y_offset: %d\n", l, nb_re_pusch, y_offset);
|
||||
|
||||
#ifdef DEBUG_PUSCH_MAPPING
|
||||
printf("NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n",
|
||||
y_offset, nb_re_pusch, l, nb_rb);
|
||||
printf("NR_ULSCH_UE: y_offset %u\t nb_re_pusch %u \t Symbol %d \t nb_rb %d \n", y_offset, nb_re_pusch, l, nb_rb);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DFT_IDFT
|
||||
int32_t debug_symbols[MAX_NUM_NR_RE] __attribute__ ((aligned(16)));
|
||||
int32_t debug_symbols[MAX_NUM_NR_RE] __attribute__((aligned(16)));
|
||||
int offset = 0;
|
||||
printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits,mod_order);
|
||||
printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits, mod_order);
|
||||
|
||||
for (int ll = 0; ll < (available_bits/mod_order); ll++) {
|
||||
for (int ll = 0; ll < (available_bits / mod_order); ll++) {
|
||||
debug_symbols[ll] = ulsch_ue->ulsch_mod_tp[ll];
|
||||
}
|
||||
|
||||
printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols);
|
||||
for (int ll = 0; ll < (number_of_symbols-number_dmrs_symbols); ll++) {
|
||||
|
||||
printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols, number_dmrs_symbols);
|
||||
for (int ll = 0; ll < (number_of_symbols - number_dmrs_symbols); ll++) {
|
||||
nr_idft(&debug_symbols[offset], nb_re_pusch);
|
||||
offset = offset + nb_re_pusch;
|
||||
}
|
||||
LOG_M("preDFT_all_symbols.m", "UE_preDFT", ulsch_mod[0], number_of_symbols * nb_re_pusch, 1, 1);
|
||||
LOG_M("postDFT_all_symbols.m", "UE_postDFT", ulsch_mod_tp, number_of_symbols * nb_re_pusch, 1, 1);
|
||||
LOG_M("DEBUG_IDFT_SYMBOLS.m","UE_Debug_IDFT", debug_symbols,number_of_symbols*nb_re_pusch,1,1);
|
||||
LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1);
|
||||
LOG_M("DEBUG_IDFT_SYMBOLS.m", "UE_Debug_IDFT", debug_symbols, number_of_symbols * nb_re_pusch, 1, 1);
|
||||
LOG_M("UE_DMRS_SEQ.m", "UE_DMRS_SEQ", dmrs_seq, nb_re_pusch, 1, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
/////////////////////////ULSCH RE mapping/////////////////////////
|
||||
///////////
|
||||
|
||||
const int slot_sz = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot;
|
||||
c16_t tx_precoding[Nl][slot_sz];
|
||||
@@ -748,12 +734,13 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
} // for (nl=0; nl < Nl; nl++)
|
||||
|
||||
/////////////////////////ULSCH precoding/////////////////////////
|
||||
///////////
|
||||
|
||||
/// Layer Precoding and Antenna port mapping
|
||||
// ulsch_mod 0-3 are mapped on antenna ports
|
||||
// The precoding info is supported by nfapi such as num_prgs, prg_size, prgs_list and pm_idx
|
||||
// The same precoding matrix is applied on prg_size RBs, Thus
|
||||
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
|
||||
|
||||
// The Precoding matrix:
|
||||
for (int ap = 0; ap < frame_parms->nb_antennas_tx; ap++) {
|
||||
for (int l = start_symbol; l < start_symbol + number_of_symbols; l++) {
|
||||
@@ -834,8 +821,9 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
NR_UL_UE_HARQ_t *harq_process_ulsch = NULL;
|
||||
harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
|
||||
harq_process_ulsch->ULstatus = SCH_IDLE;
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS);
|
||||
|
||||
}
|
||||
|
||||
uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
#include "impl_defs_nr.h"
|
||||
#include "time_meas.h"
|
||||
#include "PHY/CODING/coding_defs.h"
|
||||
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
||||
#include "PHY/TOOLS/tools_defs.h"
|
||||
#include "common/platform_types.h"
|
||||
#include "NR_UE_TRANSPORT/nr_transport_ue.h"
|
||||
@@ -481,9 +482,10 @@ typedef struct PHY_VARS_NR_UE_s {
|
||||
/// N0 (used for abstraction)
|
||||
double N0;
|
||||
|
||||
/// NR LDPC coding related
|
||||
nrLDPC_coding_interface_t nrLDPC_coding_interface;
|
||||
uint8_t max_ldpc_iterations;
|
||||
|
||||
int ldpc_offload_enable;
|
||||
/// SRS variables
|
||||
nr_srs_info_t *nr_srs_info;
|
||||
|
||||
|
||||
@@ -271,7 +271,6 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
|
||||
{
|
||||
const int slot_tx = proc->nr_slot_tx;
|
||||
const int frame_tx = proc->frame_tx;
|
||||
const int gNB_id = proc->gNB_id;
|
||||
|
||||
AssertFatal(ue->CC_id == 0, "Transmission on secondary CCs is not supported yet\n");
|
||||
|
||||
@@ -288,12 +287,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
|
||||
|
||||
start_meas_nr_ue_phy(ue, PHY_PROC_TX);
|
||||
|
||||
const int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
||||
if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE) {
|
||||
start_meas_nr_ue_phy(ue, PUSCH_PROC_STATS);
|
||||
nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, gNB_id, phy_data, (c16_t **)&txdataF);
|
||||
stop_meas_nr_ue_phy(ue, PUSCH_PROC_STATS);
|
||||
}
|
||||
nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF);
|
||||
|
||||
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF);
|
||||
|
||||
@@ -685,23 +679,22 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls
|
||||
return unav_res;
|
||||
}
|
||||
|
||||
/*! \brief Process the whole DLSCH slot
|
||||
*/
|
||||
static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t *llr[2],
|
||||
int G)
|
||||
{
|
||||
int16_t *llr[2]) {
|
||||
if (dlsch[0].active == false) {
|
||||
LOG_E(PHY, "DLSCH should be active when calling this function\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
int gNB_id = proc->gNB_id;
|
||||
bool dec = false;
|
||||
int harq_pid = dlsch[0].dlsch_config.harq_process_nbr;
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
uint32_t ret = UINT32_MAX, ret1 = UINT32_MAX;
|
||||
uint32_t ret = UINT32_MAX;
|
||||
NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][harq_pid];
|
||||
NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid];
|
||||
uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos);
|
||||
@@ -711,19 +704,21 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
|
||||
uint8_t is_cw0_active = dl_harq0->status;
|
||||
uint8_t is_cw1_active = dl_harq1->status;
|
||||
int nb_dlsch = 0;
|
||||
nb_dlsch += (is_cw0_active == ACTIVE) ? 1 : 0;
|
||||
nb_dlsch += (is_cw1_active == ACTIVE) ? 1 : 0;
|
||||
uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols;
|
||||
uint8_t dmrs_type = dlsch[0].dlsch_config.dmrsConfigType;
|
||||
|
||||
uint8_t nb_re_dmrs;
|
||||
if (dmrs_type==NFAPI_NR_DMRS_TYPE1) {
|
||||
nb_re_dmrs = 6*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
|
||||
}
|
||||
else {
|
||||
nb_re_dmrs = 4*dlsch[0].dlsch_config.n_dmrs_cdm_groups;
|
||||
if (dmrs_type == NFAPI_NR_DMRS_TYPE1) {
|
||||
nb_re_dmrs = 6 * dlsch[0].dlsch_config.n_dmrs_cdm_groups;
|
||||
} else {
|
||||
nb_re_dmrs = 4 * dlsch[0].dlsch_config.n_dmrs_cdm_groups;
|
||||
}
|
||||
|
||||
LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw0_active);
|
||||
LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw1_active);
|
||||
LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW0 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw0_active);
|
||||
LOG_D(PHY, "AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx % 1024, nr_slot_rx, harq_pid, is_cw1_active);
|
||||
|
||||
// exit dlsch procedures as there are no active dlsch
|
||||
if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) {
|
||||
@@ -734,44 +729,43 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
return false;
|
||||
}
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
nr_dlsch_unscrambling(llr[0], G, 0, dlsch[0].dlsch_config.dlDataScramblingId, dlsch[0].rnti);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
int G[2];
|
||||
uint8_t DLSCH_ids[nb_dlsch];
|
||||
int pdsch_id = 0;
|
||||
uint8_t *p_b[2] = {NULL};
|
||||
for (uint8_t DLSCH_id = 0; DLSCH_id < 2; DLSCH_id++) {
|
||||
NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[DLSCH_id][harq_pid];
|
||||
if (dl_harq->status != ACTIVE) continue;
|
||||
|
||||
DLSCH_ids[pdsch_id++] = DLSCH_id;
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[DLSCH_id].dlsch_config;
|
||||
uint32_t unav_res = 0;
|
||||
if (dlsch_config->pduBitmap & 0x1) {
|
||||
uint16_t ptrsSymbPos = 0;
|
||||
set_ptrs_symb_idx(&ptrsSymbPos, dlsch_config->number_symbols, dlsch_config->start_symbol, 1 << dlsch_config->PTRSTimeDensity,
|
||||
dlsch_config->dlDmrsSymbPos);
|
||||
int n_ptrs = (dlsch_config->number_rbs + dlsch_config->PTRSFreqDensity - 1) / dlsch_config->PTRSFreqDensity;
|
||||
int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols);
|
||||
unav_res = n_ptrs * ptrsSymbPerSlot;
|
||||
}
|
||||
unav_res += compute_csi_rm_unav_res(dlsch_config);
|
||||
G[DLSCH_id] = nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[DLSCH_id].Nl);
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
nr_dlsch_unscrambling(llr[DLSCH_id], G[DLSCH_id], 0, dlsch[DLSCH_id].dlsch_config.dlDataScramblingId, dlsch[DLSCH_id].rnti);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
|
||||
p_b[DLSCH_id] = dl_harq->b;
|
||||
}
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
// create memory to store decoder output
|
||||
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated
|
||||
int num_rb = dlsch[0].dlsch_config.number_rbs;
|
||||
if (num_rb != 273) {
|
||||
a_segments = a_segments*num_rb;
|
||||
a_segments = (a_segments/273)+1;
|
||||
}
|
||||
uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
|
||||
__attribute__ ((aligned(32))) uint8_t p_b[dlsch_bytes];
|
||||
ret = nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
|
||||
ret = nr_dlsch_decoding(ue,
|
||||
proc,
|
||||
gNB_id,
|
||||
llr[0],
|
||||
&ue->frame_parms,
|
||||
&dlsch[0],
|
||||
dl_harq0,
|
||||
frame_rx,
|
||||
nb_symb_sch,
|
||||
nr_slot_rx,
|
||||
harq_pid,
|
||||
dlsch_bytes,
|
||||
p_b,
|
||||
G);
|
||||
|
||||
LOG_T(PHY,"dlsch decoding, ret = %d\n", ret);
|
||||
|
||||
|
||||
if(ret<ue->max_ldpc_iterations+1)
|
||||
dec = true;
|
||||
if (ret < ue->max_ldpc_iterations + 1) dec = true;
|
||||
|
||||
int ind_type = -1;
|
||||
switch(dlsch[0].rnti_type) {
|
||||
switch (dlsch[0].rnti_type) {
|
||||
case TYPE_RA_RNTI_:
|
||||
ind_type = FAPI_NR_RX_PDU_TYPE_RAR;
|
||||
break;
|
||||
@@ -790,75 +784,21 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b);
|
||||
nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b[0]);
|
||||
|
||||
LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8);
|
||||
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
if (cpumeas(CPUMEAS_GETSTATE)) {
|
||||
LOG_D(PHY,
|
||||
" --> Unscrambling for CW0 %5.3f\n",
|
||||
" --> Unscrambling %5.3f\n",
|
||||
ue->phy_cpu_stats.cpu_time_stats[DLSCH_UNSCRAMBLING_STATS].p_time / (cpuf * 1000.0));
|
||||
LOG_D(PHY,
|
||||
"AbsSubframe %d.%d --> LDPC Decoding for CW0 %5.3f\n",
|
||||
"AbsSubframe %d.%d --> LDPC Decoding %5.3f\n",
|
||||
frame_rx % 1024,
|
||||
nr_slot_rx,
|
||||
ue->phy_cpu_stats.cpu_time_stats[DLSCH_DECODING_STATS].p_time / (cpuf * 1000.0));
|
||||
}
|
||||
|
||||
if(is_cw1_active) {
|
||||
// start ldpc decode for CW 1
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[1].dlsch_config;
|
||||
uint32_t unav_res = 0;
|
||||
if(dlsch_config->pduBitmap & 0x1) {
|
||||
uint16_t ptrsSymbPos = 0;
|
||||
set_ptrs_symb_idx(&ptrsSymbPos,
|
||||
dlsch_config->number_symbols,
|
||||
dlsch_config->start_symbol,
|
||||
1 << dlsch_config->PTRSTimeDensity,
|
||||
dlsch_config->dlDmrsSymbPos);
|
||||
int n_ptrs = (dlsch_config->number_rbs + dlsch_config->PTRSFreqDensity - 1) / dlsch_config->PTRSFreqDensity;
|
||||
int ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymbPos, dlsch_config->start_symbol, dlsch_config->number_symbols);
|
||||
unav_res = n_ptrs * ptrsSymbPerSlot;
|
||||
}
|
||||
start_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
unav_res += compute_csi_rm_unav_res(dlsch_config);
|
||||
G = nr_get_G(dlsch_config->number_rbs, nb_symb_sch, nb_re_dmrs, dmrs_len, unav_res, dlsch_config->qamModOrder, dlsch[1].Nl);
|
||||
nr_dlsch_unscrambling(llr[1], G, 0, dlsch[1].dlsch_config.dlDataScramblingId, dlsch[1].rnti);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
ret1 = nr_dlsch_decoding(ue,
|
||||
proc,
|
||||
gNB_id,
|
||||
llr[1],
|
||||
&ue->frame_parms,
|
||||
&dlsch[1],
|
||||
dl_harq1,
|
||||
frame_rx,
|
||||
nb_symb_sch,
|
||||
nr_slot_rx,
|
||||
harq_pid,
|
||||
dlsch_bytes,
|
||||
p_b,
|
||||
G);
|
||||
LOG_T(PHY,"CW dlsch decoding, ret1 = %d\n", ret1);
|
||||
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
if (cpumeas(CPUMEAS_GETSTATE)) {
|
||||
LOG_D(PHY,
|
||||
" --> Unscrambling for CW1 %5.3f\n",
|
||||
ue->phy_cpu_stats.cpu_time_stats[DLSCH_UNSCRAMBLING_STATS].p_time / (cpuf * 1000.0));
|
||||
LOG_D(PHY,
|
||||
"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n",
|
||||
frame_rx % 1024,
|
||||
nr_slot_rx,
|
||||
ue->phy_cpu_stats.cpu_time_stats[DLSCH_DECODING_STATS].p_time / (cpuf * 1000.0));
|
||||
}
|
||||
LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS);
|
||||
}
|
||||
|
||||
// send to mac
|
||||
// send to mac
|
||||
if (ue->if_inst && ue->if_inst->dl_indication) {
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
@@ -869,8 +809,18 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]);
|
||||
}
|
||||
|
||||
if (ue->phy_sim_dlsch_b)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b, dlsch_bytes);
|
||||
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS; // number of segments to be allocated
|
||||
int num_rb = dlsch[0].dlsch_config.number_rbs;
|
||||
if (num_rb != 273) {
|
||||
a_segments = a_segments * num_rb;
|
||||
a_segments = (a_segments / 273) + 1;
|
||||
}
|
||||
uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment
|
||||
|
||||
if (ue->phy_sim_dlsch_b && is_cw0_active == ACTIVE)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b[0], dlsch_bytes);
|
||||
else if (ue->phy_sim_dlsch_b && is_cw1_active == ACTIVE)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes);
|
||||
|
||||
return dec;
|
||||
}
|
||||
@@ -1144,8 +1094,9 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_PROCEDURES_STATS);
|
||||
|
||||
if (ret_pdsch >= 0)
|
||||
nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G);
|
||||
if (ret_pdsch >= 0) {
|
||||
nr_ue_dlsch_procedures(ue, proc, dlsch, llr);
|
||||
}
|
||||
else {
|
||||
LOG_E(NR_PHY, "Demodulation impossible, internal error\n");
|
||||
int ack_nack_slot = (proc->nr_slot_rx + dlsch_config->k1_feedback) % ue->frame_parms.slots_per_frame;
|
||||
|
||||
Reference in New Issue
Block a user