Commit 80c40669 authored by Yi-Hung Chang's avatar Yi-Hung Chang Committed by Romain Beurdouche

feat(nrLDPC_coding_interface): Use reworked interface in UE

parent 00e1ad12
......@@ -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;
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);
bool decodeSuccess = (rdata->decodeIterations < (1+dlsch->max_ldpc_iterations));
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
};
int max_num_segments = 0;
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];
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
uint8_t nb_re_dmrs;
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;
}
if (decodeSuccess) {
memcpy(b+rdata->offset,
harq_process->c[r],
rdata->Kr_bytes - (harq_process->F>>3) -((harq_process->C>1)?3:0));
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);
(*num_seg_ok)++;
} else {
LOG_D(PHY, "DLSCH %d in error\n", rdata->dlsch_id);
}
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 (!last)
return false; // continue decoding
// 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;
harq_process->decodeResult = *num_seg_ok == 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, 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;
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);
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) {
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_SEGMENTATION, VCD_FUNCTION_OUT);
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
}
if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD))
LOG_I(PHY, "Segmentation: C %d, K %d\n", harq_process->C, harq_process->K);
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;
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);
}
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]);
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));
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];
TB_parameters->segments = segments[pdsch_id];
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;
}
//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);
}
int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
// 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;
if (ret_decoder != 0) {
return dlsch->max_ldpc_iterations + 1;
}
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);
// 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);
//NR_DL_UE_HARQ_t *harq_process = dlsch->harq_processes[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);
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);
}
kpiStructure.nb_total++;
kpiStructure.blockSize = dlsch_config->TBS;
kpiStructure.dl_mcs = dlsch_config->mcs;
kpiStructure.nofRBs = dlsch_config->number_rbs;
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);
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,
" 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 (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));
}
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_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 (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 (nb_rb != 273) {
a_segments = a_segments*nb_rb;
a_segments = a_segments/273 +1;
}
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);
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);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN);
/////////////////////////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};
/////////////////////////////////////////////////////////////////////////////////////////
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);
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
///////////////////////// 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);
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);
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);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT);
#ifdef DEBUG_ULSCH_CODING
uint16_t Kr_bytes;
Kr_bytes = impp.Kr >> 3;
#endif
///////////////////////// 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
max_num_segments = max(max_num_segments, TB_parameters->C);
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
nrLDPC_segment_encoding_parameters_t segments[nb_ulsch][max_num_segments];
memset(segments, 0, sizeof(segments));
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];
NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid];
TB_parameters->segments = segments[pusch_id];
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;
reset_meas(&segment_parameters->ts_interleave);
reset_meas(&segment_parameters->ts_rate_match);
reset_meas(&segment_parameters->ts_ldpc_encode);
} // TB_parameters->C
} // pusch_id
///////////////////////// | LDCP coding | ////////////////////////////////////
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
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_IN);
}
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);
#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;
}
}
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);
///////////////////////// 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);
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;
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);
#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
///////////////////////// 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;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
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;
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;
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;
}
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,
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;
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
ret = nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids);
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
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;
......
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