Merge remote-tracking branch 'origin/NR_UE_pusch_optimization' into integration_2024_w38b
This commit is contained in:
@@ -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);
|
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[in] n_symbs, number of modulated symbols
|
||||||
@param[out] tx_layers, modulated symbols for each layer
|
@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)
|
\brief This function implements the OFDM front end processor on reception (FEP)
|
||||||
\param frame_parms Pointer to frame parameters
|
\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
|
* NAME : is_ptrs_subcarrier
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ void set_ptrs_symb_idx(uint16_t *ptrs_symbols,
|
|||||||
uint8_t L_ptrs,
|
uint8_t L_ptrs,
|
||||||
uint16_t dmrs_symb_pos);
|
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,
|
uint8_t is_ptrs_subcarrier(uint16_t k,
|
||||||
uint16_t n_rnti,
|
uint16_t n_rnti,
|
||||||
uint8_t K_ptrs,
|
uint8_t K_ptrs,
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
|
|||||||
&harq_process->Z,
|
&harq_process->Z,
|
||||||
&harq_process->F,
|
&harq_process->F,
|
||||||
harq_process->BG);
|
harq_process->BG);
|
||||||
|
stop_meas_nr_ue_phy(ue, ULSCH_SEGMENTATION_STATS);
|
||||||
impp.n_segments = harq_process->C;
|
impp.n_segments = harq_process->C;
|
||||||
impp.K = harq_process->K;
|
impp.K = harq_process->K;
|
||||||
impp.Kr = impp.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);
|
LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B);
|
||||||
return(-1);
|
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);
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT);
|
||||||
|
|
||||||
#ifdef DEBUG_ULSCH_CODING
|
#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);
|
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) {
|
if (ldpc_interface_offload.LDPCencoder) {
|
||||||
for (int j = 0; j < impp.n_segments; j++) {
|
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);
|
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);
|
ldpc_interface_offload.LDPCencoder(harq_process->c, &harq_process->f, &impp);
|
||||||
|
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
|
||||||
} else {
|
} else {
|
||||||
if (ulsch->pusch_pdu.pusch_data.new_data_indicator) {
|
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++) {
|
for (int j = 0; j < (impp.n_segments / 8 + 1); j++) {
|
||||||
impp.macro_num = j;
|
impp.macro_num = j;
|
||||||
impp.Kr = impp.K;
|
impp.Kr = impp.K;
|
||||||
ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp);
|
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);
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT);
|
||||||
|
|
||||||
#ifdef DEBUG_ULSCH_CODING
|
#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);
|
write_output("ulsch_enc_output0.m", "enc0", &harq_process->d[0][0], (3 * 8 * Kr_bytes) + 12, 1, 4);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
stop_meas_nr_ue_phy(ue, ULSCH_LDPC_ENCODING_STATS);
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
for (int r = 0; r < impp.n_segments; r++) { // looping over C segments
|
for (int r = 0; r < impp.n_segments; r++) { // looping over C segments
|
||||||
if (impp.F > 0) {
|
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);
|
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,
|
void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||||
const unsigned char harq_pid,
|
const unsigned char harq_pid,
|
||||||
const uint32_t frame,
|
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);
|
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];
|
||||||
int l_prime[2], delta;
|
|
||||||
uint8_t nb_dmrs_re_per_rb;
|
uint8_t nb_dmrs_re_per_rb;
|
||||||
int i;
|
|
||||||
int sample_offsetF, N_RE_prime;
|
|
||||||
|
|
||||||
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
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",
|
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);
|
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
|
// 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;
|
harq_process_ul_ue->num_of_mod_symbols = N_RE_prime*nb_rb;
|
||||||
|
|
||||||
/////////////////////////PTRS parameters' initialization/////////////////////////
|
/////////////////////////PTRS parameters' initialization/////////////////////////
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
uint8_t L_ptrs, K_ptrs = 0;
|
unsigned int K_ptrs = 0, k_RE_ref = 0;
|
||||||
uint32_t unav_res = 0;
|
uint32_t unav_res = 0;
|
||||||
if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
if (pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
|
||||||
K_ptrs = pusch_pdu->pusch_ptrs.ptrs_freq_density;
|
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;
|
ulsch_ue->ptrs_symbols = 0;
|
||||||
|
|
||||||
@@ -197,8 +571,11 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|||||||
.oob_event_value = 0};
|
.oob_event_value = 0};
|
||||||
trace_pdu(&tmp);
|
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;
|
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/////////////////////////
|
/////////////////////////ULSCH layer mapping/////////////////////////
|
||||||
///////////
|
///////////
|
||||||
const int sz = available_bits / mod_order;
|
const int sz = available_bits / mod_order / Nl;
|
||||||
c16_t tx_layers[Nl][sz];
|
c16_t ulsch_mod[Nl][sz];
|
||||||
memset(tx_layers, 0, sizeof(tx_layers));
|
|
||||||
|
|
||||||
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;
|
uint8_t u = 0, v = 0;
|
||||||
c16_t *dmrs_seq = NULL;
|
c16_t *dmrs_seq = NULL;
|
||||||
/// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
|
/// 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)));
|
c16_t ulsch_mod_tp[max_num_re] __attribute__((aligned(16)));
|
||||||
memset(y, 0, sizeof(y));
|
memset(ulsch_mod_tp, 0, sizeof(ulsch_mod_tp));
|
||||||
|
|
||||||
if (pusch_pdu->transform_precoding == transformPrecoder_enabled) {
|
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*/
|
/* In the symbol with DMRS no data would be transmitted CDM groups is 2*/
|
||||||
continue;
|
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;
|
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);
|
printf("NR_ULSCH_UE: available_bits: %u, mod_order: %d", available_bits,mod_order);
|
||||||
|
|
||||||
for (int ll = 0; ll < (available_bits/mod_order); ll++) {
|
for (int ll = 0; ll < (available_bits/mod_order); ll++) {
|
||||||
debug_symbols[ll] = ulsch_ue->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);
|
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);
|
nr_idft(&debug_symbols[offset], nb_re_pusch);
|
||||||
offset = 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("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", y,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("DEBUG_IDFT_SYMBOLS.m","UE_Debug_IDFT", debug_symbols,number_of_symbols*nb_re_pusch,1,1);
|
||||||
LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1);
|
LOG_M("UE_DMRS_SEQ.m","UE_DMRS_SEQ", dmrs_seq,nb_re_pusch,1,1);
|
||||||
#endif
|
#endif
|
||||||
@@ -334,157 +700,57 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
|||||||
/////////////////////////ULSCH RE mapping/////////////////////////
|
/////////////////////////ULSCH RE mapping/////////////////////////
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
const int encoded_length = frame_parms->N_RB_UL * 14 * NR_NB_SC_PER_RB * mod_order * Nl;
|
const int slot_sz = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot;
|
||||||
c16_t tx_precoding[Nl][encoded_length];
|
c16_t tx_precoding[Nl][slot_sz];
|
||||||
memset(tx_precoding, 0, sizeof(tx_precoding));
|
memset(tx_precoding, 0, sizeof(tx_precoding));
|
||||||
|
|
||||||
for (int nl=0; nl < Nl; nl++) {
|
for (int nl = 0; nl < Nl; nl++) {
|
||||||
uint8_t k_prime = 0;
|
|
||||||
uint16_t m = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG_PUSCH_MAPPING
|
#ifdef DEBUG_PUSCH_MAPPING
|
||||||
printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
|
printf("NR_ULSCH_UE: Value of CELL ID %d /t, u %d \n", frame_parms->Nid_cell, u);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int dmrs_port = get_dmrs_port(nl,pusch_pdu->dmrs_ports);
|
const uint8_t dmrs_port = get_dmrs_port(nl, pusch_pdu->dmrs_ports);
|
||||||
// DMRS params for this dmrs port
|
const uint8_t delta = get_delta(dmrs_port, dmrs_type);
|
||||||
|
int Wt[2];
|
||||||
|
int Wf[2];
|
||||||
get_Wt(Wt, dmrs_port, dmrs_type);
|
get_Wt(Wt, dmrs_port, dmrs_type);
|
||||||
get_Wf(Wf, 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++) {
|
c16_t *data = (pusch_pdu->transform_precoding == transformPrecoder_enabled) ? ulsch_mod_tp : ulsch_mod[nl];
|
||||||
|
|
||||||
uint16_t k = start_sc;
|
nr_phy_pxsch_params_t params = {.rnti = rnti,
|
||||||
uint16_t n = 0;
|
.K_ptrs = K_ptrs,
|
||||||
uint8_t is_dmrs_sym = 0;
|
.k_RE_ref = k_RE_ref,
|
||||||
uint8_t is_ptrs_sym = 0;
|
.first_sc_offset = frame_parms->first_carrier_offset,
|
||||||
uint16_t dmrs_idx = 0, ptrs_idx = 0;
|
.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};
|
||||||
|
|
||||||
c16_t mod_ptrs[nb_rb] __attribute((aligned(16))); // assume maximum number of PTRS per pusch allocation
|
map_symbols(params, slot, dmrs_seq, data, tx_precoding[nl]);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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++)
|
} // for (nl=0; nl < Nl; nl++)
|
||||||
|
|
||||||
/////////////////////////ULSCH precoding/////////////////////////
|
/////////////////////////ULSCH precoding/////////////////////////
|
||||||
///////////
|
///////////
|
||||||
/// Layer Precoding and Antenna port mapping
|
/// 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 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
|
// The same precoding matrix is applied on prg_size RBs, Thus
|
||||||
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
|
// 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++) {
|
for (int i = 0; i < NR_NB_SC_PER_RB; i++) {
|
||||||
int32_t re_offset = l * frame_parms->ofdm_symbol_size + k;
|
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) {
|
if (++k >= frame_parms->ofdm_symbol_size) {
|
||||||
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,
|
uint8_t zero_flag,
|
||||||
uint32_t N)
|
uint32_t N)
|
||||||
{
|
{
|
||||||
|
|
||||||
simd_q15_t alpha_128,*x_128=(simd_q15_t *)x,*y_128=(simd_q15_t*)y;
|
simd_q15_t alpha_128,*x_128=(simd_q15_t *)x,*y_128=(simd_q15_t*)y;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
alpha_128 = set1_int16(alpha);
|
alpha_128 = set1_int16(alpha);
|
||||||
|
const uint32_t num_simd_adds = N / 4;
|
||||||
|
const uint32_t num_adds = N % 4;
|
||||||
|
|
||||||
if (zero_flag == 1)
|
if (zero_flag == 1) {
|
||||||
for (n=0; n<N>>2; n++) {
|
for (n = 0; n < num_simd_adds; n++) {
|
||||||
// print_shorts("x_128[n]=", &x_128[n]);
|
|
||||||
// print_shorts("alpha_128", &alpha_128);
|
|
||||||
y_128[n] = mulhi_int16(x_128[n],alpha_128);
|
y_128[n] = mulhi_int16(x_128[n],alpha_128);
|
||||||
// print_shorts("y_128[n]=", &y_128[n]);
|
|
||||||
}
|
}
|
||||||
|
for (n = 0; n < num_adds; n++) {
|
||||||
else
|
const uint32_t offset = num_simd_adds * 4;
|
||||||
for (n=0; n<N>>2; n++) {
|
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));
|
y_128[n] = adds_int16(y_128[n],mulhi_int16(x_128[n],alpha_128));
|
||||||
}
|
}
|
||||||
|
for (n = 0; n < num_adds; n++) {
|
||||||
simde_mm_empty();
|
const uint32_t offset = num_simd_adds * 4;
|
||||||
simde_m_empty();
|
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)
|
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" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ALIGNARRAYSIZE(a, b) (((a + b - 1) / b) * b)
|
||||||
|
#define ALNARS_16_4(a) ALIGNARRAYSIZE(a, 4)
|
||||||
|
|
||||||
typedef struct complexd {
|
typedef struct complexd {
|
||||||
double r;
|
double r;
|
||||||
double i;
|
double i;
|
||||||
|
|||||||
@@ -45,11 +45,13 @@
|
|||||||
FN(PHY_RX_PDCCH_STATS),\
|
FN(PHY_RX_PDCCH_STATS),\
|
||||||
FN(DLSCH_PROCEDURES_STATS),\
|
FN(DLSCH_PROCEDURES_STATS),\
|
||||||
FN(PHY_PROC_TX),\
|
FN(PHY_PROC_TX),\
|
||||||
|
FN(PUSCH_PROC_STATS),\
|
||||||
FN(ULSCH_SEGMENTATION_STATS),\
|
FN(ULSCH_SEGMENTATION_STATS),\
|
||||||
FN(ULSCH_LDPC_ENCODING_STATS),\
|
FN(ULSCH_LDPC_ENCODING_STATS),\
|
||||||
FN(ULSCH_RATE_MATCHING_STATS),\
|
FN(ULSCH_RATE_MATCHING_STATS),\
|
||||||
FN(ULSCH_INTERLEAVING_STATS),\
|
FN(ULSCH_INTERLEAVING_STATS),\
|
||||||
FN(ULSCH_ENCODING_STATS)
|
FN(ULSCH_ENCODING_STATS),\
|
||||||
|
FN(OFDM_MOD_STATS)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FOREACH_NR_PHY_CPU_MEAS(NOOP),
|
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);
|
start_meas_nr_ue_phy(ue, PHY_PROC_TX);
|
||||||
|
|
||||||
int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
const int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id;
|
||||||
if (ue->ul_harq_processes[harq_pid].ULstatus == ACTIVE)
|
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);
|
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);
|
ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF);
|
||||||
|
|
||||||
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF);
|
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF);
|
||||||
|
|
||||||
LOG_D(PHY, "Sending Uplink data \n");
|
LOG_D(PHY, "Sending Uplink data \n");
|
||||||
|
start_meas_nr_ue_phy(ue, OFDM_MOD_STATS);
|
||||||
nr_ue_pusch_common_procedures(ue,
|
nr_ue_pusch_common_procedures(ue,
|
||||||
proc->nr_slot_tx,
|
proc->nr_slot_tx,
|
||||||
&ue->frame_parms,
|
&ue->frame_parms,
|
||||||
ue->frame_parms.nb_antennas_tx,
|
ue->frame_parms.nb_antennas_tx,
|
||||||
(c16_t **)txdataF,
|
(c16_t **)txdataF,
|
||||||
link_type_ul);
|
link_type_ul);
|
||||||
|
stop_meas_nr_ue_phy(ue, OFDM_MOD_STATS);
|
||||||
|
|
||||||
nr_ue_prach_procedures(ue, proc);
|
nr_ue_prach_procedures(ue, proc);
|
||||||
|
|
||||||
|
|||||||
@@ -1421,17 +1421,6 @@ int main(int argc, char *argv[])
|
|||||||
errors_decoding++;
|
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) {
|
if (errors_decoding > 0 && error_flag == 0) {
|
||||||
n_false_positive++;
|
n_false_positive++;
|
||||||
if (n_trials==1)
|
if (n_trials==1)
|
||||||
|
|||||||
Reference in New Issue
Block a user