Commit d017afad authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/NR_UE_pusch_optimization' into integration_2024_w38b

parents 05bb40d7 321a20ea
......@@ -318,10 +318,10 @@ void nr_layer_mapping(int nbCodes,
}
}
void nr_ue_layer_mapping(const c16_t *mod_symbs, const int n_layers, const int n_symbs, int sz, c16_t tx_layers[][sz])
void nr_ue_layer_mapping(const c16_t *mod_symbs, const int n_layers, const int n_symbs, c16_t tx_layers[][n_symbs])
{
for (int i=0; i<n_symbs/n_layers; i++) {
for (int l=0; l<n_layers; l++) {
for (int l = 0; l < n_layers; l++) {
for (int i = 0; i < n_symbs; i++) {
tx_layers[l][i] = c16mulRealShift(mod_symbs[n_layers * i + l], AMP, 15);
}
}
......
......@@ -69,7 +69,7 @@ void nr_layer_mapping(int nbCodes,
@param[in] n_symbs, number of modulated symbols
@param[out] tx_layers, modulated symbols for each layer
*/
void nr_ue_layer_mapping(const c16_t *mod_symbs, const int n_layers, const int n_symbs, int sz, c16_t tx_layers[][sz]);
void nr_ue_layer_mapping(const c16_t *mod_symbs, const int n_layers, const int n_symbs, c16_t tx_layers[][n_symbs]);
/*!
\brief This function implements the OFDM front end processor on reception (FEP)
\param frame_parms Pointer to frame parameters
......
......@@ -85,6 +85,13 @@ void set_ptrs_symb_idx(uint16_t *ptrs_symbols,
}
}
unsigned int get_first_ptrs_re(const rnti_t rnti, const uint8_t K_ptrs, const uint16_t nRB, const uint8_t k_RE_ref)
{
const uint16_t nRB_Kptrs = nRB % K_ptrs;
const uint16_t k_RB_ref = nRB_Kptrs ? (rnti % nRB_Kptrs) : (rnti % K_ptrs);
return (k_RE_ref + k_RB_ref * NR_NB_SC_PER_RB);
}
/*******************************************************************
*
* NAME : is_ptrs_subcarrier
......
......@@ -53,6 +53,8 @@ void set_ptrs_symb_idx(uint16_t *ptrs_symbols,
uint8_t L_ptrs,
uint16_t dmrs_symb_pos);
unsigned int get_first_ptrs_re(const rnti_t rnti, const uint8_t K_ptrs, const uint16_t nRB, const uint8_t k_RE_ref);
uint8_t is_ptrs_subcarrier(uint16_t k,
uint16_t n_rnti,
uint8_t K_ptrs,
......
......@@ -116,6 +116,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
&harq_process->Z,
&harq_process->F,
harq_process->BG);
stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS);
impp.n_segments = harq_process->C;
impp.K = harq_process->K;
impp.Kr = impp.K;
......@@ -126,7 +127,6 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B);
return(-1);
}
stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT);
#ifdef DEBUG_ULSCH_CODING
......@@ -149,19 +149,22 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
}
start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
if (ldpc_interface_offload.LDPCencoder) {
for (int j = 0; j < impp.n_segments; j++) {
impp.perCB[j].E_cb = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, j);
}
start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
ldpc_interface_offload.LDPCencoder(harq_process->c, &harq_process->f, &impp);
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
} else {
if (ulsch->pusch_pdu.pusch_data.new_data_indicator) {
start_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
for (int j = 0; j < (impp.n_segments / 8 + 1); j++) {
impp.macro_num = j;
impp.Kr = impp.K;
ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp);
}
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT);
#ifdef DEBUG_ULSCH_CODING
......@@ -169,7 +172,6 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
write_output("ulsch_enc_output0.m", "enc0", &harq_process->d[0][0], (3 * 8 * Kr_bytes) + 12, 1, 4);
#endif
}
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
///////////////////////////////////////////////////////////////////////////////
for (int r = 0; r < impp.n_segments; r++) { // looping over C segments
if (impp.F > 0) {
......
......@@ -85,6 +85,382 @@ void nr_pusch_codeword_scrambling(uint8_t *in, uint32_t size, uint32_t Nid, uint
nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out);
}
/*
The function pointers are set once before calling the mapping funcion for
all symbols based on different parameters. Then the mapping is done for
each symbol by calling the function pointers.
*/
static void (*map_dmrs_ptr)(const unsigned int, const c16_t *, c16_t *);
static void (*map_data_dmrs_ptr)(const unsigned int num_cdm_no_data, const c16_t *, c16_t *);
/*
The following set of functions map dmrs and/or data REs in one RB based on
configuration of DMRS type, number of CDM groups with no data and delta.
For all other combinations of the parameters not present below is not
applicable.
*/
/*
DMRS mapping in a RB for Type 1.
Mapping as in TS 38.211 6.4.1.1.3 k = 4n + 2k^prime + delta
*/
static void map_dmrs_type1_cdm1_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out)
{
*(out + delta) = *dmrs++;
*(out + delta + 2) = *dmrs++;
*(out + delta + 4) = *dmrs++;
*(out + delta + 6) = *dmrs++;
*(out + delta + 8) = *dmrs++;
*(out + delta + 10) = *dmrs++;
}
/*
Data in DMRS symbol for Type 1, NumCDMGroupNoData = 1 and delta 0 (antenna port 0 and 1).
There is no data in DMRS symbol for other scenarios in type 1.
*/
static void map_data_dmrs_type1_cdm1_rb(const unsigned int num_cdm_no_data, const c16_t *data, c16_t *out)
{
*(out + 1) = *data++;
*(out + 3) = *data++;
*(out + 5) = *data++;
*(out + 7) = *data++;
*(out + 9) = *data++;
*(out + 11) = *data++;
}
#define NR_DMRS_TYPE2_CDM_GRP_SIZE 2
#define NR_DMRS_TYPE2_NUM_CDM_GRP 3
/*
Map DMRS for type 2
Mapping as in TS 38.211 6.4.1.1.3 k = 6n + k^prime + delta
*/
static void map_dmrs_type2_rb(const unsigned int delta, const c16_t *dmrs, c16_t *out)
{
memcpy(out + delta, dmrs, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE);
out += (NR_DMRS_TYPE2_CDM_GRP_SIZE * NR_DMRS_TYPE2_NUM_CDM_GRP);
dmrs += NR_DMRS_TYPE2_CDM_GRP_SIZE;
memcpy(out + delta, dmrs, sizeof(c16_t) * NR_DMRS_TYPE2_CDM_GRP_SIZE);
}
/*
Map data for type 2 DMRS
*/
static void map_data_dmrs_type2_rb(const unsigned int num_cdm_no_data, const c16_t *data, c16_t *out)
{
unsigned int offset = num_cdm_no_data * NR_DMRS_TYPE2_CDM_GRP_SIZE;
const unsigned int size = (NR_DMRS_TYPE2_NUM_CDM_GRP - num_cdm_no_data) * NR_DMRS_TYPE2_CDM_GRP_SIZE;
memcpy(out + offset, data, sizeof(c16_t) * size);
offset += NR_DMRS_TYPE2_CDM_GRP_SIZE * NR_DMRS_TYPE2_NUM_CDM_GRP;
data += size;
memcpy(out + offset, data, sizeof(c16_t) * size);
}
/*
Map data and PTRS in RB
*/
static void map_data_ptrs(const unsigned int ptrsIdx, const c16_t *data, const c16_t *ptrs, c16_t *out)
{
memcpy(out, data, sizeof(c16_t) * ptrsIdx);
data += ptrsIdx;
*(out + ptrsIdx) = *ptrs;
memcpy(out + ptrsIdx + 1, data, sizeof(c16_t) * NR_NB_SC_PER_RB - ptrsIdx - 1);
}
/*
Map data only in RB
*/
static void map_data_rb(const c16_t *data, c16_t *out)
{
memcpy(out, data, sizeof(c16_t) * NR_NB_SC_PER_RB);
}
/*
This function is used when a PRB is on both sides of DC.
The destination buffer in this case in not contiguous so REs are mapped on to a temporary buffer
so that we can reuse the existing functions. Then it is copied to the destination buffer.
*/
static void map_over_dc(const unsigned int right_dc,
const unsigned int num_cdm_no_data,
const unsigned int fft_size,
const unsigned int dmrs_per_rb,
const unsigned int data_per_rb,
const unsigned int delta,
const unsigned int ptrsIdx,
const c16_t **ptrs,
const c16_t **dmrs,
const c16_t **data,
c16_t **out)
{
// if first RE is DC no need to map in this function
if (right_dc == 0)
return;
c16_t *out_tmp = *out;
c16_t tmp_out_buf[NR_NB_SC_PER_RB];
const unsigned int left_dc = NR_NB_SC_PER_RB - right_dc;
/* copy out to temp buffer. incase we want to preserve the REs in the out buffer
as we call mapping of data in DMRS symbol after mapping DMRS REs
*/
memcpy(tmp_out_buf, out_tmp, sizeof(c16_t) * left_dc);
out_tmp -= (fft_size - left_dc);
memcpy(tmp_out_buf + left_dc, out_tmp, sizeof(c16_t) * right_dc);
/* map on to temp buffer */
if (dmrs && data) {
map_data_dmrs_ptr(num_cdm_no_data, *data, tmp_out_buf);
*data += data_per_rb;
} else if (dmrs) {
map_dmrs_ptr(delta, *dmrs, tmp_out_buf);
*dmrs += dmrs_per_rb;
} else if (ptrs) {
map_data_ptrs(ptrsIdx, *data, *ptrs, tmp_out_buf);
*data += (NR_NB_SC_PER_RB - 1);
*ptrs += 1;
} else if (data) {
map_data_rb(*data, tmp_out_buf);
*data += NR_NB_SC_PER_RB;
} else {
DevAssert(false);
}
/* copy back to out buffer */
out_tmp = *out;
memcpy(out_tmp, tmp_out_buf, sizeof(c16_t) * left_dc);
out_tmp -= (fft_size - left_dc);
memcpy(out_tmp, tmp_out_buf + left_dc, sizeof(c16_t) * right_dc);
out_tmp += right_dc;
*out = out_tmp;
}
/*
Holds params needed for PUSCH resoruce mapping
*/
typedef struct {
rnti_t rnti;
unsigned int K_ptrs;
unsigned int k_RE_ref;
unsigned int first_sc_offset;
unsigned int fft_size;
unsigned int num_rb_max;
unsigned int symbols_per_slot;
unsigned int slot;
unsigned int dmrs_scrambling_id;
unsigned int scid;
unsigned int dmrs_port;
int Wt;
int *Wf;
unsigned int dmrs_symb_pos;
unsigned int ptrs_symb_pos;
unsigned int pdu_bit_map;
transformPrecoder_t transform_precoding;
unsigned int bwp_start;
unsigned int start_rb;
unsigned int nb_rb;
unsigned int start_symbol;
unsigned int num_symbols;
pusch_dmrs_type_t dmrs_type;
unsigned int delta;
unsigned int num_cdm_no_data;
} nr_phy_pxsch_params_t;
/*
Map all REs in one OFDM symbol
This function operation is as follows:
mapping is done on RB basis. if RB contains DC and if DC is in middle
of the RB, then the mapping is done via map_over_dc().
*/
static void map_current_symbol(const nr_phy_pxsch_params_t p,
const bool dmrs_symbol,
const bool ptrs_symbol,
const c16_t *dmrs_seq,
const c16_t *ptrs_seq,
const c16_t **data,
c16_t *out)
{
const unsigned int abs_start_rb = p.bwp_start + p.start_rb;
const unsigned int start_sc = (p.first_sc_offset + abs_start_rb * NR_NB_SC_PER_RB) % p.fft_size;
const unsigned int dc_rb = (p.fft_size - start_sc) / NR_NB_SC_PER_RB;
const unsigned int rb_over_dc = (p.fft_size - start_sc) % NR_NB_SC_PER_RB;
const unsigned int n_cdm = p.num_cdm_no_data;
const c16_t *data_tmp = *data;
/* If current symbol is DMRS symbol */
if (dmrs_symbol) {
const unsigned int dmrs_per_rb = (p.dmrs_type == pusch_dmrs_type1) ? 6 : 4;
const unsigned int data_per_rb = NR_NB_SC_PER_RB - dmrs_per_rb;
const c16_t *p_mod_dmrs = dmrs_seq + abs_start_rb * dmrs_per_rb;
c16_t *out_tmp = out + start_sc;
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
if (rb == dc_rb) {
// map RB at DC
if (rb_over_dc) {
// if DC is in middle of RB, the following function handles it.
map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, NULL, &out_tmp);
continue;
} else {
// else just move the pointer and following function will map the rb
out_tmp -= p.fft_size;
}
}
map_dmrs_ptr(p.delta, p_mod_dmrs, out_tmp);
p_mod_dmrs += dmrs_per_rb;
out_tmp += NR_NB_SC_PER_RB;
}
/* if there is data in current DMRS symbol, we map it here. */
if (map_data_dmrs_ptr) {
c16_t *out_tmp = out + start_sc;
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
if (rb == dc_rb) {
if (rb_over_dc) {
map_over_dc(rb_over_dc, n_cdm, p.fft_size, dmrs_per_rb, data_per_rb, p.delta, 0, NULL, &p_mod_dmrs, &data_tmp, &out_tmp);
continue;
} else {
out_tmp -= p.fft_size;
}
}
map_data_dmrs_ptr(n_cdm, data_tmp, out_tmp);
data_tmp += data_per_rb;
out_tmp += NR_NB_SC_PER_RB;
}
}
/* If current symbol is a PTRS symbol */
} else if (ptrs_symbol) {
const unsigned int first_ptrs_re = get_first_ptrs_re(p.rnti, p.K_ptrs, p.nb_rb, p.k_RE_ref) + start_sc;
const unsigned int ptrs_idx_re = (start_sc - first_ptrs_re) % NR_NB_SC_PER_RB; // PTRS RE index within RB
unsigned int non_ptrs_rb = (start_sc - first_ptrs_re) / NR_NB_SC_PER_RB; // number of RBs before the first PTRS RB
int ptrs_idx_rb = -non_ptrs_rb; // RB count to check for PTRS RB
c16_t *out_tmp = out + start_sc;
const c16_t *p_mod_ptrs = ptrs_seq;
/* map data to RBs before the first PTRS RB or if current RB has no PTRS */
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
if (rb < non_ptrs_rb || ptrs_idx_rb % p.K_ptrs) {
if (rb == dc_rb) {
if (rb_over_dc) {
map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp);
continue;
} else {
out_tmp -= p.fft_size;
}
}
map_data_rb(data_tmp, out_tmp);
data_tmp += NR_NB_SC_PER_RB;
out_tmp += NR_NB_SC_PER_RB;
} else {
if (rb == dc_rb) {
if (rb_over_dc) {
map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, ptrs_idx_re, &p_mod_ptrs, NULL, &data_tmp, &out_tmp);
continue;
} else {
out_tmp -= p.fft_size;
}
}
map_data_ptrs(ptrs_idx_re, data_tmp, p_mod_ptrs, out_tmp);
p_mod_ptrs++; // increament once as only one PTRS RE per RB
data_tmp += (NR_NB_SC_PER_RB - 1);
out_tmp += NR_NB_SC_PER_RB;
}
ptrs_idx_rb++;
}
} else {
/* only data in this symbol */
c16_t *out_tmp = out + start_sc;
for (unsigned int rb = 0; rb < p.nb_rb; rb++) {
if (rb == dc_rb) {
if (rb_over_dc) {
map_over_dc(rb_over_dc, n_cdm, p.fft_size, 0, 0, p.delta, 0, NULL, NULL, &data_tmp, &out_tmp);
continue;
} else {
out_tmp -= p.fft_size;
}
}
map_data_rb(data_tmp, out_tmp);
data_tmp += NR_NB_SC_PER_RB;
out_tmp += NR_NB_SC_PER_RB;
}
}
*data = data_tmp;
}
/*
TS 38.211 table 6.4.1.1.3-1 and 2
*/
static void dmrs_amp_mult(const uint32_t dmrs_port,
const int Wt,
const int Wf[2],
const c16_t *mod_dmrs,
c16_t *mod_dmrs_out,
const uint32_t n_dmrs,
const pusch_dmrs_type_t dmrs_type)
{
/* short array that hold amplitude for k_prime = 0 and k_prime = 1 */
int32_t alpha_dmrs[2] __attribute((aligned(16)));
for (int_fast8_t i = 0; i < sizeofArray(alpha_dmrs); i++) {
const int32_t a = Wf[i] * Wt * AMP;
alpha_dmrs[i] = a;
}
/* multiply amplitude with complex DMRS vector */
for (int_fast16_t i = 0; i < n_dmrs; i++) {
mod_dmrs_out[i] = c16mulRealShift(mod_dmrs[i], alpha_dmrs[i % 2], 15);
}
}
/*
Map ULSCH data and DMRS in all of the scheduled symbols and PRBs
*/
static void map_symbols(const nr_phy_pxsch_params_t p,
const unsigned int slot,
const c16_t *dmrs_seq,
const c16_t *data,
c16_t *out)
{
// asign the function pointers
if (p.dmrs_type == pusch_dmrs_type1) {
map_dmrs_ptr = map_dmrs_type1_cdm1_rb;
map_data_dmrs_ptr = (p.num_cdm_no_data == 1) ? map_data_dmrs_type1_cdm1_rb : NULL;
} else {
map_dmrs_ptr = map_dmrs_type2_rb;
map_data_dmrs_ptr = (p.num_cdm_no_data < 3) ? map_data_dmrs_type2_rb : NULL;
}
// for all symbols
const unsigned int n_dmrs = (p.bwp_start + p.start_rb + p.nb_rb) * ((p.dmrs_type == pusch_dmrs_type1) ? 6 : 4);
const c16_t *cur_data = data;
for (int l = p.start_symbol; l < p.start_symbol + p.num_symbols; l++) {
const bool dmrs_symbol = is_dmrs_symbol(l, p.dmrs_symb_pos);
const bool ptrs_symbol = is_ptrs_symbol(l, p.ptrs_symb_pos);
c16_t mod_dmrs_amp[ALNARS_16_4(n_dmrs)] __attribute((aligned(16)));
c16_t mod_ptrs_amp[ALNARS_16_4(p.nb_rb)] __attribute((aligned(16)));
const uint32_t *gold = NULL;
if (dmrs_symbol || ptrs_symbol) {
gold = nr_gold_pusch(p.num_rb_max, p.symbols_per_slot, p.dmrs_scrambling_id, p.scid, slot, l);
}
if (dmrs_symbol) {
c16_t mod_dmrs[ALNARS_16_4(n_dmrs)] __attribute((aligned(16)));
if (p.transform_precoding == transformPrecoder_disabled) {
nr_modulation(gold, n_dmrs * 2, DMRS_MOD_ORDER, (int16_t *)mod_dmrs);
dmrs_amp_mult(p.dmrs_port, p.Wt, p.Wf, mod_dmrs, mod_dmrs_amp, n_dmrs, p.dmrs_type);
} else {
dmrs_amp_mult(p.dmrs_port, p.Wt, p.Wf, dmrs_seq, mod_dmrs_amp, n_dmrs, p.dmrs_type);
}
} else if ((p.pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) && ptrs_symbol) {
AssertFatal(p.transform_precoding == transformPrecoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n");
c16_t mod_ptrs[ALNARS_16_4(p.nb_rb)] __attribute((aligned(16)));
nr_modulation(gold, p.nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs);
const unsigned int beta_ptrs = 1; // temp value until power control is implemented
multadd_complex_vector_real_scalar((int16_t *)mod_ptrs, beta_ptrs * AMP, (int16_t *)mod_ptrs_amp, 1, p.nb_rb);
}
map_current_symbol(p,
dmrs_symbol,
ptrs_symbol,
mod_dmrs_amp,
mod_ptrs_amp,
&cur_data, // increments every symbol
out + l * p.fft_size);
}
}
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
const unsigned char harq_pid,
const uint32_t frame,
......@@ -95,11 +471,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
{
LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot);
int Wf[2], Wt[2];
int l_prime[2], delta;
int l_prime[2];
uint8_t nb_dmrs_re_per_rb;
int i;
int sample_offsetF, N_RE_prime;
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
......@@ -143,17 +516,18 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
LOG_D(PHY,"ulsch TX %x : start_rb %d nb_rb %d mod_order %d Nl %d Tpmi %d bwp_start %d start_sc %d start_symbol %d num_symbols %d cdmgrpsnodata %d num_dmrs %d dmrs_re_per_rb %d\n",
rnti,start_rb,nb_rb,mod_order,Nl,pusch_pdu->Tpmi,pusch_pdu->bwp_start,start_sc,start_symbol,number_of_symbols,cdm_grps_no_data,number_dmrs_symbols,nb_dmrs_re_per_rb);
// TbD num_of_mod_symbols is set but never used
N_RE_prime = NR_NB_SC_PER_RB*number_of_symbols - nb_dmrs_re_per_rb*number_dmrs_symbols - N_PRB_oh;
const uint32_t N_RE_prime = NR_NB_SC_PER_RB * number_of_symbols - nb_dmrs_re_per_rb * number_dmrs_symbols - N_PRB_oh;
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
/////////////////////////PTRS parameters' initialization/////////////////////////
///////////
uint8_t L_ptrs, K_ptrs = 0;
unsigned int K_ptrs = 0, k_RE_ref = 0;
uint32_t unav_res = 0;
if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
K_ptrs = pusch_pdu->pusch_ptrs.ptrs_freq_density;
L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density;
k_RE_ref = pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
uint8_t L_ptrs = 1 << pusch_pdu->pusch_ptrs.ptrs_time_density;
ulsch_ue->ptrs_symbols = 0;
......@@ -197,8 +571,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
.oob_event_value = 0};
trace_pdu(&tmp);
if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1)
if (nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, tb_size, G) == -1) {
NR_UL_UE_HARQ_t *harq_process_ulsch = &UE->ul_harq_processes[harq_pid];
harq_process_ulsch->ULstatus = SCH_IDLE;
return;
}
///////////
////////////////////////////////////////////////////////////////////
......@@ -236,23 +613,12 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
///////////
////////////////////////////////////////////////////////////////////////
/////////////////////////DMRS Modulation/////////////////////////
///////////
uint16_t n_dmrs = (pusch_pdu->bwp_start + start_rb + nb_rb)*((dmrs_type == pusch_dmrs_type1) ? 6:4);
c16_t mod_dmrs[n_dmrs] __attribute((aligned(16)));
///////////
////////////////////////////////////////////////////////////////////////
/////////////////////////ULSCH layer mapping/////////////////////////
///////////
const int sz = available_bits / mod_order;
c16_t tx_layers[Nl][sz];
memset(tx_layers, 0, sizeof(tx_layers));
const int sz = available_bits / mod_order / Nl;
c16_t ulsch_mod[Nl][sz];
nr_ue_layer_mapping(d_mod, Nl, available_bits / mod_order, sz, tx_layers);
nr_ue_layer_mapping(d_mod, Nl, sz, ulsch_mod);
///////////
////////////////////////////////////////////////////////////////////////
......@@ -266,8 +632,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
uint8_t u = 0, v = 0;
c16_t *dmrs_seq = NULL;
/// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
c16_t y[max_num_re] __attribute__((aligned(16)));
memset(y, 0, sizeof(y));
c16_t ulsch_mod_tp[max_num_re] __attribute__((aligned(16)));
memset(ulsch_mod_tp, 0, sizeof(ulsch_mod_tp));
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
......@@ -292,7 +658,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
/* In the symbol with DMRS no data would be transmitted CDM groups is 2*/
continue;
nr_dft(&y[y_offset], &tx_layers[0][y_offset], nb_re_pusch);
nr_dft(&ulsch_mod_tp[y_offset], &ulsch_mod[0][y_offset], nb_re_pusch);
y_offset = y_offset + nb_re_pusch;
......@@ -310,7 +676,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits,mod_order);
for (int ll = 0; ll < (available_bits/mod_order); ll++) {
debug_symbols[ll] = ulsch_ue->y[ll];
debug_symbols[ll] = ulsch_ue->ulsch_mod_tp[ll];
}
printf("NR_ULSCH_UE: numSym: %d, num_dmrs_sym: %d", number_of_symbols,number_dmrs_symbols);
......@@ -318,8 +684,8 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
nr_idft(&debug_symbols[offset], nb_re_pusch);
offset = offset + nb_re_pusch;
}
LOG_M("preDFT_all_symbols.m","UE_preDFT", tx_layers[0],number_of_symbols*nb_re_pusch,1,1);
LOG_M("postDFT_all_symbols.m","UE_postDFT", y,number_of_symbols*nb_re_pusch,1,1);
LOG_M("preDFT_all_symbols.m", "UE_preDFT", ulsch_mod[0], number_of_symbols * nb_re_pusch, 1, 1);
LOG_M("postDFT_all_symbols.m", "UE_postDFT", ulsch_mod_tp, number_of_symbols * nb_re_pusch, 1, 1);
LOG_M("DEBUG_IDFT_SYMBOLS.m","UE_Debug_IDFT", debug_symbols,number_of_symbols*nb_re_pusch,1,1);
LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1);
#endif
......@@ -334,157 +700,57 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
/////////////////////////ULSCH RE mapping/////////////////////////
///////////
const int encoded_length = frame_parms->N_RB_UL * 14 * NR_NB_SC_PER_RB * mod_order * Nl;
c16_t tx_precoding[Nl][encoded_length];
const int slot_sz = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot;
c16_t tx_precoding[Nl][slot_sz];
memset(tx_precoding, 0, sizeof(tx_precoding));
for (int nl=0; nl < Nl; nl++) {
uint8_t k_prime = 0;
uint16_t m = 0;
for (int nl = 0; nl < Nl; nl++) {
#ifdef DEBUG_PUSCH_MAPPING
printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
#endif
int dmrs_port = get_dmrs_port(nl,pusch_pdu->dmrs_ports);
// DMRS params for this dmrs port
const uint8_t dmrs_port = get_dmrs_port(nl, pusch_pdu->dmrs_ports);
const uint8_t delta = get_delta(dmrs_port, dmrs_type);
int Wt[2];
int Wf[2];
get_Wt(Wt, dmrs_port, dmrs_type);
get_Wf(Wf, dmrs_port, dmrs_type);
delta = get_delta(dmrs_port, dmrs_type);
for (int l=start_symbol; l<start_symbol+number_of_symbols; l++) {
uint16_t k = start_sc;
uint16_t n = 0;
uint8_t is_dmrs_sym = 0;
uint8_t is_ptrs_sym = 0;
uint16_t dmrs_idx = 0, ptrs_idx = 0;
c16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation
if ((ul_dmrs_symb_pos >> l) & 0x01) {
is_dmrs_sym = 1;
if (pusch_pdu->transform_precoding == transformPrecoder_disabled){
if (dmrs_type == pusch_dmrs_type1)
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*6;
else
dmrs_idx = (pusch_pdu->bwp_start + start_rb)*4;
// TODO: performance improvement, we can skip the modulation of DMRS symbols outside the bandwidth part
// Perform this on gold sequence, not required when SC FDMA operation is done,
LOG_D(PHY,"DMRS in symbol %d\n",l);
const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL,
frame_parms->symbols_per_slot,
pusch_pdu->ul_dmrs_scrambling_id,
pusch_pdu->scid,
slot,
l);
nr_modulation(gold,
n_dmrs * 2,
DMRS_MOD_ORDER,
(int16_t *)mod_dmrs); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
} else {
dmrs_idx = 0;
}
} else if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
AssertFatal(pusch_pdu->transform_precoding == transformPrecoder_disabled, "PTRS NOT SUPPORTED IF TRANSFORM PRECODING IS ENABLED\n");
if(is_ptrs_symbol(l, ulsch_ue->ptrs_symbols)) {
is_ptrs_sym = 1;
const uint32_t *gold = nr_gold_pusch(frame_parms->N_RB_UL,
frame_parms->symbols_per_slot,
pusch_pdu->ul_dmrs_scrambling_id,
pusch_pdu->scid,
slot,
l);
nr_modulation(gold, nb_rb, DMRS_MOD_ORDER, (int16_t *)mod_ptrs);
}
}
for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++) {
uint8_t is_dmrs = 0;
uint8_t is_ptrs = 0;
c16_t *data = (pusch_pdu->transform_precoding == transformPrecoder_enabled) ? ulsch_mod_tp : ulsch_mod[nl];
nr_phy_pxsch_params_t params = {.rnti = rnti,
.K_ptrs = K_ptrs,
.k_RE_ref = k_RE_ref,
.first_sc_offset = frame_parms->first_carrier_offset,
.fft_size = frame_parms->ofdm_symbol_size,
.num_rb_max = frame_parms->N_RB_UL,
.symbols_per_slot = frame_parms->symbols_per_slot,
.dmrs_scrambling_id = pusch_pdu->ul_dmrs_scrambling_id,
.scid = pusch_pdu->scid,
.dmrs_port = dmrs_port,
.Wt = Wt[l_prime[0]],
.Wf = Wf,
.dmrs_symb_pos = ul_dmrs_symb_pos,
.ptrs_symb_pos = ulsch_ue->ptrs_symbols,
.pdu_bit_map = pusch_pdu->pdu_bit_map,
.transform_precoding = pusch_pdu->transform_precoding,
.bwp_start = pusch_pdu->bwp_start,
.start_rb = start_rb,
.nb_rb = nb_rb,
.start_symbol = start_symbol,
.num_symbols = number_of_symbols,
.dmrs_type = dmrs_type,
.delta = delta,
.num_cdm_no_data = cdm_grps_no_data};
map_symbols(params, slot, dmrs_seq, data, tx_precoding[nl]);
sample_offsetF = l*frame_parms->ofdm_symbol_size + k;
if (is_dmrs_sym) {
if (k == ((start_sc+get_dmrs_freq_idx_ul(n, k_prime, delta, dmrs_type))%frame_parms->ofdm_symbol_size))
is_dmrs = 1;
} else if (is_ptrs_sym) {
is_ptrs = is_ptrs_subcarrier(k,
rnti,
K_ptrs,
nb_rb,
pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset,
start_sc,
frame_parms->ofdm_symbol_size);
}
if (is_dmrs == 1) {
// if transform precoding is enabled
const int tmp = Wt[l_prime[0]] * Wf[k_prime] * AMP;
if (pusch_pdu->transform_precoding == transformPrecoder_enabled)
tx_precoding[nl][sample_offsetF] = c16mulRealShift(dmrs_seq[dmrs_idx], tmp, 15);
else
tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_dmrs[dmrs_idx], tmp, 15);
#ifdef DEBUG_PUSCH_MAPPING
printf("DMRS: Layer: %d\t, dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t dmrs: %d %d\n",
nl,
dmrs_idx,
l,
k,
k_prime,
n,
tx_precoding[nl][sample_offsetF].r,
tx_precoding[nl][sample_offsetF].i);
#endif
dmrs_idx++;
k_prime++;
k_prime &= 1;
n += (k_prime) ? 0 : 1;
} else if (is_ptrs == 1) {
uint16_t beta_ptrs = 1; // temp value until power control is implemented
tx_precoding[nl][sample_offsetF] = c16mulRealShift(mod_ptrs[ptrs_idx], beta_ptrs * AMP, 15);
ptrs_idx++;
} else if (!is_dmrs_sym
|| allowed_xlsch_re_in_dmrs_symbol(k, start_sc, frame_parms->ofdm_symbol_size, cdm_grps_no_data, dmrs_type)) {
if (pusch_pdu->transform_precoding == transformPrecoder_disabled)
tx_precoding[nl][sample_offsetF] = tx_layers[nl][m];
else
tx_precoding[nl][sample_offsetF] = y[m];
#ifdef DEBUG_PUSCH_MAPPING
printf("DATA: layer %d\t m %d\t l %d \t k %d \t tx_precoding: %d %d\n",
nl,
m,
l,
k,
tx_precoding[nl][sample_offsetF].r,
tx_precoding[nl][sample_offsetF].i);
#endif
m++;
} else {
tx_precoding[nl][sample_offsetF] = (c16_t){0};
}
if (++k >= frame_parms->ofdm_symbol_size)
k -= frame_parms->ofdm_symbol_size;
} // for (i=0; i< nb_rb*NR_NB_SC_PER_RB; i++)
} // for (l=start_symbol; l<start_symbol+number_of_symbols; l++)
} // for (nl=0; nl < Nl; nl++)
/////////////////////////ULSCH precoding/////////////////////////
///////////
/// Layer Precoding and Antenna port mapping
// tx_layers 0-3 are mapped on antenna ports
// ulsch_mod 0-3 are mapped on antenna ports
// The precoding info is supported by nfapi such as num_prgs, prg_size, prgs_list and pm_idx
// The same precoding matrix is applied on prg_size RBs, Thus
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
......@@ -555,7 +821,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
for (int i = 0; i < NR_NB_SC_PER_RB; i++) {
int32_t re_offset = l * frame_parms->ofdm_symbol_size + k;
txdataF[ap][re_offset] = nr_layer_precoder(encoded_length, tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset);
txdataF[ap][re_offset] = nr_layer_precoder(slot_sz, tx_precoding, W_prec, pusch_pdu->nrOfLayers, re_offset);
if (++k >= frame_parms->ofdm_symbol_size) {
k -= frame_parms->ofdm_symbol_size;
}
......
......@@ -30,27 +30,30 @@ void multadd_complex_vector_real_scalar(int16_t *x,
uint8_t zero_flag,
uint32_t N)
{
simd_q15_t alpha_128,*x_128=(simd_q15_t *)x,*y_128=(simd_q15_t*)y;
int n;
alpha_128 = set1_int16(alpha);
const uint32_t num_simd_adds = N / 4;
const uint32_t num_adds = N % 4;
if (zero_flag == 1)
for (n=0; n<N>>2; n++) {
// print_shorts("x_128[n]=", &x_128[n]);
// print_shorts("alpha_128", &alpha_128);
if (zero_flag == 1) {
for (n = 0; n < num_simd_adds; n++) {
y_128[n] = mulhi_int16(x_128[n],alpha_128);
// print_shorts("y_128[n]=", &y_128[n]);
}
else
for (n=0; n<N>>2; n++) {
for (n = 0; n < num_adds; n++) {
const uint32_t offset = num_simd_adds * 4;
y[offset + n] = (x[offset + n] * alpha) >> 16;
}
} else {
for (n = 0; n < num_simd_adds; n++) {
y_128[n] = adds_int16(y_128[n],mulhi_int16(x_128[n],alpha_128));
}
simde_mm_empty();
simde_m_empty();
for (n = 0; n < num_adds; n++) {
const uint32_t offset = num_simd_adds * 4;
y[offset + n] += (x[offset + n] * alpha) >> 16;
}
}
}
void multadd_real_vector_complex_scalar(const int16_t *x, const int16_t *alpha, int16_t *y, uint32_t N)
......
......@@ -52,6 +52,9 @@
extern "C" {
#endif
#define ALIGNARRAYSIZE(a, b) (((a + b - 1) / b) * b)
#define ALNARS_16_4(a) ALIGNARRAYSIZE(a, 4)
typedef struct complexd {
double r;
double i;
......
......@@ -45,11 +45,13 @@
FN(PHY_RX_PDCCH_STATS),\
FN(DLSCH_PROCEDURES_STATS),\
FN(PHY_PROC_TX),\
FN(PUSCH_PROC_STATS),\
FN(ULSCH_SEGMENTATION_STATS),\
FN(ULSCH_LDPC_ENCODING_STATS),\
FN(ULSCH_RATE_MATCHING_STATS),\
FN(ULSCH_INTERLEAVING_STATS),\
FN(ULSCH_ENCODING_STATS)
FN(ULSCH_ENCODING_STATS),\
FN(OFDM_MOD_STATS)
typedef enum {
FOREACH_NR_PHY_CPU_MEAS(NOOP),
......
......@@ -287,21 +287,26 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
start_meas_nr_ue_phy(ue, PHY_PROC_TX);
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE)
const int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE) {
start_meas_nr_ue_phy(ue, PUSCH_PROC_STATS);
nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, gNB_id, phy_data, (c16_t **)&txdataF);
stop_meas_nr_ue_phy(ue, PUSCH_PROC_STATS);
}
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF);
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF);
LOG_D(PHY, "Sending Uplink data \n");
start_meas_nr_ue_phy(ue, OFDM_MOD_STATS);
nr_ue_pusch_common_procedures(ue,
proc->nr_slot_tx,
&ue->frame_parms,
ue->frame_parms.nb_antennas_tx,
(c16_t **)txdataF,
link_type_ul);
stop_meas_nr_ue_phy(ue, OFDM_MOD_STATS);
nr_ue_prach_procedures(ue, proc);
......
......@@ -1421,17 +1421,6 @@ int main(int argc, char *argv[])
errors_decoding++;
}
}
if (n_trials == 1) {
for (int r = 0; r < UE->ul_harq_processes[harq_pid].C; r++)
for (int i = 0; i < UE->ul_harq_processes[harq_pid].K >> 3; i++) {
if ((UE->ul_harq_processes[harq_pid].c[r][i] ^ ulsch_gNB->harq_process->c[r][i]) != 0)
printf("************");
/*printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r,
i,UE->ul_harq_processes[harq_pid].c[r][i],
i,ulsch_gNB->harq_process->c[r][i],
UE->ul_harq_processes[harq_pid].c[r][i]^ulsch_gNB->harq_process->c[r][i]);*/
}
}
if (errors_decoding > 0 && error_flag == 0) {
n_false_positive++;
if (n_trials==1)
......
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