type0 DLSCH frequency allocation for channel estimation

This commit is contained in:
francescomani
2025-10-13 10:57:49 +02:00
parent e70a2b3cc1
commit 99e4f54d61
5 changed files with 122 additions and 51 deletions
@@ -938,6 +938,7 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
}
void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
const freq_alloc_bitmap_t *freq_alloc,
c16_t *rxF,
c16_t *pil,
c16_t *dl_ch,
@@ -948,45 +949,49 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
{
c16_t *dl_ch0 = dl_ch;
int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size;
c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
memset(dl_ls_est, 0, sizeof(dl_ls_est));
int nest_count = 0;
uint64_t noise_amp2 = 0;
for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt += 2) {
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
int idx = 0;
for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) {
bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01;
if (allocated_rb) {
for (int pilot_cnt = 0; pilot_cnt < 6; pilot_cnt += 2) {
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
#ifdef DEBUG_PDSCH
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i);
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i);
#endif
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
#ifdef DEBUG_PDSCH
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
#endif
c16_t ch = c16addShift(ch_l, ch_r, 1);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) {
dl_ls_est[k] = ch;
c16_t ch = c16addShift(ch_l, ch_r, 1);
pil++;
re_offset = (re_offset + 2) % frame_parms->ofdm_symbol_size;
for (int k = 0; k < 4; k++) {
dl_ls_est[idx] = ch;
idx++;
}
}
} else {
pil += 6;
re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size;
}
}
c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
nr_est_delay(frame_parms->ofdm_symbol_size, dl_ls_est, ch_estimates_time, delay);
int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP);
c16_t *dl_delay_table = frame_parms->delay_table[delay_idx];
for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) {
for (int pilot_cnt = 0; pilot_cnt < idx >> 1; pilot_cnt++) {
int k = pilot_cnt << 1;
c16_t ch = c16mulShift(dl_ls_est[k], dl_delay_table[k], 8);
if (pilot_cnt == 0) { // Treat first pilot
c16multaddVectRealComplex(filt16_ul_p0, &ch, dl_ch, 16);
} else if (pilot_cnt == 1 || pilot_cnt == 2) {
c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16);
} else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot
} else if (pilot_cnt == (idx >> 1) - 1) { // Treat last pilot
c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16);
} else { // Treat middle pilots
c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16);
@@ -998,9 +1003,11 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
// Revert delay
dl_ch = dl_ch0;
int nest_count = 0;
uint64_t noise_amp2 = 0;
int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
c16_t *dl_inv_delay_table = frame_parms->delay_table[inv_delay_idx];
for (int k = 0; k < 12 * nb_rb_pdsch; k++) {
for (int k = 0; k < idx; k++) {
dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8);
noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k]));
nest_count++;
@@ -1096,6 +1103,7 @@ void NFAPI_NR_DMRS_TYPE1_average_prb(NR_DL_FRAME_PARMS *frame_parms,
}
void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
const freq_alloc_bitmap_t *freq_alloc,
c16_t *rxF,
c16_t *pil,
c16_t *dl_ch,
@@ -1106,45 +1114,50 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
{
int re_offset = bwp_start_subcarrier % frame_parms->ofdm_symbol_size;
c16_t *dl_ch0 = dl_ch;
c16_t dl_ls_est[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
memset(dl_ls_est, 0, sizeof(dl_ls_est));
int nest_count = 0;
uint64_t noise_amp2 = 0;
for (int pilot_cnt = 0; pilot_cnt < 4 * nb_rb_pdsch; pilot_cnt += 2) {
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
int idx = 0;
for (int rb = freq_alloc->start; rb < freq_alloc->start + nb_rb_pdsch; rb++) {
bool allocated_rb = (freq_alloc->bitmap[rb / 8] >> (rb % 8)) & 0x01;
if (allocated_rb) {
for (int pilot_cnt = 0; pilot_cnt < 4; pilot_cnt += 2) {
c16_t ch_l = c16mulShift(*pil, rxF[re_offset], 15);
#ifdef DEBUG_PDSCH
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i);
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_l.r, ch_l.i);
#endif
pil++;
re_offset = (re_offset + 1) % frame_parms->ofdm_symbol_size;
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
pil++;
re_offset = (re_offset + 1) % frame_parms->ofdm_symbol_size;
c16_t ch_r = c16mulShift(*pil, rxF[re_offset], 15);
#ifdef DEBUG_PDSCH
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
printf("pilot %3d: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d) \n", pilot_cnt + 1, pil->r, pil->i, rxF[re_offset].r, rxF[re_offset].i, ch_r.r, ch_r.i);
#endif
c16_t ch = c16addShift(ch_l, ch_r, 1);
for (int k = 3 * pilot_cnt; k < (3 * pilot_cnt) + 6; k++) {
dl_ls_est[k] = ch;
c16_t ch = c16addShift(ch_l, ch_r, 1);
pil++;
re_offset = (re_offset + 5) % frame_parms->ofdm_symbol_size;
for (int k = 0; k < 6; k++) {
dl_ls_est[idx] = ch;
idx++;
}
}
} else {
pil += 4;
re_offset = (re_offset + 12) % frame_parms->ofdm_symbol_size;
}
pil++;
re_offset = (re_offset + 5) % frame_parms->ofdm_symbol_size;
}
c16_t ch_estimates_time[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
nr_est_delay(frame_parms->ofdm_symbol_size, dl_ls_est, ch_estimates_time, delay);
int delay_idx = get_delay_idx(delay->est_delay, MAX_DELAY_COMP);
c16_t *dl_delay_table = frame_parms->delay_table[delay_idx];
for (int pilot_cnt = 0; pilot_cnt < 6 * nb_rb_pdsch; pilot_cnt++) {
int k = (pilot_cnt / 3) * 6;
// kept the same as before but unclear why would it be nb_rb_pdsch / 2 and not / 3
for (int pilot_cnt = 0; pilot_cnt < idx >> 1; pilot_cnt++) {
int k = pilot_cnt << 1;
c16_t ch = c16mulShift(dl_ls_est[k], dl_delay_table[k], 8);
if (pilot_cnt == 0) { // Treat first pilot
c16multaddVectRealComplex(filt16_ul_p0, &ch, dl_ch, 16);
} else if (pilot_cnt == 1 || pilot_cnt == 2) {
c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16);
} else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot
} else if (pilot_cnt == (idx >> 1) - 1) { // Treat last pilot
c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16);
} else { // Treat middle pilots
c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16);
@@ -1156,9 +1169,11 @@ void NFAPI_NR_DMRS_TYPE2_linear_interp(NR_DL_FRAME_PARMS *frame_parms,
// Revert delay
dl_ch = dl_ch0;
int nest_count = 0;
uint64_t noise_amp2 = 0;
int inv_delay_idx = get_delay_idx(-delay->est_delay, MAX_DELAY_COMP);
c16_t *dl_inv_delay_table = frame_parms->delay_table[inv_delay_idx];
for (int k = 0; k < 12 * nb_rb_pdsch; k++) {
for (int k = 0; k < idx; k++) {
dl_ch[k] = c16mulShift(dl_ch[k], dl_inv_delay_table[k], 8);
noise_amp2 += c16amp2(c16sub(dl_ls_est[k], dl_ch[k]));
nest_count++;
@@ -1256,6 +1271,7 @@ void NFAPI_NR_DMRS_TYPE2_average_prb(NR_DL_FRAME_PARMS *frame_parms,
void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch,
const freq_alloc_bitmap_t *freq_alloc,
int nl,
unsigned short p,
unsigned char symbol,
@@ -1270,7 +1286,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
const int ch_offset = fp->ofdm_symbol_size * symbol;
const int symbol_offset = fp->ofdm_symbol_size * symbol;
int bwp_start_subcarrier = ue->frame_parms.first_carrier_offset + (dlsch->BWPStart + dlsch->start_rb) * 12;
int bwp_start_subcarrier = fp->first_carrier_offset + (dlsch->BWPStart + freq_alloc->start) * 12;
#ifdef DEBUG_PDSCH
printf(
@@ -1287,8 +1303,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
// generate pilot for gNB port number 1000+p
int config_type = dlsch->dmrsConfigType;
int rb_offset = dlsch->start_rb + (dlsch->refPoint ? 0 : dlsch->BWPStart);
int nb_rb_pdsch = dlsch->number_rbs;
int rb_offset = freq_alloc->start + (dlsch->refPoint ? 0 : dlsch->BWPStart);
int nb_rb_pdsch = freq_alloc->end - freq_alloc->start + 1;
int8_t delta = get_delta(p, config_type);
c16_t pilot[3280] __attribute__((aligned(16)));
// Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS
@@ -1311,7 +1327,8 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
memset(dl_ch, 0, sizeof(*dl_ch) * fp->ofdm_symbol_size);
if (config_type == NFAPI_NR_DMRS_TYPE1 && ue->chest_freq == 0) {
NFAPI_NR_DMRS_TYPE1_linear_interp(&ue->frame_parms,
NFAPI_NR_DMRS_TYPE1_linear_interp(fp,
freq_alloc,
rxF,
&pilot[6 * rb_offset],
dl_ch,
@@ -1322,6 +1339,7 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
} else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->chest_freq == 0) {
NFAPI_NR_DMRS_TYPE2_linear_interp(fp,
freq_alloc,
rxF,
&pilot[4 * rb_offset],
dl_ch,
@@ -1331,9 +1349,11 @@ void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
nvar);
} else if (config_type == NFAPI_NR_DMRS_TYPE1) {
AssertFatal(dlsch->resource_alloc == 1, "PRB average in channel estimation not supported for type0 DLSCH\n");
NFAPI_NR_DMRS_TYPE1_average_prb(fp, rxF, &pilot[6 * rb_offset], dl_ch, bwp_start_subcarrier, nb_rb_pdsch);
} else {
AssertFatal(dlsch->resource_alloc == 1, "PRB average in channel estimation not supported for type0 DLSCH\n");
NFAPI_NR_DMRS_TYPE2_average_prb(fp, rxF, &pilot[4 * rb_offset], dl_ch, bwp_start_subcarrier, nb_rb_pdsch);
}
@@ -81,6 +81,7 @@ int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp,
void nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
const fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch,
const freq_alloc_bitmap_t *freq_alloc,
int nl,
unsigned short p,
unsigned char symbol,
@@ -67,7 +67,6 @@ typedef struct pdsch_scope_req_s {
/** \brief This function initialises structures for DLSCH at UE
*/
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);
/** \brief This is the alternative top-level entry point for DLSCH decoding in UE.
@@ -38,6 +38,12 @@
#include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h"
#include "../NR_TRANSPORT/nr_transport_common_proto.h"
typedef struct {
int start;
int end;
uint8_t bitmap[36];
} freq_alloc_bitmap_t;
typedef struct {
/// Index of current HARQ round for this ULSCH
uint8_t round;
+48 -3
View File
@@ -577,6 +577,43 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
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 = {
.start = size,
.end = 0
};
for (int start = 0; start < size; start++) {
if ((bitmap[start / 8] >> start % 8) & 0x1) {
alloc.start = start;
break;
}
}
AssertFatal(alloc.start < size, "Frequency allocation bitmap empty\n");
for (int end = size - 1; end > 0; end--) {
if ((bitmap[end / 8] >> end % 8) & 0x1) {
alloc.end = end;
break;
}
}
AssertFatal(alloc.end > 0, "Frequency allocation bitmap empty\n");
memcpy(alloc.bitmap, bitmap, alloc_size * sizeof(uint8_t));
return alloc;
}
static freq_alloc_bitmap_t set_bitmap_from_start_size(int start, int size)
{
freq_alloc_bitmap_t alloc = {
.start = start,
.end = start + size - 1
};
memset(alloc.bitmap, 0, 36 * sizeof(uint8_t));
for (int i = start; i < size + start; i++)
alloc.bitmap[i / 8] += 1 << (i % 8);
return alloc;
}
static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
NR_UE_DLSCH_t dlsch[2],
@@ -595,8 +632,15 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
// 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];
freq_alloc_bitmap_t freq_alloc = {0};
if (dlschCfg->resource_alloc == 0) {
int alloc_size = (dlschCfg->BWPSize / 8) + (dlschCfg->BWPSize % 8 > 0);
freq_alloc = set_start_end_from_bitmap(dlschCfg->BWPSize, alloc_size, dlschCfg->rb_bitmap);
} else
freq_alloc = set_bitmap_from_start_size(dlschCfg->start_rb, dlschCfg->number_rbs);
LOG_D(PHY,
"[UE %d] frame_rx %d, nr_slot_rx %d, harq_pid %d (%d), BWP start %d, rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask "
"[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 %d, DMRS mask "
"%x, Nl %d\n",
ue->Mod_id,
frame_rx,
@@ -604,8 +648,8 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
harq_pid,
dlsch0_harq->status,
dlschCfg->BWPStart,
dlschCfg->start_rb,
dlschCfg->number_rbs,
freq_alloc.start,
freq_alloc.end,
dlschCfg->start_symbol,
dlschCfg->number_symbols,
dlschCfg->dlDmrsSymbPos,
@@ -642,6 +686,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
nr_pdsch_channel_estimation(ue,
proc,
dlschCfg,
&freq_alloc,
nl,
get_dmrs_port(nl, dlschCfg->dmrs_ports),
m,