group two symbol loops to make one with smaller tsack size and smaller variables
This commit is contained in:
@@ -276,7 +276,7 @@ void nr_layer_mapping(int nbCodes,
|
|||||||
for (int i2 = ((n_symbs >> 4) << 4); i2 < n_symbs; i2 += 2) {
|
for (int i2 = ((n_symbs >> 4) << 4); i2 < n_symbs; i2 += 2) {
|
||||||
tx_layers[0][i2 >> 1] = mod_symbs[0][i2];
|
tx_layers[0][i2 >> 1] = mod_symbs[0][i2];
|
||||||
tx_layers[1][i2 >> 1] = mod_symbs[0][i2 + 1];
|
tx_layers[1][i2 >> 1] = mod_symbs[0][i2 + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < n_symbs; i += 32) {
|
for (i = 0; i < n_symbs; i += 32) {
|
||||||
@@ -738,30 +738,26 @@ c16_t nr_layer_precoder(int sz, c16_t datatx_F_precoding[][sz], const char *prec
|
|||||||
}
|
}
|
||||||
|
|
||||||
c16_t nr_layer_precoder_cm(int n_layers,
|
c16_t nr_layer_precoder_cm(int n_layers,
|
||||||
int n_symbols,
|
|
||||||
int symSz,
|
int symSz,
|
||||||
c16_t datatx_F_precoding[n_layers][n_symbols][symSz],
|
c16_t datatx_F_precoding[n_layers][symSz],
|
||||||
int ap,
|
int ap,
|
||||||
nfapi_nr_pm_pdu_t *pmi_pdu,
|
nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||||
int symbol,
|
|
||||||
int offset)
|
int offset)
|
||||||
{
|
{
|
||||||
c16_t precodatatx_F = {0};
|
c16_t precodatatx_F = {0};
|
||||||
for (int al = 0; al < n_layers; al++) {
|
for (int al = 0; al < n_layers; al++) {
|
||||||
nfapi_nr_pm_weights_t *w = &pmi_pdu->weights[al][ap];
|
nfapi_nr_pm_weights_t *w = &pmi_pdu->weights[al][ap];
|
||||||
c16_t prec_weight = {.r = w->precoder_weight_Re, .i = w->precoder_weight_Im};
|
c16_t prec_weight = {.r = w->precoder_weight_Re, .i = w->precoder_weight_Im};
|
||||||
precodatatx_F = c16maddShift(datatx_F_precoding[al][symbol][offset], prec_weight, precodatatx_F, 15);
|
precodatatx_F = c16maddShift(datatx_F_precoding[al][offset], prec_weight, precodatatx_F, 15);
|
||||||
}
|
}
|
||||||
return precodatatx_F;
|
return precodatatx_F;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nr_layer_precoder_simd(const int n_layers,
|
void nr_layer_precoder_simd(const int n_layers,
|
||||||
const int n_symbols,
|
|
||||||
const int symSz,
|
const int symSz,
|
||||||
const c16_t txdataF_res_mapped[n_layers][n_symbols][symSz],
|
const c16_t txdataF_res_mapped[n_layers][symSz],
|
||||||
const int ant,
|
const int ant,
|
||||||
const nfapi_nr_pm_pdu_t *pmi_pdu,
|
const nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||||
const int symbol,
|
|
||||||
const int sc_offset,
|
const int sc_offset,
|
||||||
const int re_cnt,
|
const int re_cnt,
|
||||||
c16_t *txdataF_precoded)
|
c16_t *txdataF_precoded)
|
||||||
@@ -811,7 +807,7 @@ void nr_layer_precoder_simd(const int n_layers,
|
|||||||
#ifdef DEBUG_DLSCH_PRECODING_PRINT_WITH_TRIVIAL // Get result with trivial solution, TODO: To be removed
|
#ifdef DEBUG_DLSCH_PRECODING_PRINT_WITH_TRIVIAL // Get result with trivial solution, TODO: To be removed
|
||||||
c16_t y_triv[4];
|
c16_t y_triv[4];
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
y_triv[i] = nr_layer_precoder_cm(n_layers, NR_SYMBOLS_PER_SLOT, symSz, txdataF_res_mapped, ant, pmi_pdu, symbol, sc + i);
|
y_triv[i] = nr_layer_precoder_cm(n_layers, symSz, txdataF_res_mapped, ant, pmi_pdu, sc + i);
|
||||||
memcpy(&txdataF_precoded[sc], y_triv, sizeof(y_triv));
|
memcpy(&txdataF_precoded[sc], y_triv, sizeof(y_triv));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -135,12 +135,10 @@ void apply_nr_rotation_RX(const NR_DL_FRAME_PARMS *frame_parms,
|
|||||||
c16_t nr_layer_precoder(int sz, c16_t datatx_F_precoding[][sz], const char *prec_matrix, uint8_t n_layers, int32_t re_offset);
|
c16_t nr_layer_precoder(int sz, c16_t datatx_F_precoding[][sz], const char *prec_matrix, uint8_t n_layers, int32_t re_offset);
|
||||||
|
|
||||||
c16_t nr_layer_precoder_cm(int n_layers,
|
c16_t nr_layer_precoder_cm(int n_layers,
|
||||||
int n_symbols,
|
|
||||||
int symSz,
|
int symSz,
|
||||||
c16_t datatx_F_precoding[n_layers][n_symbols][symSz],
|
c16_t datatx_F_precoding[n_layers][symSz],
|
||||||
int ap,
|
int ap,
|
||||||
nfapi_nr_pm_pdu_t *pmi_pdu,
|
nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||||
int symbol,
|
|
||||||
int offset);
|
int offset);
|
||||||
|
|
||||||
/*! \brief Precoding with SIMDe, txdataF_precoded[] = prec_matrix[] * txdataF_res_mapped[]
|
/*! \brief Precoding with SIMDe, txdataF_precoded[] = prec_matrix[] * txdataF_res_mapped[]
|
||||||
@@ -150,13 +148,11 @@ c16_t nr_layer_precoder_cm(int n_layers,
|
|||||||
@param[out] txdataF_precoded Precoded antenna data
|
@param[out] txdataF_precoded Precoded antenna data
|
||||||
*/
|
*/
|
||||||
void nr_layer_precoder_simd(const int n_layers,
|
void nr_layer_precoder_simd(const int n_layers,
|
||||||
const int n_symbols,
|
const int symSz,
|
||||||
const int symSz,
|
const c16_t txdataF_res_mapped[n_layers][symSz],
|
||||||
const c16_t txdataF_res_mapped[n_layers][n_symbols][symSz],
|
const int ant,
|
||||||
const int ant,
|
const nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||||
const nfapi_nr_pm_pdu_t *pmi_pdu,
|
const int sc_offset,
|
||||||
const int symbol,
|
const int re_cnt,
|
||||||
const int sc_offset,
|
c16_t *txdataF_precoded);
|
||||||
const int re_cnt,
|
|
||||||
c16_t *txdataF_precoded);
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -514,6 +514,99 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms,
|
|||||||
return txl - txl_start;
|
return txl - txl_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void do_txdataF(c16_t **txdataF,
|
||||||
|
int symbol_sz,
|
||||||
|
c16_t txdataF_precoding[][symbol_sz],
|
||||||
|
PHY_VARS_gNB *gNB,
|
||||||
|
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||||
|
int ant,
|
||||||
|
int start_sc,
|
||||||
|
int txdataF_offset_per_symbol)
|
||||||
|
{
|
||||||
|
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||||
|
int rb = 0;
|
||||||
|
uint16_t subCarrier = start_sc;
|
||||||
|
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||||
|
while (rb < rel15->rbSize) {
|
||||||
|
// get pmi info
|
||||||
|
const int pmi = (pb->num_prgs > 0 && pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0;
|
||||||
|
const int pmi2 = (rb < (rel15->rbSize - 1) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 1) / pb->prg_size].pm_idx) : -1;
|
||||||
|
|
||||||
|
// If pmi of next RB and pmi of current RB are the same, we do 2 RB in a row
|
||||||
|
// if pmi differs, or current rb is the end (rel15->rbSize - 1), than we do 1 RB in a row
|
||||||
|
const int rb_step = pmi == pmi2 ? 2 : 1;
|
||||||
|
const int re_cnt = NR_NB_SC_PER_RB * rb_step;
|
||||||
|
|
||||||
|
if (pmi == 0) { // unitary Precoding
|
||||||
|
if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC
|
||||||
|
if (ant < rel15->nrOfLayers)
|
||||||
|
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
|
||||||
|
&txdataF_precoding[ant][subCarrier],
|
||||||
|
re_cnt * sizeof(**txdataF));
|
||||||
|
else
|
||||||
|
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF));
|
||||||
|
} else { // RB does cross DC
|
||||||
|
const int neg_length = symbol_sz - subCarrier;
|
||||||
|
const int pos_length = re_cnt - neg_length;
|
||||||
|
if (ant < rel15->nrOfLayers) {
|
||||||
|
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
|
||||||
|
&txdataF_precoding[ant][subCarrier],
|
||||||
|
neg_length * sizeof(**txdataF));
|
||||||
|
memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant], pos_length * sizeof(**txdataF));
|
||||||
|
} else {
|
||||||
|
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF));
|
||||||
|
memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subCarrier += re_cnt;
|
||||||
|
if (subCarrier >= symbol_sz) {
|
||||||
|
subCarrier -= symbol_sz;
|
||||||
|
}
|
||||||
|
} else { // non-unitary Precoding
|
||||||
|
AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n");
|
||||||
|
// get the precoding matrix weights:
|
||||||
|
nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix
|
||||||
|
AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx);
|
||||||
|
AssertFatal(ant < pmi_pdu->num_ant_ports,
|
||||||
|
"Antenna port index %d exceeds precoding matrix AP size %d\n",
|
||||||
|
ant,
|
||||||
|
pmi_pdu->num_ant_ports);
|
||||||
|
AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers,
|
||||||
|
"Number of layers %d doesn't match to the one in precoding matrix %d\n",
|
||||||
|
rel15->nrOfLayers,
|
||||||
|
pmi_pdu->numLayers);
|
||||||
|
if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe
|
||||||
|
nr_layer_precoder_simd(rel15->nrOfLayers,
|
||||||
|
symbol_sz,
|
||||||
|
txdataF_precoding,
|
||||||
|
ant,
|
||||||
|
pmi_pdu,
|
||||||
|
subCarrier,
|
||||||
|
re_cnt,
|
||||||
|
&txdataF[ant][txdataF_offset_per_symbol]);
|
||||||
|
subCarrier += re_cnt;
|
||||||
|
} else { // crossing ofdm_symbol_size, use simple arithmetic operations
|
||||||
|
for (int i = 0; i < re_cnt; i++) {
|
||||||
|
txdataF[ant][txdataF_offset_per_symbol + subCarrier] =
|
||||||
|
nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier);
|
||||||
|
#ifdef DEBUG_DLSCH_MAPPING
|
||||||
|
printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n",
|
||||||
|
ant,
|
||||||
|
l_symbol,
|
||||||
|
subCarrier,
|
||||||
|
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r,
|
||||||
|
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i);
|
||||||
|
#endif
|
||||||
|
if (++subCarrier >= symbol_sz) {
|
||||||
|
subCarrier -= symbol_sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // else{ // crossing ofdm_symbol_size, use simple arithmetic operations
|
||||||
|
} // else { // non-unitary Precoding
|
||||||
|
|
||||||
|
rb += rb_step;
|
||||||
|
} // RB loop: while(rb < rel15->rbSize)
|
||||||
|
}
|
||||||
static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot)
|
static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot)
|
||||||
{
|
{
|
||||||
const int16_t amp = gNB->TX_AMP;
|
const int16_t amp = gNB->TX_AMP;
|
||||||
@@ -618,8 +711,6 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
|||||||
start_sc -= symbol_sz;
|
start_sc -= symbol_sz;
|
||||||
|
|
||||||
const uint32_t txdataF_offset = slot * frame_parms->samples_per_slot_wCP;
|
const uint32_t txdataF_offset = slot * frame_parms->samples_per_slot_wCP;
|
||||||
c16_t txdataF_precoding[rel15->nrOfLayers][NR_NUMBER_OF_SYMBOLS_PER_SLOT][symbol_sz] __attribute__((aligned(64)));
|
|
||||||
memset(txdataF_precoding, 0, sizeof(txdataF_precoding));
|
|
||||||
#ifdef DEBUG_DLSCH_MAPPING
|
#ifdef DEBUG_DLSCH_MAPPING
|
||||||
printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n",
|
printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n",
|
||||||
start_sc,
|
start_sc,
|
||||||
@@ -634,12 +725,30 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
|||||||
c16_t mod_dmrs[(n_dmrs+63)&~63] __attribute__((aligned(64)));
|
c16_t mod_dmrs[(n_dmrs+63)&~63] __attribute__((aligned(64)));
|
||||||
unsigned int re_beginning_of_symbol = 0;
|
unsigned int re_beginning_of_symbol = 0;
|
||||||
|
|
||||||
start_meas(&gNB->dlsch_resource_mapping_stats);
|
|
||||||
int layerSz2 = (layerSz + 63) & ~63;
|
int layerSz2 = (layerSz + 63) & ~63;
|
||||||
c16_t tx_layers[rel15->nrOfLayers][layerSz2] __attribute__((aligned(64)));
|
c16_t tx_layers[rel15->nrOfLayers][layerSz2] __attribute__((aligned(64)));
|
||||||
memset(tx_layers, 0, sizeof(tx_layers));
|
memset(tx_layers, 0, sizeof(tx_layers));
|
||||||
nr_layer_mapping(rel15->NrOfCodewords, encoded_length, mod_symbs, rel15->nrOfLayers, layerSz2, nb_re, tx_layers);
|
nr_layer_mapping(rel15->NrOfCodewords, encoded_length, mod_symbs, rel15->nrOfLayers, layerSz2, nb_re, tx_layers);
|
||||||
|
|
||||||
|
/// Layer Precoding and Antenna port mapping
|
||||||
|
// tx_layers 1-8 are mapped on antenna ports 1000-1007
|
||||||
|
// 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
|
||||||
|
// The Precoding matrix:
|
||||||
|
// The Codebook Type I
|
||||||
|
start_meas(&gNB->dlsch_precoding_stats);
|
||||||
|
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||||
|
// beam number in multi-beam scenario (concurrent beams)
|
||||||
|
int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||||
|
int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||||
|
&gNB->common_vars,
|
||||||
|
slot,
|
||||||
|
frame_parms->symbols_per_slot,
|
||||||
|
bitmap);
|
||||||
|
|
||||||
|
c16_t **txdataF = gNB->common_vars.txdataF[beam_nb];
|
||||||
|
|
||||||
// Loop Over OFDM symbols:
|
// Loop Over OFDM symbols:
|
||||||
for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; l_symbol++) {
|
for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; l_symbol++) {
|
||||||
int l_prime = 0; // single symbol layer 0
|
int l_prime = 0; // single symbol layer 0
|
||||||
@@ -685,13 +794,14 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
|||||||
if (rel15->rnti != SI_RNTI)
|
if (rel15->rnti != SI_RNTI)
|
||||||
dmrs_idx += rel15->BWPStart;
|
dmrs_idx += rel15->BWPStart;
|
||||||
dmrs_idx *= dmrs_Type == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
|
dmrs_idx *= dmrs_Type == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
|
||||||
|
c16_t txdataF_precoding[rel15->nrOfLayers][symbol_sz] __attribute__((aligned(64)));
|
||||||
int layer_sz = 0;
|
int layer_sz = 0;
|
||||||
for (int layer = 0; layer < rel15->nrOfLayers; layer++) {
|
for (int layer = 0; layer < rel15->nrOfLayers; layer++) {
|
||||||
layer_sz = do_onelayer(frame_parms,
|
layer_sz = do_onelayer(frame_parms,
|
||||||
slot,
|
slot,
|
||||||
rel15,
|
rel15,
|
||||||
layer,
|
layer,
|
||||||
txdataF_precoding[layer][l_symbol],
|
txdataF_precoding[layer],
|
||||||
tx_layers[layer] + re_beginning_of_symbol,
|
tx_layers[layer] + re_beginning_of_symbol,
|
||||||
start_sc,
|
start_sc,
|
||||||
symbol_sz,
|
symbol_sz,
|
||||||
@@ -705,123 +815,13 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
|||||||
mod_dmrs + dmrs_idx);
|
mod_dmrs + dmrs_idx);
|
||||||
} // layer loop
|
} // layer loop
|
||||||
re_beginning_of_symbol += layer_sz;
|
re_beginning_of_symbol += layer_sz;
|
||||||
} // symbol loop
|
stop_meas(&gNB->dlsch_resource_mapping_stats);
|
||||||
stop_meas(&gNB->dlsch_resource_mapping_stats);
|
|
||||||
|
|
||||||
/// Layer Precoding and Antenna port mapping
|
for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) {
|
||||||
// tx_layers 1-8 are mapped on antenna ports 1000-1007
|
|
||||||
// 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
|
|
||||||
// The Precoding matrix:
|
|
||||||
// The Codebook Type I
|
|
||||||
start_meas(&gNB->dlsch_precoding_stats);
|
|
||||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
|
||||||
// beam number in multi-beam scenario (concurrent beams)
|
|
||||||
int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
|
||||||
int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
|
||||||
&gNB->common_vars,
|
|
||||||
slot,
|
|
||||||
frame_parms->symbols_per_slot,
|
|
||||||
bitmap);
|
|
||||||
|
|
||||||
c16_t **txdataF = gNB->common_vars.txdataF[beam_nb];
|
|
||||||
|
|
||||||
for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) {
|
|
||||||
for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; l_symbol++) {
|
|
||||||
uint16_t subCarrier = start_sc;
|
|
||||||
const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz + txdataF_offset;
|
const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz + txdataF_offset;
|
||||||
int rb = 0;
|
do_txdataF(txdataF, symbol_sz, txdataF_precoding, gNB, rel15, ant, start_sc, txdataF_offset_per_symbol);
|
||||||
|
}
|
||||||
while (rb < rel15->rbSize) {
|
}
|
||||||
// get pmi info
|
|
||||||
const int pmi = (pb->num_prgs > 0 && pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0;
|
|
||||||
const int pmi2 = (rb < (rel15->rbSize - 1) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 1) / pb->prg_size].pm_idx) : -1;
|
|
||||||
|
|
||||||
// If pmi of next RB and pmi of current RB are the same, we do 2 RB in a row
|
|
||||||
// if pmi differs, or current rb is the end (rel15->rbSize - 1), than we do 1 RB in a row
|
|
||||||
const int rb_step = pmi == pmi2 ? 2 : 1;
|
|
||||||
const int re_cnt = NR_NB_SC_PER_RB * rb_step;
|
|
||||||
|
|
||||||
if (pmi == 0) { // unitary Precoding
|
|
||||||
if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC
|
|
||||||
if (ant < rel15->nrOfLayers)
|
|
||||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
|
|
||||||
&txdataF_precoding[ant][l_symbol][subCarrier],
|
|
||||||
re_cnt * sizeof(**txdataF));
|
|
||||||
else
|
|
||||||
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF));
|
|
||||||
} else { // RB does cross DC
|
|
||||||
const int neg_length = symbol_sz - subCarrier;
|
|
||||||
const int pos_length = re_cnt - neg_length;
|
|
||||||
if (ant < rel15->nrOfLayers) {
|
|
||||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
|
|
||||||
&txdataF_precoding[ant][l_symbol][subCarrier],
|
|
||||||
neg_length * sizeof(**txdataF));
|
|
||||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant][l_symbol], pos_length * sizeof(**txdataF));
|
|
||||||
} else {
|
|
||||||
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF));
|
|
||||||
memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
subCarrier += re_cnt;
|
|
||||||
if (subCarrier >= symbol_sz) {
|
|
||||||
subCarrier -= symbol_sz;
|
|
||||||
}
|
|
||||||
} else { // non-unitary Precoding
|
|
||||||
AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n");
|
|
||||||
// get the precoding matrix weights:
|
|
||||||
nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix
|
|
||||||
AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx);
|
|
||||||
AssertFatal(ant < pmi_pdu->num_ant_ports,
|
|
||||||
"Antenna port index %d exceeds precoding matrix AP size %d\n",
|
|
||||||
ant,
|
|
||||||
pmi_pdu->num_ant_ports);
|
|
||||||
AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers,
|
|
||||||
"Number of layers %d doesn't match to the one in precoding matrix %d\n",
|
|
||||||
rel15->nrOfLayers,
|
|
||||||
pmi_pdu->numLayers);
|
|
||||||
if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe
|
|
||||||
nr_layer_precoder_simd(rel15->nrOfLayers,
|
|
||||||
NR_SYMBOLS_PER_SLOT,
|
|
||||||
symbol_sz,
|
|
||||||
txdataF_precoding,
|
|
||||||
ant,
|
|
||||||
pmi_pdu,
|
|
||||||
l_symbol,
|
|
||||||
subCarrier,
|
|
||||||
re_cnt,
|
|
||||||
&txdataF[ant][txdataF_offset_per_symbol]);
|
|
||||||
subCarrier += re_cnt;
|
|
||||||
} else { // crossing ofdm_symbol_size, use simple arithmetic operations
|
|
||||||
for (int i = 0; i < re_cnt; i++) {
|
|
||||||
txdataF[ant][txdataF_offset_per_symbol + subCarrier] = nr_layer_precoder_cm(rel15->nrOfLayers,
|
|
||||||
NR_SYMBOLS_PER_SLOT,
|
|
||||||
symbol_sz,
|
|
||||||
txdataF_precoding,
|
|
||||||
ant,
|
|
||||||
pmi_pdu,
|
|
||||||
l_symbol,
|
|
||||||
subCarrier);
|
|
||||||
#ifdef DEBUG_DLSCH_MAPPING
|
|
||||||
printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n",
|
|
||||||
ant,
|
|
||||||
l_symbol,
|
|
||||||
subCarrier,
|
|
||||||
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r,
|
|
||||||
txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i);
|
|
||||||
#endif
|
|
||||||
if (++subCarrier >= symbol_sz) {
|
|
||||||
subCarrier -= symbol_sz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // else{ // crossing ofdm_symbol_size, use simple arithmetic operations
|
|
||||||
} // else { // non-unitary Precoding
|
|
||||||
|
|
||||||
rb += rb_step;
|
|
||||||
} // RB loop: while(rb < rel15->rbSize)
|
|
||||||
} // symbol loop
|
|
||||||
} // port loop
|
|
||||||
|
|
||||||
stop_meas(&gNB->dlsch_precoding_stats);
|
stop_meas(&gNB->dlsch_precoding_stats);
|
||||||
/* output and its parts for each dlsch should be aligned on 64 bytes
|
/* output and its parts for each dlsch should be aligned on 64 bytes
|
||||||
|
|||||||
Reference in New Issue
Block a user