restructuring of UE DLSCH code to handle 2 codewords
even if 2 codewords are currently not supported and not tested, the way UE handled the possibility of having 2 codewords was messy, in between support and non-support the intention of this MR is to cleanup the code more than extend the support Signed-off-by: Francesco Mani <email@francescomani.it>
This commit is contained in:
+2
-2
@@ -558,8 +558,8 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE,
|
||||
if (phy_data->dlsch[0].active
|
||||
&& (phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_ || phy_data->dlsch[0].rnti_type == TYPE_RA_RNTI_)) {
|
||||
// indicate to tx thread to wait for DLSCH decoding
|
||||
if (phy_data->dlsch[0].dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH
|
||||
const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % fp->slots_per_frame;
|
||||
if (phy_data->dlsch_config.k1_feedback) { // if feedback is 0 there is no HARQ associated with this DLSCH
|
||||
const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch_config.k1_feedback) % fp->slots_per_frame;
|
||||
tx_wait_for_dlsch[ack_nack_slot]++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
uint8_t harq_pid;
|
||||
uint8_t cw_idx;
|
||||
uint8_t ack_nack;
|
||||
uint32_t pdu_length;
|
||||
uint8_t* pdu;
|
||||
@@ -466,6 +467,17 @@ typedef struct {
|
||||
|
||||
typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t mcs;
|
||||
bool new_data_indicator;
|
||||
uint8_t rv;
|
||||
uint16_t targetCodeRate;
|
||||
uint8_t qamModOrder;
|
||||
uint32_t TBS;
|
||||
uint8_t ldpcBaseGraph;
|
||||
uint8_t Nl;
|
||||
} fapi_nr_dl_cw_info_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t BWPSize;
|
||||
uint16_t BWPStart;
|
||||
@@ -482,15 +494,8 @@ typedef struct {
|
||||
uint8_t prb_bundling_size_ind;
|
||||
uint8_t rate_matching_ind;
|
||||
uint8_t zp_csi_rs_trigger;
|
||||
uint8_t mcs;
|
||||
bool new_data_indicator;
|
||||
uint8_t rv;
|
||||
uint16_t targetCodeRate;
|
||||
uint8_t qamModOrder;
|
||||
uint32_t TBS;
|
||||
uint8_t tb2_mcs;
|
||||
bool tb2_new_data_indicator;
|
||||
uint8_t tb2_rv;
|
||||
uint8_t n_codewords;
|
||||
fapi_nr_dl_cw_info_t cw_info[2];
|
||||
uint8_t harq_process_nbr;
|
||||
vrb_to_prb_mapping_t vrb_to_prb_mapping;
|
||||
uint8_t dai;
|
||||
@@ -523,7 +528,6 @@ typedef struct {
|
||||
uint16_t dlDataScramblingId;
|
||||
uint16_t pduBitmap;
|
||||
uint32_t k1_feedback;
|
||||
uint8_t ldpcBaseGraph;
|
||||
uint8_t numCsiRsForRateMatching;
|
||||
fapi_nr_dl_config_csirs_pdu_rel15_t csiRsForRateMatching[NFAPI_MAX_NUM_CSI_RATEMATCH];
|
||||
} fapi_nr_dl_config_dlsch_pdu_rel15_t;
|
||||
|
||||
@@ -1374,127 +1374,94 @@ void nr_pdsch_ptrs_processing(int nbRx,
|
||||
int nl,
|
||||
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
NR_DL_UE_HARQ_t *dlsch0_harq,
|
||||
NR_DL_UE_HARQ_t *dlsch1_harq,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
|
||||
uint8_t nr_slot_rx,
|
||||
unsigned char symbol,
|
||||
int nb_rb,
|
||||
uint16_t rnti,
|
||||
NR_UE_DLSCH_t dlsch[2])
|
||||
uint16_t *ptrsSymbPos,
|
||||
uint8_t *ptrsSymbIdx)
|
||||
{
|
||||
//#define DEBUG_DL_PTRS 1
|
||||
int32_t *ptrs_re_symbol = NULL;
|
||||
int8_t ret = 0;
|
||||
/* harq specific variables */
|
||||
uint8_t symbInSlot = 0;
|
||||
uint16_t *startSymbIndex = NULL;
|
||||
uint16_t *nbSymb = NULL;
|
||||
uint8_t *L_ptrs = NULL;
|
||||
uint8_t *K_ptrs = NULL;
|
||||
uint16_t *dmrsSymbPos = NULL;
|
||||
uint16_t *ptrsSymbPos = NULL;
|
||||
uint8_t *ptrsSymbIdx = NULL;
|
||||
uint8_t *ptrsReOffset = NULL;
|
||||
int nscid = 0;
|
||||
int symbInSlot = dlsch_config->start_symbol + dlsch_config->number_symbols;
|
||||
int startSymbIndex = dlsch_config->start_symbol;
|
||||
int nbSymb = dlsch_config->number_symbols;
|
||||
int L_ptrs = dlsch_config->PTRSTimeDensity;
|
||||
int K_ptrs = dlsch_config->PTRSFreqDensity;
|
||||
int dmrsSymbPos = dlsch_config->dlDmrsSymbPos;
|
||||
int ptrsReOffset = dlsch_config->PTRSReOffset;
|
||||
int nscid = dlsch_config->nscid;
|
||||
|
||||
if(dlsch0_harq->status == NR_ACTIVE) {
|
||||
symbInSlot = dlsch[0].dlsch_config.start_symbol + dlsch[0].dlsch_config.number_symbols;
|
||||
startSymbIndex = &dlsch[0].dlsch_config.start_symbol;
|
||||
nbSymb = &dlsch[0].dlsch_config.number_symbols;
|
||||
L_ptrs = &dlsch[0].dlsch_config.PTRSTimeDensity;
|
||||
K_ptrs = &dlsch[0].dlsch_config.PTRSFreqDensity;
|
||||
dmrsSymbPos = &dlsch[0].dlsch_config.dlDmrsSymbPos;
|
||||
ptrsReOffset = &dlsch[0].dlsch_config.PTRSReOffset;
|
||||
ptrsSymbPos = &dlsch[0].ptrs_symbols;
|
||||
ptrsSymbIdx = &dlsch[0].ptrs_symbol_index;
|
||||
nscid = dlsch[0].dlsch_config.nscid;
|
||||
}
|
||||
if(dlsch1_harq) {
|
||||
symbInSlot = dlsch[1].dlsch_config.start_symbol + dlsch[1].dlsch_config.number_symbols;
|
||||
startSymbIndex = &dlsch[1].dlsch_config.start_symbol;
|
||||
nbSymb = &dlsch[1].dlsch_config.number_symbols;
|
||||
L_ptrs = &dlsch[1].dlsch_config.PTRSTimeDensity;
|
||||
K_ptrs = &dlsch[1].dlsch_config.PTRSFreqDensity;
|
||||
dmrsSymbPos = &dlsch[1].dlsch_config.dlDmrsSymbPos;
|
||||
ptrsReOffset = &dlsch[1].dlsch_config.PTRSReOffset;
|
||||
ptrsSymbPos = &dlsch[1].ptrs_symbols;
|
||||
ptrsSymbIdx = &dlsch[1].ptrs_symbol_index;
|
||||
nscid = dlsch[1].dlsch_config.nscid;
|
||||
}
|
||||
/* loop over antennas */
|
||||
for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
|
||||
c16_t *phase_per_symbol = (c16_t*)ptrs_phase_per_slot[aarx];
|
||||
ptrs_re_symbol = (int32_t*)ptrs_re_per_slot[aarx];
|
||||
ptrs_re_symbol[symbol] = 0;
|
||||
phase_per_symbol[symbol].i = 0; // Imag
|
||||
/* set DMRS estimates to 0 angle with magnitude 1 */
|
||||
if(is_dmrs_symbol(symbol,*dmrsSymbPos)) {
|
||||
if(is_dmrs_symbol(symbol, dmrsSymbPos)) {
|
||||
/* set DMRS real estimation to 32767 */
|
||||
phase_per_symbol[symbol].r=INT16_MAX; // 32767
|
||||
#ifdef DEBUG_DL_PTRS
|
||||
printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i);
|
||||
#endif
|
||||
}
|
||||
else { // real ptrs value is set to 0
|
||||
} else { // real ptrs value is set to 0
|
||||
phase_per_symbol[symbol].r = 0; // Real
|
||||
}
|
||||
|
||||
if(dlsch0_harq->status == NR_ACTIVE) {
|
||||
if(symbol == *startSymbIndex) {
|
||||
*ptrsSymbPos = 0;
|
||||
set_ptrs_symb_idx(ptrsSymbPos,
|
||||
*nbSymb,
|
||||
*startSymbIndex,
|
||||
1<< *L_ptrs,
|
||||
*dmrsSymbPos);
|
||||
}
|
||||
/* if not PTRS symbol set current ptrs symbol index to zero*/
|
||||
*ptrsSymbIdx = 0;
|
||||
/* Check if current symbol contains PTRS */
|
||||
if(is_ptrs_symbol(symbol, *ptrsSymbPos)) {
|
||||
*ptrsSymbIdx = symbol;
|
||||
/*------------------------------------------------------------------------------------------------------- */
|
||||
/* 1) Estimate common phase error per PTRS symbol */
|
||||
/*------------------------------------------------------------------------------------------------------- */
|
||||
const uint32_t *gold =
|
||||
if (symbol == startSymbIndex) {
|
||||
*ptrsSymbPos = 0;
|
||||
set_ptrs_symb_idx(ptrsSymbPos, nbSymb, startSymbIndex, 1 << L_ptrs, dmrsSymbPos);
|
||||
}
|
||||
/* if not PTRS symbol set current ptrs symbol index to zero*/
|
||||
*ptrsSymbIdx = 0;
|
||||
/* Check if current symbol contains PTRS */
|
||||
if (is_ptrs_symbol(symbol, *ptrsSymbPos)) {
|
||||
*ptrsSymbIdx = symbol;
|
||||
/*------------------------------------------------------------------------------------------------------- */
|
||||
/* 1) Estimate common phase error per PTRS symbol */
|
||||
/*------------------------------------------------------------------------------------------------------- */
|
||||
const uint32_t *gold =
|
||||
nr_gold_pdsch(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, frame_parms->Nid_cell, nscid, nr_slot_rx, symbol);
|
||||
nr_ptrs_cpe_estimation(*K_ptrs,
|
||||
*ptrsReOffset,
|
||||
nb_rb,
|
||||
rnti,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
rxdataF_comp[symbol][0][aarx],
|
||||
gold,
|
||||
(int16_t *)&phase_per_symbol[symbol],
|
||||
&ptrs_re_symbol[symbol]);
|
||||
}
|
||||
}// HARQ 0
|
||||
nr_ptrs_cpe_estimation(K_ptrs,
|
||||
ptrsReOffset,
|
||||
nb_rb,
|
||||
rnti,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
rxdataF_comp[symbol][0][aarx],
|
||||
gold,
|
||||
(int16_t *)&phase_per_symbol[symbol],
|
||||
&ptrs_re_symbol[symbol]);
|
||||
}
|
||||
|
||||
/* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
|
||||
if(symbol == (symbInSlot -1)) {
|
||||
if (symbol == (symbInSlot -1)) {
|
||||
/*------------------------------------------------------------------------------------------------------- */
|
||||
/* 2) Interpolate PTRS estimated value in TD */
|
||||
/*------------------------------------------------------------------------------------------------------- */
|
||||
/* If L-PTRS is > 0 then we need interpolation */
|
||||
if(*L_ptrs > 0) {
|
||||
ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, *startSymbIndex, *nbSymb);
|
||||
if (L_ptrs > 0) {
|
||||
ret = nr_ptrs_process_slot(dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, startSymbIndex, nbSymb);
|
||||
if(ret != 0) {
|
||||
LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_DL_PTRS
|
||||
LOG_M("ptrsEst.m","est",ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
|
||||
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + (*startSymbIndex) * rx_size_symbol, rx_size_symbol * (*nbSymb), 1, 1);
|
||||
LOG_M("ptrsEst.m","est", ptrs_phase_per_slot[aarx], frame_parms->symbols_per_slot, 1, 1);
|
||||
LOG_M("rxdataF_bf_ptrs_comp.m", "bf_ptrs_cmp", rxdataF_comp[0][aarx] + startSymbIndex * rx_size_symbol, rx_size_symbol * nbSymb, 1, 1);
|
||||
#endif
|
||||
/*------------------------------------------------------------------------------------------------------- */
|
||||
/* 3) Compensated DMRS based estimated signal with PTRS estimation */
|
||||
/*--------------------------------------------------------------------------------------------------------*/
|
||||
for(uint8_t i = *startSymbIndex; i < symbInSlot; i++) {
|
||||
for(uint8_t i = startSymbIndex; i < symbInSlot; i++) {
|
||||
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
|
||||
/* Skip rotation if the slot processing is wrong */
|
||||
if((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) {
|
||||
if((!is_dmrs_symbol(i, dmrsSymbPos)) && (ret == 0)) {
|
||||
#ifdef DEBUG_DL_PTRS
|
||||
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i);
|
||||
printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i);
|
||||
#endif
|
||||
rotate_cpx_vector(rxdataF_comp[i][0][aarx], &phase_per_symbol[i], rxdataF_comp[i][0][aarx], nb_rb * NR_NB_SC_PER_RB, 15);
|
||||
}// if not DMRS Symbol
|
||||
|
||||
@@ -126,13 +126,13 @@ void nr_pdsch_ptrs_processing(int nbRx,
|
||||
int nl,
|
||||
c16_t rxdataF_comp[][nl][nbRx][rx_size_symbol],
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
NR_DL_UE_HARQ_t *dlsch0_harq,
|
||||
NR_DL_UE_HARQ_t *dlsch1_harq,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
|
||||
uint8_t nr_slot_rx,
|
||||
unsigned char symbol,
|
||||
int nb_rb,
|
||||
uint16_t rnti,
|
||||
NR_UE_DLSCH_t dlsch[2]);
|
||||
uint16_t *ptrsSymbPos,
|
||||
uint8_t *ptrsSymbIdx);
|
||||
|
||||
int nr_sl_psbch_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
sl_nr_ue_phy_params_t *sl_phy_params,
|
||||
|
||||
@@ -170,7 +170,7 @@ static void send_ssb_rsrp_meas(PHY_VARS_NR_UE *ue,
|
||||
nr_downlink_indication_t dl_indication = {0};
|
||||
fapi_nr_rx_indication_t rx_ind = {0};
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, &l1_measurements, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, &l1_measurements, NULL);
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
|
||||
|
||||
@@ -961,6 +961,6 @@ void nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue,
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t rx_ind = {0};
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, NULL, NULL, 1, proc, (void *)&l1_measurements, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_MEAS_IND, ue, 0, 0, NULL, 1, proc, (void *)&l1_measurements, NULL);
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
|
||||
@@ -43,178 +43,143 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid,
|
||||
void 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,
|
||||
int cw_idx,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
|
||||
int16_t *dlsch_llr,
|
||||
uint8_t *b,
|
||||
int number_rbs,
|
||||
uint8_t *DLSCH_ids)
|
||||
int G)
|
||||
{
|
||||
nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch];
|
||||
memset(TBs, 0, sizeof(TBs));
|
||||
nrLDPC_TB_decoding_parameters_t TB_parameters = {0};
|
||||
nrLDPC_slot_decoding_parameters_t slot_parameters = {
|
||||
.frame = proc->frame_rx,
|
||||
.slot = proc->nr_slot_rx,
|
||||
.nb_TBs = nb_dlsch,
|
||||
.nb_TBs = 1,
|
||||
.threadPool = &get_nrUE_params()->Tpool,
|
||||
.TBs = TBs
|
||||
.TBs = &TB_parameters
|
||||
};
|
||||
|
||||
int max_num_segments = 0;
|
||||
uint8_t dmrs_Type = dlsch_config->dmrsConfigType;
|
||||
int harq_pid = dlsch_config->harq_process_nbr;
|
||||
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
|
||||
fapi_nr_dl_cw_info_t *cw_info = &dlsch->cw_info;
|
||||
NR_DL_UE_HARQ_t *harq_process = &phy_vars_ue->dl_harq_processes[cw_idx][dlsch_config->harq_process_nbr];
|
||||
LOG_D(PHY, "Round %d RV idx %d\n", harq_process->DLround, cw_info->rv);
|
||||
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);
|
||||
|
||||
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];
|
||||
TB_parameters.harq_unique_pid = 2 * harq_pid + cw_idx;
|
||||
TB_parameters.G = G;
|
||||
TB_parameters.nb_rb = number_rbs;
|
||||
TB_parameters.Qm = cw_info->qamModOrder;
|
||||
TB_parameters.mcs = cw_info->mcs;
|
||||
TB_parameters.nb_layers = cw_info->Nl;
|
||||
TB_parameters.BG = cw_info->ldpcBaseGraph;
|
||||
TB_parameters.A = cw_info->TBS;
|
||||
TB_parameters.processedSegments = &harq_process->processedSegments;
|
||||
|
||||
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
|
||||
uint8_t nb_re_dmrs;
|
||||
float Coderate = (float)cw_info->targetCodeRate / 10240.0f;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 = 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,
|
||||
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,
|
||||
cw_idx,
|
||||
harq_pid,
|
||||
dlsch_config->TBS,
|
||||
TB_parameters->G,
|
||||
cw_info->TBS,
|
||||
G,
|
||||
nb_re_dmrs,
|
||||
dmrs_length,
|
||||
TB_parameters->mcs,
|
||||
TB_parameters->nb_layers,
|
||||
TB_parameters.mcs,
|
||||
TB_parameters.nb_layers,
|
||||
dlsch_config->number_symbols,
|
||||
TB_parameters->nb_rb,
|
||||
TB_parameters->Qm,
|
||||
TB_parameters.nb_rb,
|
||||
TB_parameters.Qm,
|
||||
Coderate);
|
||||
|
||||
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->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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
max_num_segments = max(max_num_segments, TB_parameters->C);
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
nrLDPC_segment_decoding_parameters_t segments[nb_dlsch][max_num_segments];
|
||||
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->max_ldpc_iterations;
|
||||
TB_parameters.rv_index = cw_info->rv;
|
||||
TB_parameters.tbslbrm = dlsch_config->tbslbrm;
|
||||
TB_parameters.abort_decode = &harq_process->abort_decode;
|
||||
set_abort(&harq_process->abort_decode, false);
|
||||
|
||||
nrLDPC_segment_decoding_parameters_t segments[TB_parameters.C];
|
||||
memset(segments, 0, sizeof(segments));
|
||||
bool d_to_be_cleared[nb_dlsch][max_num_segments];
|
||||
bool d_to_be_cleared[TB_parameters.C];
|
||||
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];
|
||||
TB_parameters.segments = segments;
|
||||
|
||||
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[r] = true;
|
||||
else
|
||||
d_to_be_cleared[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 + r_offset;
|
||||
segment_parameters->d = harq_process->d[r];
|
||||
segment_parameters->d_to_be_cleared = &d_to_be_cleared[r];
|
||||
segment_parameters->c = harq_process->c[r];
|
||||
segment_parameters->decodeSuccess = 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);
|
||||
|
||||
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;
|
||||
}
|
||||
r_offset += segment_parameters->E;
|
||||
}
|
||||
|
||||
int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters);
|
||||
@@ -224,114 +189,90 @@ void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 = 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,
|
||||
" 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) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (harq_process->decodeResult) {
|
||||
LOG_D(PHY, "DLSCH received ok \n");
|
||||
harq_process->status = NR_SCH_IDLE;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
|
||||
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 + offset, harq_process->c[r], (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0));
|
||||
} else {
|
||||
LOG_D(PHY, "DLSCH received nok \n");
|
||||
kpiStructure.nb_nack++;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
|
||||
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
|
||||
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, cw_info->rv);
|
||||
LOG_D(PHY, "downlink segment error %d/%d\n", r, harq_process->C);
|
||||
}
|
||||
offset += (harq_process->K >> 3) - (harq_process->F >> 3) - ((harq_process->C > 1) ? 3 : 0);
|
||||
|
||||
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,
|
||||
number_rbs,
|
||||
dlsch_config->qamModOrder,
|
||||
Coderate);
|
||||
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 = cw_info->TBS;
|
||||
kpiStructure.dl_mcs = cw_info->mcs;
|
||||
kpiStructure.nofRBs = number_rbs;
|
||||
|
||||
harq_process->decodeResult = harq_process->processedSegments == harq_process->C;
|
||||
|
||||
if (harq_process->decodeResult && harq_process->C > 1) {
|
||||
/* check global CRC */
|
||||
// we have regrouped the transport block
|
||||
if (!check_crc(b, lenWithCrc(1, cw_info->TBS), crcType(1, cw_info->TBS))) {
|
||||
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 (harq_process->decodeResult) {
|
||||
// We search only a reccuring OAI error that propagates all 0 packets with a 0 CRC, so we
|
||||
const int sz = cw_info->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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (harq_process->decodeResult) {
|
||||
LOG_D(PHY, "DLSCH received ok \n");
|
||||
harq_process->status = NR_SCH_IDLE;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1;
|
||||
} else {
|
||||
LOG_D(PHY, "DLSCH received nok \n");
|
||||
kpiStructure.nb_nack++;
|
||||
dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations;
|
||||
UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK");
|
||||
}
|
||||
|
||||
LOG_D(PHY,
|
||||
"%d.%d DLSCH Decoded, harq_pid %d, cw_idx %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,
|
||||
cw_idx,
|
||||
harq_process->DLround,
|
||||
harq_process->decodeResult,
|
||||
cw_info->TBS,
|
||||
cw_info->TBS / 8,
|
||||
G,
|
||||
nb_re_dmrs,
|
||||
dmrs_length,
|
||||
cw_info->mcs,
|
||||
cw_info->Nl,
|
||||
dlsch_config->number_symbols,
|
||||
number_rbs,
|
||||
cw_info->qamModOrder,
|
||||
Coderate);
|
||||
}
|
||||
|
||||
@@ -856,12 +856,12 @@ static void nr_dlsch_layer_demapping(const uint8_t Nl,
|
||||
const uint8_t mod_order,
|
||||
const int llrLayerSize,
|
||||
const int16_t llr_layers[NR_SYMBOLS_PER_SLOT][Nl][llrLayerSize],
|
||||
const NR_UE_DLSCH_t *dlsch,
|
||||
const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
|
||||
const uint32_t re_len[NR_SYMBOLS_PER_SLOT],
|
||||
int16_t *llr)
|
||||
{
|
||||
const int s0 = dlsch->dlsch_config.start_symbol;
|
||||
const int s1 = dlsch->dlsch_config.number_symbols;
|
||||
const int s0 = dlsch_config->start_symbol;
|
||||
const int s1 = dlsch_config->number_symbols;
|
||||
|
||||
int k = 0;
|
||||
switch (Nl) {
|
||||
@@ -901,28 +901,28 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch,
|
||||
const c16_t dl_ch_magb[rx_size_symbol],
|
||||
const c16_t dl_ch_magr[rx_size_symbol],
|
||||
const int nb_antennas_rx,
|
||||
const c16_t rxdataF_comp[dlsch->Nl][nb_antennas_rx][rx_size_symbol],
|
||||
const c16_t rxdataF_comp[dlsch->cw_info.Nl][nb_antennas_rx][rx_size_symbol],
|
||||
const int llrSize,
|
||||
int16_t layer_llr[dlsch->Nl][llrSize])
|
||||
int16_t layer_llr[dlsch->cw_info.Nl][llrSize])
|
||||
{
|
||||
switch (dlsch->dlsch_config.qamModOrder) {
|
||||
switch (dlsch->cw_info.qamModOrder) {
|
||||
case 2 :
|
||||
for (int l = 0; l < dlsch[0].Nl; l++)
|
||||
for (int l = 0; l < dlsch->cw_info.Nl; l++)
|
||||
nr_qpsk_llr(rxdataF_comp[l][0], layer_llr[l], len);
|
||||
break;
|
||||
|
||||
case 4 :
|
||||
for (int l = 0; l < dlsch[0].Nl; l++)
|
||||
for (int l = 0; l < dlsch->cw_info.Nl; l++)
|
||||
nr_16qam_llr(rxdataF_comp[l][0], dl_ch_mag, layer_llr[l], len);
|
||||
break;
|
||||
|
||||
case 6 :
|
||||
for(int l=0; l < dlsch[0].Nl; l++)
|
||||
for(int l=0; l < dlsch->cw_info.Nl; l++)
|
||||
nr_64qam_llr(rxdataF_comp[l][0], dl_ch_mag, dl_ch_magb, layer_llr[l], len);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
for(int l=0; l < dlsch[0].Nl; l++)
|
||||
for(int l=0; l < dlsch->cw_info.Nl; l++)
|
||||
nr_256qam_llr(rxdataF_comp[l][0],
|
||||
dl_ch_mag,
|
||||
dl_ch_magb,
|
||||
@@ -943,23 +943,25 @@ static int nr_dlsch_llr(const NR_UE_DLSCH_t *dlsch,
|
||||
/* Main Function */
|
||||
int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
const freq_alloc_bitmap_t *freq_alloc,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
|
||||
NR_DL_UE_HARQ_t *dlsch_harq,
|
||||
unsigned char symbol,
|
||||
bool first_symbol_flag,
|
||||
unsigned char harq_pid,
|
||||
uint32_t pdsch_est_size,
|
||||
int32_t dl_ch_estimates[][pdsch_est_size],
|
||||
int16_t *llr[2],
|
||||
int16_t *llr,
|
||||
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int32_t *log2_maxh,
|
||||
int rx_size_symbol,
|
||||
int nbRx,
|
||||
c16_t rxdataF_comp[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_mag[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magb[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magr[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
|
||||
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
|
||||
int G,
|
||||
@@ -967,7 +969,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
pdsch_scope_req_t *scope_req)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
const int nl = dlsch[0].Nl;
|
||||
const int nl = dlsch->cw_info.Nl;
|
||||
const int n_rx = fp->nb_antennas_rx;
|
||||
const int matrixSz = n_rx * nl;
|
||||
__attribute__((aligned(32))) int32_t dl_ch_estimates_ext[matrixSz][rx_size_symbol];
|
||||
@@ -979,72 +981,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
const int gNB_id = proc->gNB_id;
|
||||
uint8_t slot = 0;
|
||||
|
||||
int32_t codeword_TB0 = -1;
|
||||
int32_t codeword_TB1 = -1;
|
||||
|
||||
uint32_t nb_re_pdsch = -1;
|
||||
|
||||
NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL;
|
||||
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
|
||||
if (NR_MAX_NB_LAYERS>4)
|
||||
dlsch1_harq = &ue->dl_harq_processes[1][harq_pid];
|
||||
|
||||
if (dlsch0_harq && dlsch1_harq){
|
||||
|
||||
LOG_D(PHY,
|
||||
"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n",
|
||||
frame,
|
||||
nr_slot_rx,
|
||||
symbol,
|
||||
harq_pid,
|
||||
dlsch0_harq->status,
|
||||
dlsch1_harq->status);
|
||||
|
||||
if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){
|
||||
codeword_TB0 = dlsch0_harq->codeword; // SV: where is this set? revisit for DL MIMO.
|
||||
codeword_TB1 = dlsch1_harq->codeword;
|
||||
dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid];
|
||||
dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid];
|
||||
|
||||
DEBUG_HARQ("[DEMOD] I am assuming both TBs are active, in cw0 %d and cw1 %d \n", codeword_TB0, codeword_TB1);
|
||||
|
||||
} else if ((dlsch0_harq->status == NR_ACTIVE) && (dlsch1_harq->status != NR_ACTIVE) ) {
|
||||
codeword_TB0 = dlsch0_harq->codeword;
|
||||
dlsch0_harq = &ue->dl_harq_processes[codeword_TB0][harq_pid];
|
||||
dlsch1_harq = NULL;
|
||||
|
||||
DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active, in cw %d \n", codeword_TB0);
|
||||
|
||||
} else if ((dlsch0_harq->status != NR_ACTIVE) && (dlsch1_harq->status == NR_ACTIVE)){
|
||||
codeword_TB1 = dlsch1_harq->codeword;
|
||||
dlsch0_harq = NULL;
|
||||
dlsch1_harq = &ue->dl_harq_processes[codeword_TB1][harq_pid];
|
||||
|
||||
DEBUG_HARQ("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", codeword_TB1);
|
||||
LOG_E(PHY, "[DEMOD] slot %d TB0 not active and TB1 active case is not supported\n", nr_slot_rx);
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
LOG_E(PHY, "[DEMOD] slot %d: no active DLSCH (2 layers case)\n", nr_slot_rx);
|
||||
return (-1);
|
||||
}
|
||||
} else if (dlsch0_harq) {
|
||||
if (dlsch0_harq->status == NR_ACTIVE) {
|
||||
codeword_TB0 = dlsch0_harq->codeword;
|
||||
dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
|
||||
DEBUG_HARQ("[DEMOD] I am assuming only TB0 is active\n");
|
||||
} else {
|
||||
LOG_E(PHY, "[DEMOD] slot %d nr_rx_pdsch no active DLSCH (one layer case)\n", nr_slot_rx);
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
LOG_E(PHY, "[DEMOD] slot %d Inconsistent call to nr_rx_pdsch (no layer 0)\n", nr_slot_rx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_HARQ("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1);
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config;
|
||||
DevAssert(dlsch0_harq);
|
||||
DevAssert(dlsch_harq);
|
||||
|
||||
if (gNB_id > 2) {
|
||||
LOG_E(PHY, "Illegal gNB_id %d\n", gNB_id);
|
||||
@@ -1229,7 +1167,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
fp,
|
||||
symbol,
|
||||
nb_re_pdsch,
|
||||
dlsch_config->qamModOrder,
|
||||
dlsch->cw_info.qamModOrder,
|
||||
nb_rb_pdsch,
|
||||
*log2_maxh); // log2_maxh+I0_shift
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_COMPENSATION_STATS);
|
||||
@@ -1286,7 +1224,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
dl_ch_magb[symbol],
|
||||
dl_ch_magr[symbol],
|
||||
dl_ch_estimates_ext,
|
||||
dlsch_config->qamModOrder,
|
||||
dlsch->cw_info.qamModOrder,
|
||||
*log2_maxh,
|
||||
symbol,
|
||||
nb_re_pdsch,
|
||||
@@ -1312,14 +1250,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
int nbSymb = 0;
|
||||
int pduBitmap = 0;
|
||||
|
||||
if(dlsch0_harq->status == NR_ACTIVE) {
|
||||
if(dlsch_harq->status == NR_ACTIVE) {
|
||||
startSymbIdx = dlsch_config->start_symbol;
|
||||
nbSymb = dlsch_config->number_symbols;
|
||||
pduBitmap = dlsch_config->pduBitmap;
|
||||
}
|
||||
|
||||
/* Check for PTRS bitmap and process it respectively */
|
||||
if((pduBitmap & 0x1) && (dlsch[0].rnti_type == TYPE_C_RNTI_)) {
|
||||
if((pduBitmap & 0x1) && (dlsch->rnti_type == TYPE_C_RNTI_)) {
|
||||
nr_pdsch_ptrs_processing(nbRx,
|
||||
ptrs_phase_per_slot,
|
||||
ptrs_re_per_slot,
|
||||
@@ -1327,13 +1265,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
nl,
|
||||
rxdataF_comp,
|
||||
fp,
|
||||
dlsch0_harq,
|
||||
dlsch1_harq,
|
||||
dlsch_config,
|
||||
nr_slot_rx,
|
||||
symbol,
|
||||
freq_alloc->num_rbs,
|
||||
dlsch[0].rnti,
|
||||
dlsch);
|
||||
dlsch->rnti,
|
||||
&dlsch->ptrs_symbols,
|
||||
&dlsch->ptrs_symbol_index);
|
||||
dl_valid_re[symbol] -= ptrs_re_per_slot[0][symbol];
|
||||
}
|
||||
/* at last symbol in a slot calculate LLR's for whole slot */
|
||||
@@ -1341,7 +1279,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
/* create LLR layer buffer */
|
||||
int max_symb_re = 0;
|
||||
GET_ARRAY_MAX(dl_valid_re, NR_SYMBOLS_PER_SLOT, max_symb_re);
|
||||
const int llr_per_symbol = max_symb_re * dlsch->dlsch_config.qamModOrder;
|
||||
const int llr_per_symbol = max_symb_re * dlsch->cw_info.qamModOrder;
|
||||
__attribute__((aligned(32))) int16_t layer_llr[NR_SYMBOLS_PER_SLOT][nl][llr_per_symbol];
|
||||
|
||||
// Generate LLR from PTRS compensated signal
|
||||
@@ -1360,14 +1298,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_LLR_STATS);
|
||||
start_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
|
||||
nr_dlsch_layer_demapping(nl, dlsch_config->qamModOrder, llr_per_symbol, layer_llr, dlsch, dl_valid_re, llr[0]);
|
||||
nr_dlsch_layer_demapping(nl, dlsch->cw_info.qamModOrder, llr_per_symbol, layer_llr, dlsch_config, dl_valid_re, llr);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_LAYER_DEMAPPING);
|
||||
/*
|
||||
for (int i=0; i < 2; i++){
|
||||
snprintf(filename, 50, "llr%d_symb_%d_nr_slot_rx_%d.m", i, symbol, nr_slot_rx);
|
||||
write_output(filename,"llr", &llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb_pdsch*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb_pdsch*4*dlsch1_harq->Qm), 1, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
if (UEScopeHasTryLock(ue)) {
|
||||
metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx };
|
||||
int total_valid_res = 0;
|
||||
|
||||
@@ -446,7 +446,8 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
nr_fill_rx_indication(&rx_ind,
|
||||
FAPI_NR_RX_PDU_TYPE_SSB,
|
||||
ue,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
number_pdus,
|
||||
proc,
|
||||
|
||||
@@ -404,7 +404,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
if (decoderState) {
|
||||
if (ue) { // decoding failed in synced state
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, NULL, NULL);
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
}
|
||||
@@ -464,7 +464,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
|
||||
|
||||
if (ue) {
|
||||
nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL);
|
||||
nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, 0, 0, NULL, number_pdus, proc, (void *)result, NULL);
|
||||
|
||||
if (ue->if_inst && ue->if_inst->dl_indication)
|
||||
ue->if_inst->dl_indication(&dl_indication);
|
||||
|
||||
@@ -60,19 +60,17 @@ int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb
|
||||
@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
|
||||
*/
|
||||
void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
short **dlsch_llr,
|
||||
uint8_t **b,
|
||||
int *G,
|
||||
int nb_dlsch,
|
||||
int cw_idx,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
|
||||
int16_t *dlsch_llr,
|
||||
uint8_t *b,
|
||||
int number_rbs,
|
||||
uint8_t *DLSCH_ids);
|
||||
int G);
|
||||
|
||||
int nr_ulsch_pre_encoding(PHY_VARS_NR_UE *ue,
|
||||
const NR_UE_ULSCH_t *ulsch,
|
||||
@@ -278,23 +276,25 @@ void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue,
|
||||
*/
|
||||
int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
const freq_alloc_bitmap_t *freq_alloc,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config,
|
||||
NR_DL_UE_HARQ_t *dlsch_harq,
|
||||
unsigned char symbol,
|
||||
bool first_symbol_flag,
|
||||
unsigned char harq_pid,
|
||||
uint32_t pdsch_est_size,
|
||||
int32_t dl_ch_estimates[][pdsch_est_size],
|
||||
int16_t *llr[2],
|
||||
int16_t *llr,
|
||||
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int32_t *log2_maxh,
|
||||
int rx_size_symbol,
|
||||
int nbRx,
|
||||
c16_t rxdataF_comp[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_mag[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magb[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magr[][dlsch->Nl][nbRx][rx_size_symbol],
|
||||
c16_t rxdataF_comp[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_mag[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magb[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t dl_ch_magr[][dlsch->cw_info.Nl][nbRx][rx_size_symbol],
|
||||
c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT],
|
||||
int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT],
|
||||
int G,
|
||||
|
||||
@@ -97,16 +97,13 @@ typedef struct {
|
||||
} NR_DL_UE_HARQ_t;
|
||||
|
||||
typedef struct {
|
||||
fapi_nr_dl_cw_info_t cw_info;
|
||||
/// RNTI
|
||||
uint16_t rnti;
|
||||
/// RNTI type
|
||||
uint8_t rnti_type;
|
||||
/// Active flag for DLSCH demodulation
|
||||
bool active;
|
||||
/// Structure to hold dlsch config from MAC
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
|
||||
/// Number of MIMO layers (streams)
|
||||
uint8_t Nl;
|
||||
/// Maximum number of LDPC iterations
|
||||
uint8_t max_ldpc_iterations;
|
||||
/// number of iterations used in last turbo decoding
|
||||
|
||||
@@ -521,8 +521,9 @@ typedef struct nr_phy_data_tx_s {
|
||||
|
||||
typedef struct nr_phy_data_s {
|
||||
NR_UE_PDCCH_CONFIG phy_pdcch_config;
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
|
||||
NR_UE_DLSCH_t dlsch[2];
|
||||
|
||||
int n_dlsch_codewords;
|
||||
// Sidelink Rx action decided by MAC
|
||||
sl_nr_rx_config_type_enum_t sl_rx_action;
|
||||
NR_UE_CSI_RS csirs_vars;
|
||||
@@ -535,7 +536,7 @@ enum stream_status_e { STREAM_STATUS_UNSYNC, STREAM_STATUS_SYNCING, STREAM_STATU
|
||||
*/
|
||||
typedef struct nr_rxtx_thread_data_s {
|
||||
UE_nr_rxtx_proc_t proc;
|
||||
PHY_VARS_NR_UE *UE;
|
||||
PHY_VARS_NR_UE *UE;
|
||||
int writeBlockSize;
|
||||
nr_phy_data_t phy_data;
|
||||
dynamic_barrier_t* next_barrier;
|
||||
|
||||
@@ -102,8 +102,9 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
|
||||
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
int cw_idx,
|
||||
int harq_pid,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
uint16_t n_pdus,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
|
||||
@@ -21,48 +21,44 @@ extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
|
||||
const char *const dl_pdu_type[] = {"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM", "TA"};
|
||||
const char *const ul_pdu_type[] = {"PRACH", "PUCCH", "PUSCH", "SRS"};
|
||||
|
||||
static void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
|
||||
static void configure_dlsch(NR_UE_DLSCH_t *dlsch,
|
||||
NR_DL_UE_HARQ_t *harq_list,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
int cw_idx,
|
||||
int rnti)
|
||||
{
|
||||
const uint8_t current_harq_pid = dlsch_config_pdu->harq_process_nbr;
|
||||
dlsch0->active = true;
|
||||
dlsch0->rnti = rnti;
|
||||
dlsch->active = true;
|
||||
dlsch->rnti = rnti;
|
||||
|
||||
LOG_D(PHY,"current_harq_pid = %d\n", current_harq_pid);
|
||||
LOG_D(PHY,"Configure DLSCH for pid = %d\n", current_harq_pid);
|
||||
|
||||
NR_DL_UE_HARQ_t *dlsch0_harq = &harq_list[current_harq_pid];
|
||||
NR_DL_UE_HARQ_t *dlsch_harq = &harq_list[current_harq_pid];
|
||||
dlsch->cw_info = dlsch_config_pdu->cw_info[cw_idx];
|
||||
|
||||
//get nrOfLayers from DCI info
|
||||
uint8_t Nl = 0;
|
||||
for (int i = 0; i < 12; i++) { // max 12 ports
|
||||
if ((dlsch_config_pdu->dmrs_ports >> i) & 0x01)
|
||||
Nl += 1;
|
||||
}
|
||||
if (Nl == 0) {
|
||||
LOG_E(PHY, "Invalid number of layers %d for DLSCH\n", Nl);
|
||||
if (dlsch->cw_info.Nl == 0) {
|
||||
LOG_E(PHY, "Invalid number of layers %d for DLSCH\n", dlsch->cw_info.Nl);
|
||||
// setting NACK for this TB
|
||||
dlsch0->active = false;
|
||||
update_harq_status(mac, current_harq_pid, 0);
|
||||
dlsch->active = false;
|
||||
update_harq_status(mac, current_harq_pid, cw_idx, 0);
|
||||
return;
|
||||
}
|
||||
dlsch0->Nl = Nl;
|
||||
if (dlsch_config_pdu->new_data_indicator) {
|
||||
dlsch0_harq->first_rx = true;
|
||||
dlsch0_harq->DLround = 0;
|
||||
|
||||
if (dlsch->cw_info.new_data_indicator) {
|
||||
dlsch_harq->first_rx = true;
|
||||
dlsch_harq->DLround = 0;
|
||||
} else {
|
||||
dlsch0_harq->first_rx = false;
|
||||
dlsch0_harq->DLround++;
|
||||
dlsch_harq->first_rx = false;
|
||||
dlsch_harq->DLround++;
|
||||
}
|
||||
downlink_harq_process(dlsch0_harq, current_harq_pid, dlsch_config_pdu->new_data_indicator, dlsch_config_pdu->rv, dlsch0->rnti_type);
|
||||
if (dlsch0_harq->status != NR_ACTIVE) {
|
||||
// dlsch0_harq->status not ACTIVE due to false retransmission
|
||||
downlink_harq_process(dlsch_harq, current_harq_pid, dlsch->cw_info.new_data_indicator, dlsch->cw_info.rv, dlsch->rnti_type);
|
||||
if (dlsch_harq->status != NR_ACTIVE) {
|
||||
// dlsch_harq->status not ACTIVE due to false retransmission
|
||||
// Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status
|
||||
dlsch0->active = false;
|
||||
dlsch->active = false;
|
||||
LOG_W(NR_MAC, "dlsch0_harq->status not ACTIVE due to false retransmission harq pid: %d\n", current_harq_pid);
|
||||
update_harq_status(mac, current_harq_pid, dlsch0_harq->decodeResult);
|
||||
update_harq_status(mac, current_harq_pid, cw_idx, dlsch_harq->decodeResult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,23 +157,28 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
|
||||
case FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH: {
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15;
|
||||
NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0;
|
||||
phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords;
|
||||
phy_data->dlsch_config = *dlsch_config_pdu;
|
||||
dlsch0->rnti_type = TYPE_RA_RNTI_;
|
||||
dlsch0->dlsch_config = *dlsch_config_pdu;
|
||||
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti);
|
||||
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, 0, pdu->dlsch_config_pdu.rnti);
|
||||
} break;
|
||||
case FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH: {
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15;
|
||||
NR_UE_DLSCH_t *dlsch0 = phy_data->dlsch + 0;
|
||||
phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords;
|
||||
phy_data->dlsch_config = *dlsch_config_pdu;
|
||||
dlsch0->rnti_type = TYPE_SI_RNTI_;
|
||||
dlsch0->dlsch_config = *dlsch_config_pdu;
|
||||
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti);
|
||||
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, 0, pdu->dlsch_config_pdu.rnti);
|
||||
} break;
|
||||
case FAPI_NR_DL_CONFIG_TYPE_DLSCH: {
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu = &pdu->dlsch_config_pdu.dlsch_config_rel15;
|
||||
NR_UE_DLSCH_t *dlsch0 = &phy_data->dlsch[0];
|
||||
dlsch0->rnti_type = TYPE_C_RNTI_;
|
||||
dlsch0->dlsch_config = *dlsch_config_pdu;
|
||||
configure_dlsch(dlsch0, phy->dl_harq_processes[0], dlsch_config_pdu, mac, pdu->dlsch_config_pdu.rnti);
|
||||
phy_data->n_dlsch_codewords = dlsch_config_pdu->n_codewords;
|
||||
phy_data->dlsch_config = *dlsch_config_pdu;
|
||||
for (int c = 0; c < dlsch_config_pdu->n_codewords; c++) {
|
||||
NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[c];
|
||||
dlsch->rnti_type = TYPE_C_RNTI_;
|
||||
configure_dlsch(dlsch, phy->dl_harq_processes[c], dlsch_config_pdu, mac, c, pdu->dlsch_config_pdu.rnti);
|
||||
}
|
||||
} break;
|
||||
case FAPI_NR_CONFIG_TA_COMMAND:
|
||||
configure_ta_command(phy, &pdu->ta_command_pdu);
|
||||
|
||||
@@ -29,6 +29,6 @@ void nr_ue_sl_phy_config_request(nr_sl_phy_config_t *phy_config);
|
||||
\param synch_request including target_Nid_cell*/
|
||||
void nr_ue_synch_request(nr_synch_request_t *synch_request);
|
||||
|
||||
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack);
|
||||
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, int cw_idx, uint8_t ack_nack);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -94,31 +94,35 @@ static uint32_t get_ssb_arfcn(NR_DL_FRAME_PARMS *frame_parms)
|
||||
uint64_t ssb_freq = frame_parms->dl_CarrierFreq - (band_size_hz / 2) + frame_parms->subcarrier_spacing * ssb_center_sc;
|
||||
return to_nrarfcn(ssb_freq);
|
||||
}
|
||||
|
||||
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
int cw_idx,
|
||||
int harq_pid,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
uint16_t n_pdus,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
uint8_t *b)
|
||||
{
|
||||
if (n_pdus > 1){
|
||||
LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__);
|
||||
if (n_pdus > 1) {
|
||||
LOG_E(PHY, "Multiple number of DL PDUs not supported yet...\n");
|
||||
return;
|
||||
}
|
||||
fapi_nr_rx_indication_body_t *rx = rx_ind->rx_indication_body + n_pdus - 1;
|
||||
switch (pdu_type){
|
||||
case FAPI_NR_RX_PDU_TYPE_SIB:
|
||||
case FAPI_NR_RX_PDU_TYPE_RAR:
|
||||
case FAPI_NR_RX_PDU_TYPE_DLSCH:
|
||||
if(dlsch0) {
|
||||
NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr];
|
||||
rx->pdsch_pdu.harq_pid = dlsch0->dlsch_config.harq_process_nbr;
|
||||
rx->pdsch_pdu.ack_nack = dl_harq0->decodeResult;
|
||||
if(dlsch) {
|
||||
NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[cw_idx][harq_pid];
|
||||
rx->pdsch_pdu.harq_pid = harq_pid;
|
||||
rx->pdsch_pdu.cw_idx = cw_idx;
|
||||
rx->pdsch_pdu.ack_nack = dl_harq->decodeResult;
|
||||
rx->pdsch_pdu.pdu = b;
|
||||
rx->pdsch_pdu.pdu_length = dlsch0->dlsch_config.TBS / 8;
|
||||
if (dl_harq0->decodeResult) {
|
||||
rx->pdsch_pdu.pdu_length = dlsch->cw_info.TBS / 8;
|
||||
if (dl_harq->decodeResult) {
|
||||
int t = WS_C_RNTI;
|
||||
if (pdu_type == FAPI_NR_RX_PDU_TYPE_RAR)
|
||||
t = WS_RA_RNTI;
|
||||
@@ -130,16 +134,13 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
.pdu_buffer_size = rx->pdsch_pdu.pdu_length,
|
||||
.ueid = 0,
|
||||
.rntiType = t,
|
||||
.rnti = dlsch0->rnti,
|
||||
.rnti = dlsch->rnti,
|
||||
.sysFrame = proc->frame_rx,
|
||||
.subframe = proc->nr_slot_rx,
|
||||
.harq_pid = dlsch0->dlsch_config.harq_process_nbr};
|
||||
.harq_pid = harq_pid};
|
||||
trace_pdu(&tmp);
|
||||
}
|
||||
}
|
||||
if(dlsch1) {
|
||||
AssertFatal(1==0,"Second codeword currently not supported\n");
|
||||
}
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_SSB: {
|
||||
if (typeSpecific) {
|
||||
@@ -168,7 +169,6 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
|
||||
rx->pdu_type = pdu_type;
|
||||
rx_ind->number_pdus = n_pdus;
|
||||
|
||||
}
|
||||
|
||||
int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){
|
||||
@@ -488,8 +488,10 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
|
||||
|
||||
static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
NR_UE_DLSCH_t dlsch[2],
|
||||
int16_t *llr[2],
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
NR_DL_UE_HARQ_t *dlsch_harq,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg,
|
||||
int16_t *llr,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP],
|
||||
int G,
|
||||
freq_alloc_bitmap_t *freq_alloc)
|
||||
@@ -502,11 +504,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
LOG_E(NR_PHY, "Handling of more than one CW not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
NR_UE_DLSCH_t *dlsch0 = &dlsch[0];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg = &dlsch0->dlsch_config;
|
||||
|
||||
int harq_pid = dlschCfg->harq_process_nbr;
|
||||
// dlsch0_harq contains the previous transmissions data for this harq pid
|
||||
NR_DL_UE_HARQ_t *dlsch0_harq = &ue->dl_harq_processes[0][harq_pid];
|
||||
|
||||
LOG_D(PHY,
|
||||
"[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, start RB %d, end RB %d, symbol_start %d, nb_symbols "
|
||||
@@ -516,18 +515,18 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
frame_rx,
|
||||
nr_slot_rx,
|
||||
harq_pid,
|
||||
dlsch0_harq->status,
|
||||
dlsch_harq->status,
|
||||
dlschCfg->BWPStart,
|
||||
freq_alloc->first_rb,
|
||||
freq_alloc->last_rb,
|
||||
dlschCfg->start_symbol,
|
||||
dlschCfg->number_symbols,
|
||||
dlschCfg->dlDmrsSymbPos,
|
||||
dlsch0->Nl);
|
||||
dlsch->cw_info.Nl);
|
||||
|
||||
const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size + 15) / 16) * 16;
|
||||
fourDimArray_t *toFree = NULL;
|
||||
allocCast2D(pdsch_dl_ch_estimates, int32_t, toFree, ue->frame_parms.nb_antennas_rx * dlsch0->Nl, pdsch_est_size, false);
|
||||
allocCast2D(pdsch_dl_ch_estimates, int32_t, toFree, ue->frame_parms.nb_antennas_rx * dlsch->cw_info.Nl, pdsch_est_size, false);
|
||||
|
||||
c16_t ptrs_phase_per_slot[ue->frame_parms.nb_antennas_rx][NR_SYMBOLS_PER_SLOT];
|
||||
memset(ptrs_phase_per_slot, 0, sizeof(ptrs_phase_per_slot));
|
||||
@@ -541,7 +540,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
c16_t,
|
||||
toFree2,
|
||||
ue->frame_parms.symbols_per_slot,
|
||||
dlsch[0].Nl,
|
||||
dlsch->cw_info.Nl,
|
||||
ue->frame_parms.nb_antennas_rx,
|
||||
rx_size_symbol,
|
||||
false);
|
||||
@@ -551,7 +550,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
start_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
|
||||
for (int m = dlschCfg->start_symbol; m < (dlschCfg->start_symbol + dlschCfg->number_symbols); m++) {
|
||||
if (dlschCfg->dlDmrsSymbPos & (1 << m)) {
|
||||
for (int nl = 0; nl < dlsch0->Nl; nl++) { // for MIMO Config: it shall loop over no_layers
|
||||
for (int nl = 0; nl < dlsch->cw_info.Nl; nl++) { // for MIMO Config: it shall loop over no_layers
|
||||
LOG_D(PHY, "PDSCH Channel estimation layer %d, slot %d, symbol %d\n", nl, nr_slot_rx, m);
|
||||
uint32_t nvar_tmp = 0;
|
||||
nr_pdsch_channel_estimation(ue,
|
||||
@@ -580,7 +579,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
}
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_CHANNEL_ESTIMATION_STATS);
|
||||
nvar /= (dlschCfg->number_symbols * dlsch0->Nl * ue->frame_parms.nb_antennas_rx);
|
||||
nvar /= (dlschCfg->number_symbols * dlsch->cw_info.Nl * ue->frame_parms.nb_antennas_rx);
|
||||
nr_ue_measurement_procedures(2, ue, proc, freq_alloc->num_rbs, pdsch_est_size, pdsch_dl_ch_estimates);
|
||||
|
||||
if (ue->chest_time == 1) { // averaging time domain channel estimates
|
||||
@@ -589,7 +588,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
dlschCfg->number_symbols,
|
||||
dlschCfg->start_symbol,
|
||||
dlschCfg->dlDmrsSymbPos,
|
||||
freq_alloc->num_rbs);
|
||||
freq_alloc->num_rbs,
|
||||
dlsch->cw_info.Nl);
|
||||
}
|
||||
|
||||
uint16_t first_symbol_with_data = dlschCfg->start_symbol;
|
||||
@@ -630,7 +630,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
c16_t,
|
||||
toFree3,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
dlsch[0].Nl,
|
||||
dlsch->cw_info.Nl,
|
||||
ue->frame_parms.nb_antennas_rx,
|
||||
rx_size_symbol,
|
||||
false);
|
||||
@@ -639,7 +639,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
c16_t,
|
||||
toFree4,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
dlsch[0].Nl,
|
||||
dlsch->cw_info.Nl,
|
||||
ue->frame_parms.nb_antennas_rx,
|
||||
rx_size_symbol,
|
||||
false);
|
||||
@@ -648,7 +648,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
c16_t,
|
||||
toFree5,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
dlsch[0].Nl,
|
||||
dlsch->cw_info.Nl,
|
||||
ue->frame_parms.nb_antennas_rx,
|
||||
rx_size_symbol,
|
||||
false);
|
||||
@@ -663,6 +663,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
proc,
|
||||
dlsch,
|
||||
freq_alloc,
|
||||
dlschCfg,
|
||||
dlsch_harq,
|
||||
m,
|
||||
first_symbol_flag,
|
||||
harq_pid,
|
||||
@@ -760,90 +762,68 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls
|
||||
*/
|
||||
static void 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[2],
|
||||
freq_alloc_bitmap_t *freq_alloc)
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
int cw_idx,
|
||||
int G,
|
||||
freq_alloc_bitmap_t *freq_alloc,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *config,
|
||||
int16_t *llr)
|
||||
{
|
||||
if (dlsch[0].active == false) {
|
||||
if (dlsch->active == false) {
|
||||
LOG_E(PHY, "DLSCH should be active when calling this function\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int harq_pid = dlsch[0].dlsch_config.harq_process_nbr;
|
||||
int harq_pid = config->harq_process_nbr;
|
||||
int frame_rx = proc->frame_rx;
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
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];
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t rx_ind = {0};
|
||||
uint16_t number_pdus = 1;
|
||||
|
||||
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 == NR_ACTIVE) ? 1 : 0;
|
||||
nb_dlsch += (is_cw1_active == NR_ACTIVE) ? 1 : 0;
|
||||
|
||||
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 CW%d [harq_pid %d]\n", frame_rx % 1024, nr_slot_rx, cw_idx, harq_pid);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
|
||||
// exit dlsch procedures as there are no active dlsch
|
||||
if (is_cw0_active != ACTIVE && is_cw1_active != NR_ACTIVE) {
|
||||
NR_DL_UE_HARQ_t *dl_harq = &ue->dl_harq_processes[cw_idx][harq_pid];
|
||||
if (dl_harq->status != NR_ACTIVE) {
|
||||
// don't wait anymore
|
||||
LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid);
|
||||
if (dlsch[0].dlsch_config.k1_feedback) {
|
||||
const int ack_nack_slot_and_frame =
|
||||
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
|
||||
if (config->k1_feedback) {
|
||||
const int ack_nack_slot_and_frame = (proc->nr_slot_rx + config->k1_feedback) + proc->frame_rx * fp->slots_per_frame;
|
||||
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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 != NR_ACTIVE)
|
||||
continue;
|
||||
|
||||
DLSCH_ids[pdsch_id++] = DLSCH_id;
|
||||
|
||||
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_UNSCRAMBLING_STATS);
|
||||
nr_dlsch_unscrambling(llr, G, 0, config->dlDataScramblingId, dlsch->rnti);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_UNSCRAMBLING_STATS);
|
||||
|
||||
start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, freq_alloc->num_rbs, DLSCH_ids);
|
||||
nr_dlsch_decoding(ue, proc, dlsch, cw_idx, config, llr, dl_harq->b, freq_alloc->num_rbs, G);
|
||||
stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS);
|
||||
|
||||
int ind_type = -1;
|
||||
switch (dlsch[0].rnti_type) {
|
||||
switch (dlsch->rnti_type) {
|
||||
case TYPE_RA_RNTI_:
|
||||
ind_type = FAPI_NR_RX_PDU_TYPE_RAR;
|
||||
break;
|
||||
|
||||
case TYPE_SI_RNTI_:
|
||||
ind_type = FAPI_NR_RX_PDU_TYPE_SIB;
|
||||
break;
|
||||
|
||||
case TYPE_C_RNTI_:
|
||||
ind_type = FAPI_NR_RX_PDU_TYPE_DLSCH;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(true, "Invalid DLSCH type %d\n", dlsch[0].rnti_type);
|
||||
AssertFatal(false, "Invalid DLSCH type %d\n", dlsch->rnti_type);
|
||||
break;
|
||||
}
|
||||
|
||||
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[0]);
|
||||
nr_fill_rx_indication(&rx_ind, ind_type, ue, cw_idx, harq_pid, dlsch, number_pdus, proc, NULL, dl_harq->b);
|
||||
|
||||
LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8);
|
||||
LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch->cw_info.TBS, dlsch->cw_info.TBS / 8);
|
||||
if (cpumeas(CPUMEAS_GETSTATE)) {
|
||||
LOG_D(PHY,
|
||||
" --> Unscrambling %5.3f\n",
|
||||
@@ -861,9 +841,8 @@ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
// DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH
|
||||
if ((dlsch[0].rnti_type == TYPE_C_RNTI_ || dlsch[0].rnti_type == TYPE_RA_RNTI_) && dlsch[0].dlsch_config.k1_feedback) {
|
||||
const int ack_nack_slot_and_frame =
|
||||
(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame;
|
||||
if ((dlsch->rnti_type == TYPE_C_RNTI_ || dlsch->rnti_type == TYPE_RA_RNTI_) && config->k1_feedback) {
|
||||
const int ack_nack_slot_and_frame = (proc->nr_slot_rx + config->k1_feedback) + proc->frame_rx * fp->slots_per_frame;
|
||||
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]);
|
||||
}
|
||||
|
||||
@@ -874,11 +853,8 @@ static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment
|
||||
|
||||
if (ue->phy_sim_dlsch_b && is_cw0_active == NR_ACTIVE)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b[0], dlsch_bytes);
|
||||
else if (ue->phy_sim_dlsch_b && is_cw1_active == NR_ACTIVE)
|
||||
memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes);
|
||||
|
||||
if (ue->phy_sim_dlsch_b)
|
||||
memcpy(ue->phy_sim_dlsch_b, dl_harq->b, dlsch_bytes);
|
||||
}
|
||||
|
||||
static bool check_meas_to_perform(PHY_VARS_NR_UE *ue, int nr_slot_rx)
|
||||
@@ -1150,7 +1126,6 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
int nr_slot_rx = proc->nr_slot_rx;
|
||||
int gNB_id = proc->gNB_id;
|
||||
|
||||
NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[0];
|
||||
// do procedures for C-RNTI
|
||||
|
||||
bool slot_fep_map[14] = {0};
|
||||
@@ -1182,9 +1157,13 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
nr_ue_csi_rs_procedures(ue, proc, rxdataF, &phy_data->csirs_vars.csirs_config_pdu);
|
||||
}
|
||||
|
||||
int G[2] = {0};
|
||||
if (dlsch[0].active) {
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &dlsch[0].dlsch_config;
|
||||
int16_t *llr[2];
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = &phy_data->dlsch_config;
|
||||
for (int c = 0; c < phy_data->n_dlsch_codewords; c++) {
|
||||
NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[c];
|
||||
if (!dlsch->active)
|
||||
continue;
|
||||
|
||||
uint16_t nb_symb_sch = dlsch_config->number_symbols;
|
||||
uint16_t start_symb_sch = dlsch_config->start_symbol;
|
||||
|
||||
@@ -1219,32 +1198,30 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
unav_res = n_ptrs * ptrsSymbPerSlot;
|
||||
}
|
||||
unav_res += compute_csi_rm_unav_res(dlsch_config);
|
||||
G[0] = nr_get_G(freq_alloc.num_rbs,
|
||||
dlsch_config->number_symbols,
|
||||
nb_re_dmrs,
|
||||
dmrs_len,
|
||||
unav_res,
|
||||
dlsch_config->qamModOrder,
|
||||
dlsch[0].Nl);
|
||||
const uint32_t rx_llr_buf_sz = ALIGNARRAYSIZE(G[0], 32); // each LLR is 2 bytes hence 64 byte aligned
|
||||
const uint32_t nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1;
|
||||
int16_t* llr[2];
|
||||
for (int i = 0; i < nb_codewords; i++)
|
||||
llr[i] = (int16_t *)malloc16_clear(rx_llr_buf_sz * sizeof(int16_t));
|
||||
int G = nr_get_G(freq_alloc.num_rbs,
|
||||
dlsch_config->number_symbols,
|
||||
nb_re_dmrs,
|
||||
dmrs_len,
|
||||
unav_res,
|
||||
dlsch->cw_info.qamModOrder,
|
||||
dlsch->cw_info.Nl);
|
||||
const uint32_t rx_llr_buf_sz = ALIGNARRAYSIZE(G, 32); // each LLR is 2 bytes hence 64 byte aligned
|
||||
llr[c] = (int16_t *)malloc16_clear(rx_llr_buf_sz * sizeof(int16_t));
|
||||
|
||||
// dlsch_harq contains the previous transmissions data for this harq pid
|
||||
NR_DL_UE_HARQ_t *harq = &ue->dl_harq_processes[c][dlsch_config->harq_process_nbr];
|
||||
// it returns -1 in case of internal failure, or 0 in case of normal result
|
||||
int ret_pdsch = nr_ue_pdsch_procedures(ue, proc, dlsch, llr, rxdataF, G[0], &freq_alloc);
|
||||
TracyCPlot("pdsch mcs", dlsch->dlsch_config.mcs);
|
||||
int ret_pdsch = nr_ue_pdsch_procedures(ue, proc, dlsch, harq, dlsch_config, llr[c], rxdataF, &freq_alloc);
|
||||
TracyCPlot("pdsch mcs", dlsch->cw_info.mcs);
|
||||
|
||||
UEscopeCopy(ue, pdschLlr, llr[0], sizeof(int16_t), 1, G[0], 0);
|
||||
UEscopeCopy(ue, pdschLlr, llr[c], sizeof(int16_t), 1, G, 0);
|
||||
|
||||
LOG_D(PHY, "DLSCH data reception at nr_slot_rx: %d\n", nr_slot_rx);
|
||||
start_meas_nr_ue_phy(ue, DLSCH_PROCEDURES_STATS);
|
||||
|
||||
if (ret_pdsch >= 0) {
|
||||
nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G, &freq_alloc);
|
||||
}
|
||||
else {
|
||||
nr_ue_dlsch_procedures(ue, proc, dlsch, c, G, &freq_alloc, dlsch_config, llr[c]);
|
||||
} else {
|
||||
LOG_E(NR_PHY, "Demodulation impossible, internal error\n");
|
||||
if (dlsch_config->k1_feedback) {
|
||||
const int ack_nack_slot_and_frame =
|
||||
@@ -1264,10 +1241,9 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
|
||||
&rxdataF[0][start_symb_sch * ue->frame_parms.ofdm_symbol_size],
|
||||
sizeof(int32_t) * nb_symb_sch * ue->frame_parms.ofdm_symbol_size);
|
||||
if (ue->phy_sim_pdsch_llr)
|
||||
memcpy(ue->phy_sim_pdsch_llr, llr[0], sizeof(int16_t) * rx_llr_buf_sz);
|
||||
memcpy(ue->phy_sim_pdsch_llr, llr[c], sizeof(int16_t) * rx_llr_buf_sz);
|
||||
|
||||
for (int i=0; i<nb_codewords; i++)
|
||||
free(llr[i]);
|
||||
free(llr[c]);
|
||||
}
|
||||
|
||||
if (nr_slot_rx==9) {
|
||||
|
||||
@@ -457,20 +457,22 @@ int main(int argc, char **argv)
|
||||
NR_UE_DLSCH_t *dlsch0_ue = &dlsch_ue[0];
|
||||
NR_DL_UE_HARQ_t *harq_process = &UE->dl_harq_processes[0][harq_pid];
|
||||
harq_process->first_rx = 1;
|
||||
dlsch0_ue->dlsch_config.mcs = Imcs;
|
||||
dlsch0_ue->dlsch_config.mcs_table = mcs_table;
|
||||
dlsch0_ue->Nl = Nl;
|
||||
dlsch0_ue->dlsch_config.number_rbs = nb_rb;
|
||||
dlsch0_ue->dlsch_config.qamModOrder = mod_order;
|
||||
dlsch0_ue->dlsch_config.rv = rvidx;
|
||||
dlsch0_ue->dlsch_config.targetCodeRate = rate;
|
||||
dlsch0_ue->dlsch_config.TBS = TBS;
|
||||
dlsch0_ue->dlsch_config.ldpcBaseGraph = get_BG(TBS, rate);
|
||||
dlsch0_ue->dlsch_config.dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
|
||||
dlsch0_ue->dlsch_config.dlDmrsSymbPos = 4;
|
||||
dlsch0_ue->dlsch_config.n_dmrs_cdm_groups = 1;
|
||||
dlsch0_ue->dlsch_config.tbslbrm = Tbslbrm;
|
||||
printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch0_ue->dlsch_config.mcs, dlsch0_ue->dlsch_config.qamModOrder, nb_symb_sch);
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t dlsch_config;
|
||||
dlsch_config.cw_info[0].mcs = Imcs;
|
||||
dlsch_config.mcs_table = mcs_table;
|
||||
dlsch_config.number_rbs = nb_rb;
|
||||
dlsch_config.cw_info[0].Nl = Nl;
|
||||
dlsch_config.cw_info[0].qamModOrder = mod_order;
|
||||
dlsch_config.cw_info[0].rv = rvidx;
|
||||
dlsch_config.cw_info[0].targetCodeRate = rate;
|
||||
dlsch_config.cw_info[0].TBS = TBS;
|
||||
dlsch_config.cw_info[0].ldpcBaseGraph = get_BG(TBS, rate);
|
||||
dlsch_config.dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
|
||||
dlsch_config.dlDmrsSymbPos = 4;
|
||||
dlsch_config.n_dmrs_cdm_groups = 1;
|
||||
dlsch_config.tbslbrm = Tbslbrm;
|
||||
dlsch0_ue->cw_info = dlsch_config.cw_info[0];
|
||||
printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch_config.cw_info[0].mcs, dlsch_config.cw_info[0].qamModOrder, nb_symb_sch);
|
||||
|
||||
uint8_t test_input[TBS / 8 + 4]; // + 3 for CRC + 1 additional byte, see nr_dlsch_encoding()
|
||||
dlsch->pdu = test_input;
|
||||
@@ -536,27 +538,23 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
#endif
|
||||
|
||||
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated
|
||||
int num_rb = dlsch0_ue->dlsch_config.number_rbs;
|
||||
int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; // number of segments to be allocated
|
||||
int num_rb = 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 b[dlsch_bytes];
|
||||
uint8_t DLSCH_ids[1] = {0};
|
||||
short *p_channel_output_fixed = channel_output_fixed;
|
||||
uint8_t *p_b = b;
|
||||
int available_bits_array[1] = { available_bits };
|
||||
nr_dlsch_decoding(UE,
|
||||
&proc,
|
||||
dlsch0_ue,
|
||||
&p_channel_output_fixed,
|
||||
&p_b,
|
||||
available_bits_array,
|
||||
1,
|
||||
0,
|
||||
&dlsch_config,
|
||||
channel_output_fixed,
|
||||
b,
|
||||
num_rb,
|
||||
DLSCH_ids);
|
||||
available_bits);
|
||||
|
||||
if (dlsch0_ue->last_iteration_cnt > dlsch0_ue->max_ldpc_iterations)
|
||||
n_errors++;
|
||||
@@ -634,4 +632,3 @@ int main(int argc, char **argv)
|
||||
|
||||
return (n_errors);
|
||||
}
|
||||
|
||||
|
||||
@@ -1310,12 +1310,14 @@ int main(int argc, char **argv)
|
||||
|
||||
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
|
||||
|
||||
TBS = dlsch0->dlsch_config.TBS;
|
||||
uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos);
|
||||
uint16_t nb_rb = dlsch0->dlsch_config.number_rbs;
|
||||
uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups;
|
||||
uint8_t mod_order = dlsch0->dlsch_config.qamModOrder;
|
||||
uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols;
|
||||
TBS = phy_data.dlsch_config.cw_info[0].TBS;
|
||||
uint16_t length_dmrs = get_num_dmrs(phy_data.dlsch_config.dlDmrsSymbPos);
|
||||
uint16_t nb_rb = phy_data.dlsch_config.number_rbs;
|
||||
uint8_t nb_re_dmrs = phy_data.dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ?
|
||||
6 * phy_data.dlsch_config.n_dmrs_cdm_groups :
|
||||
4 * phy_data.dlsch_config.n_dmrs_cdm_groups;
|
||||
uint8_t mod_order = phy_data.dlsch_config.cw_info[0].qamModOrder;
|
||||
uint8_t nb_symb_sch = phy_data.dlsch_config.number_symbols;
|
||||
uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb;
|
||||
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers);
|
||||
if (pdu_bit_map & 0x1) {
|
||||
@@ -1457,10 +1459,10 @@ int main(int argc, char **argv)
|
||||
const int s = pdsch_pdu_rel15->StartSymbolIndex;
|
||||
const int n = pdsch_pdu_rel15->NrOfSymbols;
|
||||
for (int i = s; i < s + n; i++) {
|
||||
const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos;
|
||||
const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType;
|
||||
const uint32_t nrb = phy_data.dlsch[0].dlsch_config.number_rbs;
|
||||
const uint32_t ncdmg = phy_data.dlsch[0].dlsch_config.n_dmrs_cdm_groups;
|
||||
const uint32_t dmrsBitMap = phy_data.dlsch_config.dlDmrsSymbPos;
|
||||
const uint32_t dmrsCfg = phy_data.dlsch_config.dmrsConfigType;
|
||||
const uint32_t nrb = phy_data.dlsch_config.number_rbs;
|
||||
const uint32_t ncdmg = phy_data.dlsch_config.n_dmrs_cdm_groups;
|
||||
const uint32_t numValidReSym = ((dmrsBitMap >> i) & 1)
|
||||
? ((dmrsCfg == NFAPI_NR_DMRS_TYPE1) ? nrb * (12 - 6 * ncdmg) : nrb * (12 - 4 * ncdmg))
|
||||
: (nrb * 12);
|
||||
|
||||
@@ -83,8 +83,9 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
|
||||
void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
|
||||
uint8_t pdu_type,
|
||||
PHY_VARS_NR_UE *ue,
|
||||
NR_UE_DLSCH_t *dlsch0,
|
||||
NR_UE_DLSCH_t *dlsch1,
|
||||
int cw_idx,
|
||||
int harq_pid,
|
||||
NR_UE_DLSCH_t *dlsch,
|
||||
uint16_t n_pdus,
|
||||
const UE_nr_rxtx_proc_t *proc,
|
||||
void *typeSpecific,
|
||||
|
||||
@@ -3033,7 +3033,7 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP,
|
||||
size += 8;
|
||||
// TB2
|
||||
long *maxCWperDCI = pdsch_Config ? pdsch_Config->maxNrofCodeWordsScheduledByDCI : NULL;
|
||||
if ((maxCWperDCI != NULL) && (*maxCWperDCI == 2)) {
|
||||
if (maxCWperDCI && (*maxCWperDCI == NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n2)) {
|
||||
size += 8;
|
||||
}
|
||||
// HARQ process number – 5 bits if higher layer parameter harq-ProcessNumberSizeDCI-1-1 is configured;
|
||||
|
||||
@@ -595,7 +595,7 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
|
||||
// Defined for abstracted mode
|
||||
nr_downlink_indication_t dl_info;
|
||||
NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES];
|
||||
NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES][2]; // one harq process for each codeword
|
||||
NR_UE_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES];
|
||||
|
||||
NR_TAG_Id_t tag_Id;
|
||||
|
||||
@@ -200,12 +200,14 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
nr_mac->scheduling_info.phr_info.phr_reporting = 0;
|
||||
nr_mac->scheduling_info.phr_info.was_mac_reset = true;
|
||||
|
||||
// flush the soft buffers for all DL HARQ processes
|
||||
memset(nr_mac->dl_harq_info, 0, sizeof(nr_mac->dl_harq_info));
|
||||
|
||||
// for each DL HARQ process, consider the next received transmission for a TB as the very first transmission
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
|
||||
nr_mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
for (int c = 0; c < 2; c++) {
|
||||
// flush the soft buffers for all DL HARQ processes
|
||||
// for each DL HARQ process, consider the next received transmission for a TB as the very first transmission
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
|
||||
memset(&nr_mac->dl_harq_info[k][c], 0, sizeof(NR_UE_DL_HARQ_STATUS_t));
|
||||
nr_mac->dl_harq_info[k][c].last_ndi = -1; // initialize to invalid value
|
||||
}
|
||||
}
|
||||
|
||||
// release, if any, Temporary C-RNTI
|
||||
nr_mac->ra.t_crnti = 0;
|
||||
|
||||
@@ -1190,7 +1190,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order)
|
||||
|
||||
void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack)
|
||||
{
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid];
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid][0]; // single cw for MSG4
|
||||
int sched_slot = current_harq->ul_slot;
|
||||
int sched_frame = current_harq->ul_frame;
|
||||
PUCCH_sched_t pucch = {.n_CCE = current_harq->n_CCE,
|
||||
|
||||
@@ -218,9 +218,11 @@ int get_sum_delta_pucch(NR_UE_MAC_INST_t *mac, int slot, frame_t frame)
|
||||
const int num_dl_harq = get_nrofHARQ_ProcessesForPDSCH(&mac->sc_info);
|
||||
|
||||
for (int i = 0; i < num_dl_harq; i++) {
|
||||
if (mac->dl_harq_info[i].active && mac->dl_harq_info[i].ul_slot == slot && mac->dl_harq_info[i].ul_frame == frame) {
|
||||
delta_tpc_sum += mac->dl_harq_info[i].delta_pucch;
|
||||
mac->dl_harq_info[i].delta_pucch = 0;
|
||||
for (int c = 0; c < 2; c++) {
|
||||
if (mac->dl_harq_info[i][c].active && mac->dl_harq_info[i][c].ul_slot == slot && mac->dl_harq_info[i][c].ul_frame == frame) {
|
||||
delta_tpc_sum += mac->dl_harq_info[i][c].delta_pucch;
|
||||
mac->dl_harq_info[i][c].delta_pucch = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return delta_tpc_sum;
|
||||
|
||||
@@ -435,6 +435,7 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
|
||||
static void set_harq_status(NR_UE_MAC_INST_t *mac,
|
||||
uint8_t pucch_id,
|
||||
uint8_t harq_id,
|
||||
int cw_id,
|
||||
int8_t delta_pucch,
|
||||
uint16_t data_toul_fb,
|
||||
uint8_t dai,
|
||||
@@ -443,7 +444,7 @@ static void set_harq_status(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot)
|
||||
{
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id];
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id][cw_id];
|
||||
current_harq->active = true;
|
||||
current_harq->ack_received = false;
|
||||
current_harq->pucch_resource_indicator = pucch_id;
|
||||
@@ -469,13 +470,15 @@ static void set_harq_status(NR_UE_MAC_INST_t *mac,
|
||||
// looking for other active HARQ processes with feedback in the same frame/slot
|
||||
if (i == harq_id)
|
||||
continue;
|
||||
NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i];
|
||||
if (harq->active &&
|
||||
harq->ul_frame == current_harq->ul_frame &&
|
||||
harq->ul_slot == current_harq->ul_slot) {
|
||||
// highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot
|
||||
if (harq->dai_cumul > highest_dai)
|
||||
highest_dai = harq->dai_cumul - 1;
|
||||
for (int c = 0; c < 2; c++) {
|
||||
NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i][c];
|
||||
if (harq->active &&
|
||||
harq->ul_frame == current_harq->ul_frame &&
|
||||
harq->ul_slot == current_harq->ul_slot) {
|
||||
// highest_dai is the largest cumulative dai in the set of HARQ allocations for a given slot
|
||||
if (harq->dai_cumul > highest_dai)
|
||||
highest_dai = harq->dai_cumul - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,6 +670,99 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Table 7.3.1.3-1 of 38.211
|
||||
static int get_nl_for_cw(int Nl, int cw_idx)
|
||||
{
|
||||
AssertFatal(Nl >= 0 && Nl <= 8, "Invalid number of layers %d\n", Nl);
|
||||
if (Nl < 5)
|
||||
return Nl;
|
||||
else {
|
||||
if (cw_idx == 0)
|
||||
return Nl / 2;
|
||||
else
|
||||
return Nl / 2 + Nl % 2;
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_cw_info(NR_UE_DL_HARQ_STATUS_t *current_harq,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_pdu,
|
||||
uint8_t pdu_type,
|
||||
fapi_nr_dl_cw_info_t *cw_info,
|
||||
int number_rbs,
|
||||
int nb_re_dmrs,
|
||||
int nb_rb_oh,
|
||||
int rv,
|
||||
int mcs,
|
||||
int ndi,
|
||||
int cw_idx)
|
||||
{
|
||||
uint8_t Nl = 0;
|
||||
for (int i = 0; i < 12; i++) { // max 12 ports
|
||||
if ((dlsch_pdu->dmrs_ports >> i) & 0x01)
|
||||
Nl += 1;
|
||||
}
|
||||
|
||||
cw_info->mcs = mcs;
|
||||
/* RV for transport block */
|
||||
cw_info->rv = rv;
|
||||
/* NDI for transport block*/
|
||||
if (pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH || pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH || ndi != current_harq->last_ndi) {
|
||||
// new data
|
||||
cw_info->new_data_indicator = true;
|
||||
current_harq->R = 0;
|
||||
current_harq->TBS = 0;
|
||||
} else
|
||||
cw_info->new_data_indicator = false;
|
||||
if (pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH && pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) {
|
||||
current_harq->last_ndi = ndi;
|
||||
if (cw_info->new_data_indicator)
|
||||
current_harq->round = 0;
|
||||
else
|
||||
current_harq->round++;
|
||||
}
|
||||
cw_info->qamModOrder = nr_get_Qm_dl(cw_info->mcs, dlsch_pdu->mcs_table);
|
||||
if (cw_info->qamModOrder == 0) {
|
||||
LOG_W(NR_MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
cw_info->Nl = get_nl_for_cw(Nl, cw_idx);
|
||||
int R = nr_get_code_rate_dl(cw_info->mcs, dlsch_pdu->mcs_table);
|
||||
if (R > 0) {
|
||||
cw_info->targetCodeRate = R;
|
||||
cw_info->TBS = nr_compute_tbs(cw_info->qamModOrder,
|
||||
R,
|
||||
number_rbs,
|
||||
dlsch_pdu->number_symbols,
|
||||
nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos),
|
||||
nb_rb_oh,
|
||||
0,
|
||||
cw_info->Nl);
|
||||
// storing for possible retransmissions
|
||||
if (!cw_info->new_data_indicator && current_harq->TBS != cw_info->TBS) {
|
||||
LOG_W(NR_MAC,
|
||||
"NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
|
||||
cw_info->TBS,
|
||||
current_harq->TBS);
|
||||
cw_info->new_data_indicator = true; // treated as new data
|
||||
}
|
||||
current_harq->R = cw_info->targetCodeRate;
|
||||
current_harq->TBS = cw_info->TBS;
|
||||
}
|
||||
else {
|
||||
cw_info->targetCodeRate = current_harq->R;
|
||||
cw_info->TBS = current_harq->TBS;
|
||||
}
|
||||
|
||||
if (cw_info->TBS == 0) {
|
||||
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
|
||||
return false;
|
||||
}
|
||||
cw_info->ldpcBaseGraph = get_BG(cw_info->TBS, cw_info->targetCodeRate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
@@ -789,7 +885,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
0,
|
||||
dci->frequency_domain_assignment)
|
||||
< 0) {
|
||||
LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
|
||||
LOG_W(NR_MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -873,76 +969,28 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
NULL, // SPS not implemented,
|
||||
false, // as above
|
||||
NULL); // MCS-C-RNTI not implemented
|
||||
/* MCS */
|
||||
dlsch_pdu->mcs = dci->mcs;
|
||||
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val];
|
||||
/* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
|
||||
if (dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH ||
|
||||
dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH ||
|
||||
dci->ndi != current_harq->last_ndi) {
|
||||
// new data
|
||||
dlsch_pdu->new_data_indicator = true;
|
||||
current_harq->R = 0;
|
||||
current_harq->TBS = 0;
|
||||
} else {
|
||||
dlsch_pdu->new_data_indicator = false;
|
||||
}
|
||||
|
||||
if (dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH &&
|
||||
dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) {
|
||||
current_harq->last_ndi = dci->ndi;
|
||||
}
|
||||
|
||||
dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
|
||||
if (dlsch_pdu->qamModOrder == 0) {
|
||||
LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
|
||||
int nb_re_dmrs = ((dlsch_pdu->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
|
||||
int nb_rb_oh = mac->sc_info.xOverhead_PDSCH ? nb_rb_oh = 6 * (1 + *mac->sc_info.xOverhead_PDSCH) : 0;
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val][0];
|
||||
if (!get_cw_info(current_harq,
|
||||
dlsch_pdu,
|
||||
dl_conf_req->pdu_type,
|
||||
&dlsch_pdu->cw_info[0],
|
||||
dlsch_pdu->number_rbs,
|
||||
nb_re_dmrs,
|
||||
nb_rb_oh,
|
||||
dci->rv,
|
||||
dci->mcs,
|
||||
dci->ndi,
|
||||
0))
|
||||
return -1;
|
||||
}
|
||||
|
||||
int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
|
||||
if (R > 0) {
|
||||
dlsch_pdu->targetCodeRate = R;
|
||||
int nb_rb_oh;
|
||||
if (mac->sc_info.xOverhead_PDSCH)
|
||||
nb_rb_oh = 6 * (1 + *mac->sc_info.xOverhead_PDSCH);
|
||||
else
|
||||
nb_rb_oh = 0;
|
||||
int nb_re_dmrs = ((dlsch_pdu->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
|
||||
dlsch_pdu->TBS = nr_compute_tbs(dlsch_pdu->qamModOrder,
|
||||
R,
|
||||
dlsch_pdu->number_rbs,
|
||||
dlsch_pdu->number_symbols,
|
||||
nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos),
|
||||
nb_rb_oh,
|
||||
0,
|
||||
1);
|
||||
// storing for possible retransmissions
|
||||
current_harq->R = dlsch_pdu->targetCodeRate;
|
||||
if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) {
|
||||
LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
|
||||
dlsch_pdu->TBS, current_harq->TBS);
|
||||
dlsch_pdu->new_data_indicator = true; // treated as new data
|
||||
}
|
||||
current_harq->TBS = dlsch_pdu->TBS;
|
||||
}
|
||||
else {
|
||||
dlsch_pdu->targetCodeRate = current_harq->R;
|
||||
dlsch_pdu->TBS = current_harq->TBS;
|
||||
}
|
||||
|
||||
dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate);
|
||||
|
||||
if (dlsch_pdu->TBS == 0) {
|
||||
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
|
||||
return -1;
|
||||
}
|
||||
dlsch_pdu->n_codewords = 1;
|
||||
|
||||
int bw_tbslbrm = current_DL_BWP ? mac->sc_info.dl_bw_tbslbrm : dlsch_pdu->BWPSize;
|
||||
dlsch_pdu->tbslbrm = nr_compute_tbslbrm(dlsch_pdu->mcs_table, bw_tbslbrm, 1);
|
||||
|
||||
/* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
|
||||
dlsch_pdu->rv = dci->rv;
|
||||
/* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
|
||||
dlsch_pdu->harq_process_nbr = dci->harq_pid.val;
|
||||
/* TB_SCALING (only if CRC scrambled by P-RNTI or RA-RNTI) */
|
||||
@@ -1009,6 +1057,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
set_harq_status(mac,
|
||||
dci->pucch_resource_indicator,
|
||||
dci->harq_pid.val,
|
||||
0,
|
||||
tpc[dci->tpc],
|
||||
feedback_ti,
|
||||
dci->dai[0].val,
|
||||
@@ -1017,10 +1066,6 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
frame,
|
||||
slot);
|
||||
}
|
||||
if (dlsch_pdu->new_data_indicator)
|
||||
current_harq->round = 0;
|
||||
else
|
||||
current_harq->round++;
|
||||
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
|
||||
mac->stats.dl.rounds[current_harq->round]++;
|
||||
}
|
||||
@@ -1043,9 +1088,9 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
"(nr_ue_procedures.c) vrb_to_prb_mapping=%d \n>>> mcs=%d\n>>> ndi=%d\n>>> rv=%d\n>>> harq_process_nbr=%d\n>>> dai=%d\n>>> "
|
||||
"scaling_factor_S=%f\n>>> tpc_pucch=%d\n>>> pucch_res_ind=%d\n>>> pdsch_to_harq_feedback_time_ind=%d\n",
|
||||
dlsch_pdu->vrb_to_prb_mapping,
|
||||
dlsch_pdu->mcs,
|
||||
dlsch_pdu->new_data_indicator,
|
||||
dlsch_pdu->rv,
|
||||
dlsch_pdu->cw_info[0].mcs,
|
||||
dlsch_pdu->cw_info[0].new_data_indicator,
|
||||
dlsch_pdu->cw_info[0].rv,
|
||||
dlsch_pdu->harq_process_nbr,
|
||||
dci->dai[0].val,
|
||||
dlsch_pdu->scaling_factor_S,
|
||||
@@ -1055,7 +1100,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
dlsch_pdu->k1_feedback = feedback_ti;
|
||||
|
||||
LOG_D(MAC, "(nr_ue_procedures.c) pdu_type=%d\n\n", dl_conf_req->pdu_type);
|
||||
LOG_D(MAC, "(nr_ue_procedures.c) pdu_type=%d\n", dl_conf_req->pdu_type);
|
||||
|
||||
// the prepared dci is valid, we add it in the list
|
||||
dl_config->number_pdus++;
|
||||
@@ -1213,9 +1258,6 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
dlsch_pdu->dmrsConfigType = dl_dmrs_config->dmrs_Type == NULL ? NFAPI_NR_DMRS_TYPE1 : NFAPI_NR_DMRS_TYPE2;
|
||||
|
||||
/* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214,
|
||||
using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */
|
||||
dlsch_pdu->n_dmrs_cdm_groups = 1;
|
||||
/* VRB_TO_PRB_MAPPING */
|
||||
if ((pdsch_Config->resourceAllocation == 1) && (pdsch_Config->vrb_ToPRB_Interleaver != NULL))
|
||||
dlsch_pdu->vrb_to_prb_mapping =
|
||||
@@ -1226,28 +1268,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
|
||||
dlsch_pdu->rate_matching_ind = dci->rate_matching_indicator.val;
|
||||
/* ZP_CSI_RS_TRIGGER */
|
||||
dlsch_pdu->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val;
|
||||
/* MCS (for transport block 1)*/
|
||||
dlsch_pdu->mcs = dci->mcs;
|
||||
/* NDI (for transport block 1)*/
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val];
|
||||
if (dci->ndi != current_harq->last_ndi) {
|
||||
// new data
|
||||
dlsch_pdu->new_data_indicator = true;
|
||||
current_harq->R = 0;
|
||||
current_harq->TBS = 0;
|
||||
}
|
||||
else {
|
||||
dlsch_pdu->new_data_indicator = false;
|
||||
}
|
||||
current_harq->last_ndi = dci->ndi;
|
||||
/* RV (for transport block 1)*/
|
||||
dlsch_pdu->rv = dci->rv;
|
||||
/* MCS (for transport block 2)*/
|
||||
dlsch_pdu->tb2_mcs = dci->mcs2.val;
|
||||
/* NDI (for transport block 2)*/
|
||||
dlsch_pdu->tb2_new_data_indicator = dci->ndi2.val;
|
||||
/* RV (for transport block 2)*/
|
||||
dlsch_pdu->tb2_rv = dci->rv2.val;
|
||||
|
||||
/* HARQ_PROCESS_NUMBER */
|
||||
dlsch_pdu->harq_process_nbr = dci->harq_pid.val;
|
||||
/* TPC_PUCCH */
|
||||
@@ -1276,13 +1297,32 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
|
||||
return -1;
|
||||
}
|
||||
|
||||
NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info;
|
||||
int nb_rb_oh;
|
||||
if (sc_info->xOverhead_PDSCH)
|
||||
nb_rb_oh = 6 * (1 + *sc_info->xOverhead_PDSCH);
|
||||
else
|
||||
nb_rb_oh = 0;
|
||||
|
||||
/* ANTENNA_PORTS */
|
||||
uint8_t n_codewords = 1; // FIXME!!!
|
||||
long *max_length = dl_dmrs_config->maxLength;
|
||||
long *dmrs_type = dl_dmrs_config->dmrs_Type;
|
||||
|
||||
// In case the higher layer parameter maxNrofCodeWordsScheduledByDCI indicates that two codeword transmission is enabled,
|
||||
// then one of the two transport blocks is disabled by DCI format 1_1
|
||||
// if IMCS = 26 and if rvid = 1 for the corresponding transport block
|
||||
bool cw0 = true;
|
||||
bool cw1 = true;
|
||||
if (pdsch_Config->maxNrofCodeWordsScheduledByDCI
|
||||
&& *pdsch_Config->maxNrofCodeWordsScheduledByDCI == NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n2) {
|
||||
cw0 = dci->rv != 1 || dci->mcs != 26;
|
||||
cw1 = dci->rv2.val != 1 || dci->mcs2.val != 26;
|
||||
} else
|
||||
cw1 = false;
|
||||
|
||||
dlsch_pdu->n_front_load_symb = 1; // default value
|
||||
set_antenna_port_parameters(dlsch_pdu, n_codewords, max_length, dmrs_type, dci->antenna_ports.val);
|
||||
set_antenna_port_parameters(dlsch_pdu, cw0 + cw1, max_length, dmrs_type, dci->antenna_ports.val);
|
||||
int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
|
||||
|
||||
/* dmrs symbol positions*/
|
||||
dlsch_pdu->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config,
|
||||
@@ -1293,6 +1333,105 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
|
||||
tda_info.mapping_type,
|
||||
dlsch_pdu->n_front_load_symb);
|
||||
|
||||
dlsch_pdu->mcs_table = get_dlsch_mcs_table(NR_DL_DCI_FORMAT_1_1,
|
||||
rnti_type,
|
||||
dci_ind->ss_type,
|
||||
pdsch_Config ? pdsch_Config->mcs_Table : NULL,
|
||||
NULL, // SPS not implemented,
|
||||
false, // as above
|
||||
NULL); // MCS-C-RNTI not implemented
|
||||
|
||||
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
|
||||
// according to TS 38.213 Table 9.2.3-1
|
||||
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing);
|
||||
uint16_t feedback_ti = 0;
|
||||
const int tpc[] = {-1, 0, 1, 3};
|
||||
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
|
||||
feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
|
||||
AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing),
|
||||
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
|
||||
"file (min_rxtxtime).\n",
|
||||
feedback_ti,
|
||||
GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing));
|
||||
}
|
||||
|
||||
|
||||
int number_rbs;
|
||||
if (dlsch_pdu->resource_alloc == 1) {
|
||||
number_rbs = dlsch_pdu->number_rbs;
|
||||
} else {
|
||||
uint32_t temp_bitmap[9];
|
||||
memcpy(temp_bitmap, dlsch_pdu->rb_bitmap, 36);
|
||||
number_rbs = count_bits(temp_bitmap, 9);
|
||||
}
|
||||
|
||||
int cw_idx = 0;
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = NULL;
|
||||
if (cw0) {
|
||||
current_harq = &mac->dl_harq_info[dci->harq_pid.val][0];
|
||||
if (get_cw_info(current_harq,
|
||||
dlsch_pdu,
|
||||
dl_conf_req->pdu_type,
|
||||
&dlsch_pdu->cw_info[0],
|
||||
number_rbs,
|
||||
nb_re_dmrs,
|
||||
nb_rb_oh,
|
||||
dci->rv,
|
||||
dci->mcs,
|
||||
dci->ndi,
|
||||
cw_idx)) {
|
||||
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
|
||||
mac->stats.dl.rounds[current_harq->round]++;
|
||||
// set the harq status at MAC for feedback
|
||||
set_harq_status(mac,
|
||||
dci->pucch_resource_indicator,
|
||||
dci->harq_pid.val,
|
||||
0,
|
||||
tpc[dci->tpc],
|
||||
feedback_ti,
|
||||
dci->dai[0].val,
|
||||
dci_ind->n_CCE,
|
||||
dci_ind->N_CCE,
|
||||
frame,
|
||||
slot);
|
||||
cw_idx++;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cw1) {
|
||||
current_harq = &mac->dl_harq_info[dci->harq_pid.val][cw_idx];
|
||||
if (get_cw_info(current_harq,
|
||||
dlsch_pdu,
|
||||
dl_conf_req->pdu_type,
|
||||
&dlsch_pdu->cw_info[1],
|
||||
number_rbs,
|
||||
nb_re_dmrs,
|
||||
nb_rb_oh,
|
||||
dci->rv2.val,
|
||||
dci->mcs2.val,
|
||||
dci->ndi2.val,
|
||||
cw_idx)) {
|
||||
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
|
||||
mac->stats.dl.rounds[current_harq->round]++;
|
||||
// set the harq status at MAC for feedback
|
||||
set_harq_status(mac,
|
||||
dci->pucch_resource_indicator,
|
||||
dci->harq_pid.val,
|
||||
1,
|
||||
tpc[dci->tpc],
|
||||
feedback_ti,
|
||||
dci->dai[0].val,
|
||||
dci_ind->n_CCE,
|
||||
dci_ind->N_CCE,
|
||||
frame,
|
||||
slot);
|
||||
cw_idx++;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
dlsch_pdu->n_codewords = cw_idx;
|
||||
/* TCI */
|
||||
if (dl_conf_req->dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1) {
|
||||
// 0 bit if higher layer parameter tci-PresentInDCI is not enabled
|
||||
@@ -1311,107 +1450,9 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
|
||||
/* DMRS_SEQ_INI */
|
||||
// FIXME!!!
|
||||
|
||||
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
|
||||
// according to TS 38.213 Table 9.2.3-1
|
||||
const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing);
|
||||
uint16_t feedback_ti = 0;
|
||||
|
||||
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
|
||||
feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
|
||||
AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing),
|
||||
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
|
||||
"file (min_rxtxtime).\n",
|
||||
feedback_ti,
|
||||
GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing));
|
||||
|
||||
// set the harq status at MAC for feedback
|
||||
const int tpc[] = {-1, 0, 1, 3};
|
||||
set_harq_status(mac,
|
||||
dci->pucch_resource_indicator,
|
||||
dci->harq_pid.val,
|
||||
tpc[dci->tpc],
|
||||
feedback_ti,
|
||||
dci->dai[0].val,
|
||||
dci_ind->n_CCE,
|
||||
dci_ind->N_CCE,
|
||||
frame,
|
||||
slot);
|
||||
}
|
||||
if (dlsch_pdu->new_data_indicator)
|
||||
current_harq->round = 0;
|
||||
else
|
||||
current_harq->round++;
|
||||
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
|
||||
mac->stats.dl.rounds[current_harq->round]++;
|
||||
// send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding
|
||||
dlsch_pdu->k1_feedback = feedback_ti;
|
||||
|
||||
dlsch_pdu->mcs_table = get_dlsch_mcs_table(NR_DL_DCI_FORMAT_1_1,
|
||||
rnti_type,
|
||||
dci_ind->ss_type,
|
||||
pdsch_Config ? pdsch_Config->mcs_Table : NULL,
|
||||
NULL, // SPS not implemented,
|
||||
false, // as above
|
||||
NULL); // MCS-C-RNTI not implemented
|
||||
dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
|
||||
if (dlsch_pdu->qamModOrder == 0) {
|
||||
LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
|
||||
return -1;
|
||||
}
|
||||
uint8_t Nl = 0;
|
||||
for (int i = 0; i < 12; i++) { // max 12 ports
|
||||
if ((dlsch_pdu->dmrs_ports >> i) & 0x01)
|
||||
Nl += 1;
|
||||
}
|
||||
|
||||
NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info;
|
||||
int nb_rb_oh;
|
||||
if (sc_info->xOverhead_PDSCH)
|
||||
nb_rb_oh = 6 * (1 + *sc_info->xOverhead_PDSCH);
|
||||
else
|
||||
nb_rb_oh = 0;
|
||||
int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups;
|
||||
|
||||
int number_rbs;
|
||||
if (dlsch_pdu->resource_alloc == 1) {
|
||||
number_rbs = dlsch_pdu->number_rbs;
|
||||
} else {
|
||||
uint32_t temp_bitmap[9];
|
||||
memcpy(temp_bitmap, dlsch_pdu->rb_bitmap, 36);
|
||||
number_rbs = count_bits(temp_bitmap, 9);
|
||||
}
|
||||
int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table);
|
||||
if (R > 0) {
|
||||
dlsch_pdu->targetCodeRate = R;
|
||||
dlsch_pdu->TBS = nr_compute_tbs(dlsch_pdu->qamModOrder,
|
||||
R,
|
||||
number_rbs,
|
||||
dlsch_pdu->number_symbols,
|
||||
nb_re_dmrs * get_num_dmrs(dlsch_pdu->dlDmrsSymbPos),
|
||||
nb_rb_oh,
|
||||
0,
|
||||
Nl);
|
||||
// storing for possible retransmissions
|
||||
if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) {
|
||||
LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n",
|
||||
dlsch_pdu->TBS, current_harq->TBS);
|
||||
dlsch_pdu->new_data_indicator = true; // treated as new data
|
||||
}
|
||||
current_harq->R = dlsch_pdu->targetCodeRate;
|
||||
current_harq->TBS = dlsch_pdu->TBS;
|
||||
}
|
||||
else {
|
||||
dlsch_pdu->targetCodeRate = current_harq->R;
|
||||
dlsch_pdu->TBS = current_harq->TBS;
|
||||
}
|
||||
|
||||
dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate);
|
||||
|
||||
if (dlsch_pdu->TBS == 0) {
|
||||
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TBS_LBRM according to section 5.4.2.1 of 38.212
|
||||
int max_mimo_layers = 0;
|
||||
if (sc_info->maxMIMO_Layers_PDSCH)
|
||||
@@ -1424,10 +1465,11 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
|
||||
/*PTRS configuration */
|
||||
dlsch_pdu->pduBitmap = 0;
|
||||
if (dl_dmrs_config->phaseTrackingRS != NULL) {
|
||||
AssertFatal(cw_idx == 1, "Cannot handle PTRS with 2 codewords\n");
|
||||
bool valid_ptrs_setup =
|
||||
set_dl_ptrs_values(dl_dmrs_config->phaseTrackingRS->choice.setup,
|
||||
number_rbs,
|
||||
dlsch_pdu->mcs,
|
||||
dlsch_pdu->cw_info[0].mcs,
|
||||
dlsch_pdu->mcs_table,
|
||||
&dlsch_pdu->PTRSFreqDensity,
|
||||
&dlsch_pdu->PTRSTimeDensity,
|
||||
@@ -2339,11 +2381,8 @@ bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sche
|
||||
|
||||
/* look for dl acknowledgment which should be done on current uplink slot */
|
||||
for (int code_word = 0; code_word < number_of_code_word; code_word++) {
|
||||
|
||||
for (int dl_harq_pid = 0; dl_harq_pid < num_dl_harq; dl_harq_pid++) {
|
||||
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid];
|
||||
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid][code_word];
|
||||
if (current_harq->active) {
|
||||
LOG_D(PHY, "HARQ pid %d is active for %d.%d\n",
|
||||
dl_harq_pid, current_harq->ul_frame, current_harq->ul_slot);
|
||||
|
||||
@@ -116,15 +116,22 @@ static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity
|
||||
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
|
||||
}
|
||||
|
||||
static void flush_harq_buffers(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
|
||||
for (int c = 0; c < 2; c++) {
|
||||
memset(&mac->dl_harq_info[k][c], 0, sizeof(NR_UE_DL_HARQ_STATUS_t));
|
||||
mac->dl_harq_info[k][c].last_ndi = -1; // initialize to invalid value
|
||||
}
|
||||
memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info));
|
||||
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
}
|
||||
}
|
||||
|
||||
void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// flush all HARQ buffers for all Serving Cells
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
|
||||
memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info));
|
||||
memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info));
|
||||
mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
}
|
||||
flush_harq_buffers(mac);
|
||||
// release PUCCH for all Serving Cells;
|
||||
// release SRS for all Serving Cells;
|
||||
release_PUCCH_SRS(mac);
|
||||
@@ -142,12 +149,7 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
|
||||
void handle_ulsync_loss(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
// flush all HARQ buffers for all Serving Cells
|
||||
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
|
||||
memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info));
|
||||
memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info));
|
||||
mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
|
||||
}
|
||||
flush_harq_buffers(mac);
|
||||
// clear any configured downlink assignments and uplink grants;
|
||||
if (mac->dl_config_request)
|
||||
memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request));
|
||||
|
||||
@@ -145,6 +145,7 @@ static int8_t handle_dlsch(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
|
||||
if (mac->ra.ra_state != nrRA_WAIT_RAR) // no HARQ for MSG2
|
||||
update_harq_status(mac,
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid,
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.cw_idx,
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack);
|
||||
if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack)
|
||||
nr_ue_send_sdu(mac, dl_info, pdu_id);
|
||||
@@ -167,9 +168,9 @@ static int8_t handle_l1_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int s
|
||||
return 0;
|
||||
}
|
||||
|
||||
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack)
|
||||
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, int cw_idx, uint8_t ack_nack)
|
||||
{
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid];
|
||||
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid][cw_idx];
|
||||
|
||||
if (current_harq->active) {
|
||||
LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack);
|
||||
|
||||
Reference in New Issue
Block a user