Commit ece9d51d authored by Bartosz Podrygajlo's avatar Bartosz Podrygajlo

Symbol based PDCCH processing

1. Refactor PDCCH PHY functions to take rxdataF of one OFDM symbol and
   produce LLR for each search space. The modified functions take
   rxdataF in a different format than that produced by nr_slot_fep(). So
   for now a memcpy is used to change the array structure. Once
   nr_slot_fep() is modified, this memcpy will no longer be needed and
   will be removed.
2. Modify DCI functions to decode DCI in the last PDCCH symbol and
   inidcate to MAC once.
3. Fix PDCCH monitoring for start symbol > 0.
4. Fix multiple PDCCH monitoring within slot.
Co-authored-by: default avatarSakthivel Velumani <mail@sakthi.me>
parent 07ce1ed1
......@@ -73,6 +73,7 @@ typedef struct {
/// frequency_domain_resource;
uint8_t frequency_domain_resource[6];
uint8_t StartSymbolIndex;
uint16_t StartSymbolBitmap;
uint8_t duration;
uint8_t CceRegMappingType; // interleaved or noninterleaved
uint8_t RegBundleSize; // valid if CCE to REG mapping type is interleaved type
......
......@@ -805,17 +805,12 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
uint16_t BWPStart,
int32_t pdcch_est_size,
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size])
{
int slot = proc->nr_slot_rx;
unsigned char aarx;
unsigned short k;
unsigned int pilot_cnt;
int ch_offset,symbol_offset;
ch_offset = ue->frame_parms.ofdm_symbol_size*symbol;
symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
int nb_rb_coreset=0;
int coreset_start_rb=0;
......@@ -830,8 +825,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12;
#ifdef DEBUG_PDCCH
printf("PDCCH Channel Estimation : ch_offset %d, OFDM size %d, Ncp=%d, slot=%d, symbol %d\n",
ch_offset,
printf("PDCCH Channel Estimation : OFDM size %d, Ncp=%d, slot=%d, symbol %d\n",
ue->frame_parms.ofdm_symbol_size,
ue->frame_parms.Ncp,
slot,
......@@ -858,8 +852,8 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
k = coreset_start_subcarrier;
c16_t *pil = &pilot[dmrs_ref * 3];
c16_t *rxF = &rxdataF[aarx][symbol_offset + k + 1];
c16_t *dl_ch = &pdcch_dl_ch_estimates[aarx][ch_offset];
c16_t *rxF = &rxdataF[aarx][k + 1];
c16_t *dl_ch = &pdcch_dl_ch_estimates[aarx][0];
memset(dl_ch, 0, sizeof(c16_t) * ue->frame_parms.ofdm_symbol_size);
......@@ -879,29 +873,29 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
if (k >= ue->frame_parms.ofdm_symbol_size) {
k -= ue->frame_parms.ofdm_symbol_size;
rxF = &rxdataF[aarx][(symbol_offset + k + 1)];
rxF = &rxdataF[aarx][k + 1];
}
multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
rxF = (c16_t *)&rxdataF[aarx][k + 1)];
multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
dl_ch += 12;
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
rxF = (c16_t *)&rxdataF[aarx][k + 1];
for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) {
multadd_real_vector_complex_scalar(fl, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
rxF = (c16_t *)&rxdataF[aarx][k + 1];
multadd_real_vector_complex_scalar(fm, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
rxF = (c16_t *)&rxdataF[aarx][k + 1];
multadd_real_vector_complex_scalar(fr, c16mulShift(*pil++, *rxF, 15), dl_ch, 16);
dl_ch += 12;
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
rxF = (c16_t *)&rxdataF[aarx][k + 1];
}
#else //ELSE CH_INTERP
c32_t ch_sum = {0, 0};
......@@ -915,7 +909,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
ch_sum.r += ch.r;
ch_sum.i += ch.i;
k = (k + 4) % ue->frame_parms.ofdm_symbol_size;
rxF = (c16_t *)&rxdataF[aarx][(symbol_offset + k + 1)];
rxF = (c16_t *)&rxdataF[aarx][k + 1];
if (pilot_cnt % 3 == 2) {
ch.r = ch_sum.r / 3;
......
......@@ -52,7 +52,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
uint16_t BWPStart,
int32_t pdcch_est_size,
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size]);
c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp,
const UE_nr_rxtx_proc_t *proc,
......
This diff is collapsed.
......@@ -69,6 +69,12 @@ typedef struct pdsch_scope_req_s {
void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations);
void nr_conjch0_mult_ch1(c16_t *ch0, c16_t *ch1, c16_t *ch0conj_ch1, unsigned short nb_rb, unsigned char output_shift0);
void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb);
int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]);
int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config);
/** \brief This is the alternative top-level entry point for DLSCH decoding in UE.
It handles all the HARQ processes in only one call. The routine first
computes the segmentation information and then call LDPC decoder on the
......@@ -180,14 +186,6 @@ void nr_dlsch_unscrambling(int16_t* llr,
uint32_t Nid,
uint32_t n_RNTI);
void nr_rx_pdcch(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
int32_t pdcch_est_size,
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
c16_t *pdcch_e_rx,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
/*! \brief Performs detection of SSS to find cell ID and other framing parameters (FDD/TDD, normal/extended prefix)
@param phy_vars_ue Pointer to UE variables
@param tot_metric Pointer to variable containing maximum metric under framing hypothesis (to be compared to other hypotheses
......@@ -279,12 +277,6 @@ void nr_sl_rf_card_config_freq(PHY_VARS_NR_UE *ue,
openair0_config_t *openair0_cfg,
int freq_offset);
void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t *pdcch_e_rx,
fapi_nr_dci_indication_t *dci_ind,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15);
/** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel
estimation. It performs
- RB extraction (signal and channel estimates)
......
......@@ -138,13 +138,22 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
void *typeSpecific,
uint8_t *b);
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
int32_t pdcch_est_size,
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
int symbol,
nr_phy_data_t *phy_data,
int n_ss,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
int llr_size_symbol,
int num_monitoring_occ,
int max_symb,
c16_t rxdataF[ue->frame_parms.nb_antennas_rx][ue->frame_parms.ofdm_symbol_size],
c16_t pdcch_llr[phy_data->phy_pdcch_config.nb_search_space][num_monitoring_occ][max_symb * llr_size_symbol]);
void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
int llr_size,
int max_monOcc,
PHY_VARS_NR_UE *ue,
nr_phy_data_t *phy_data,
c16_t llr[phy_data->phy_pdcch_config.nb_search_space][max_monOcc][llr_size]);
void nr_ue_csi_im_procedures(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
......
......@@ -527,53 +527,6 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
return ret;
}
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
int32_t pdcch_est_size,
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[n_ss];
start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
/// PDCCH/DCI e-sequence (input to rate matching).
int32_t pdcch_e_rx_size = NR_MAX_PDCCH_SIZE;
c16_t pdcch_e_rx[pdcch_e_rx_size];
nr_rx_pdcch(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, pdcch_e_rx, rel15, rxdataF);
fapi_nr_dci_indication_t dci_ind;
nr_dci_decoding_procedure(ue, proc, pdcch_e_rx, &dci_ind, rel15);
for (int i = 0; i < dci_ind.number_of_dcis; i++) {
LOG_D(PHY,
"[UE %d] AbsSubFrame %d.%d: DCI %i of %d total DCIs found --> rnti %x : format %d\n",
ue->Mod_id,
frame_rx % 1024,
nr_slot_rx,
i + 1,
dci_ind.number_of_dcis,
dci_ind.dci_list[i].rnti,
dci_ind.dci_list[i].dci_format);
}
nr_downlink_indication_t dl_indication;
// fill dl_indication message
nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
// send to mac
ue->if_inst->dl_indication(&dl_indication);
stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_OUT);
return (dci_ind.number_of_dcis);
}
static freq_alloc_bitmap_t set_start_end_from_bitmap(int size, int alloc_size, const uint8_t bitmap[alloc_size])
{
freq_alloc_bitmap_t alloc = {
......@@ -1027,46 +980,68 @@ static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index)
return ue->frame_parms.ssb_index == index;
}
static int get_pdcch_max_rbs(NR_UE_PDCCH_CONFIG *phy_pdcch_config)
{
int nb_rb = 0;
int rb_offset = 0;
for (int i = 0; i < phy_pdcch_config->nb_search_space; i++) {
int tmp = 0;
get_coreset_rballoc(phy_pdcch_config->pdcch_config[i].coreset.frequency_domain_resource, &tmp, &rb_offset);
if (tmp > nb_rb)
nb_rb = tmp;
}
return nb_rb;
}
static int get_max_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config)
{
int max_pdcch_symb = 0;
for (int i = 0; i < phy_pdcch_config->nb_search_space; i++)
if (phy_pdcch_config->pdcch_config[i].coreset.duration > max_pdcch_symb)
max_pdcch_symb = phy_pdcch_config->pdcch_config[i].coreset.duration;
return max_pdcch_symb;
}
void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
{
TracyCZone(ctx);
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
TracyCZone(ctx, true);
/* process PDCCH */
LOG_D(PHY, " ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", proc->frame_rx % 1024, proc->nr_slot_rx);
start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config;
int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config);
int max_nb_symb_pdcch = get_max_pdcch_symb(phy_pdcch_config);
int llr_size_symbol = get_pdcch_max_rbs(phy_pdcch_config) * 9;
c16_t pdcch_llr[phy_pdcch_config->nb_search_space][num_monitoring_occ][max_nb_symb_pdcch * llr_size_symbol];
int start_symb_pdcch, last_symb_pdcch;
set_first_last_pdcch_symb(phy_pdcch_config, &start_symb_pdcch, &last_symb_pdcch);
/* Temporarily loop over symbols in the slot, perform OFDM demod and process PDCCH.
When symbol based proc design is fully merged, this function will be called to process only one symbol
and OFDM demod will be removed from here. */
const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP;
__attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
__attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz];
uint8_t nb_symb_pdcch = phy_pdcch_config->nb_search_space > 0 ? phy_pdcch_config->pdcch_config[0].coreset.duration : 0;
int first_symb_pdcch = phy_pdcch_config->nb_search_space > 0 ? phy_pdcch_config->pdcch_config[0].coreset.StartSymbolIndex : 0;
int last_symb_pdcch = first_symb_pdcch + nb_symb_pdcch;
for (int l = first_symb_pdcch; l < last_symb_pdcch; l++) {
nr_slot_fep(ue, fp, proc->nr_slot_rx, l, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
}
for (int symbol = start_symb_pdcch; symbol <= last_symb_pdcch; symbol++) {
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
nr_slot_fep(ue, fp, proc->nr_slot_rx, symbol, rxdataF, link_type_dl, 0, ue->common_vars.rxdata);
__attribute__((aligned(32))) c16_t rxdataF_symb[fp->nb_antennas_rx][((fp->ofdm_symbol_size + 7) / 8) * 8];
// Hold the channel estimates in frequency domain.
int32_t pdcch_est_size = ((((fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH))+15)/16)*16);
__attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size];
uint8_t dci_cnt = 0;
for(int n_ss = 0; n_ss<phy_pdcch_config->nb_search_space; n_ss++) {
for (int l = first_symb_pdcch; l < last_symb_pdcch; l++) {
// note: this only works if RBs for PDCCH are contigous!
nr_pdcch_channel_estimation(ue,
proc,
l,
&phy_pdcch_config->pdcch_config[n_ss].coreset,
fp->first_carrier_offset,
phy_pdcch_config->pdcch_config[n_ss].BWPStart,
pdcch_est_size,
pdcch_dl_ch_estimates,
rxdataF);
for (int ant = 0; ant < fp->nb_antennas_rx; ant++)
memcpy(rxdataF_symb[ant], &rxdataF[ant][symbol * fp->ofdm_symbol_size], sizeof(c16_t) * fp->ofdm_symbol_size);
nr_pdcch_generate_llr(ue, proc, symbol, phy_data, llr_size_symbol, num_monitoring_occ, max_nb_symb_pdcch, rxdataF_symb, pdcch_llr);
if (symbol == last_symb_pdcch) {
nr_pdcch_dci_indication(proc, llr_size_symbol * max_nb_symb_pdcch, num_monitoring_occ, ue, phy_data, pdcch_llr);
UEscopeCopy(ue, pdcchLlr, pdcch_llr, sizeof(c16_t), 1, sizeof(pdcch_llr), 0);
}
dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF);
}
LOG_D(PHY, "[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, proc->frame_rx, proc->nr_slot_rx, dci_cnt);
phy_pdcch_config->nb_search_space = 0;
stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS);
TracyCZoneEnd(ctx);
if (ue->phy_sim_rxdataF)
memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size);
memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * max_nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size);
}
int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data)
......
......@@ -110,17 +110,6 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
{
}
int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
int32_t pdcch_est_size,
c16_t pdcch_dl_ch_estimates[][pdcch_est_size],
nr_phy_data_t *phy_data,
int n_ss,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
return 0;
}
configmodule_interface_t *uniqCfg = NULL;
int main(int argc, char **argv)
{
......
......@@ -307,12 +307,7 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac,
break;
}
for (int i = 0; i < sps; i++) {
if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) {
rel15->coreset.StartSymbolIndex = i;
break;
}
}
rel15->coreset.StartSymbolBitmap = monitoringSymbolsWithinSlot;
uint32_t Y = 0;
if (ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific)
Y = get_Y(ss, slot, rel15->rnti);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment