NR PDSCH zeroes RE around the DC. Added delay and CFO emulation to phy_dl_nr_test

master
Xavier Arteaga 4 years ago committed by Andre Puschmann
parent 667cc0b552
commit 2e3c00aa97

@ -37,6 +37,8 @@ typedef struct SRSRAN_API {
srsran_sch_nr_args_t sch; srsran_sch_nr_args_t sch;
bool measure_evm; bool measure_evm;
bool measure_time; bool measure_time;
bool disable_zero_re_around_dc; ///< PDSCH NR sets the LLR around the DC to zero to avoid noise
uint32_t nof_zero_re_around_dc; ///< Number of RE to set to zero around DC. It uses default value if 0.
} srsran_pdsch_nr_args_t; } srsran_pdsch_nr_args_t;
/** /**
@ -57,6 +59,8 @@ typedef struct SRSRAN_API {
uint32_t meas_time_us; uint32_t meas_time_us;
srsran_re_pattern_t dmrs_re_pattern; srsran_re_pattern_t dmrs_re_pattern;
uint32_t nof_rvd_re; uint32_t nof_rvd_re;
uint32_t nof_zero_re_around_dc; ///< Sets a number of RE surrounding the center of the resource grid to zero. Set to 0
///< for disabling.
} srsran_pdsch_nr_t; } srsran_pdsch_nr_t;
/** /**

@ -16,10 +16,14 @@
#include "srsran/phy/mimo/layermap.h" #include "srsran/phy/mimo/layermap.h"
#include "srsran/phy/mimo/precoding.h" #include "srsran/phy/mimo/precoding.h"
#include "srsran/phy/modem/demod_soft.h" #include "srsran/phy/modem/demod_soft.h"
#include "srsran/phy/phch/ra_nr.h"
///@brief Default number of zero RE around DC
#define PDSCH_NR_DEFAULT_NOF_ZERO_RE_AROUND_DC 3
int pdsch_nr_init_common(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args) int pdsch_nr_init_common(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* args)
{ {
SRSRAN_MEM_ZERO(q, srsran_pdsch_nr_t, 1);
for (srsran_mod_t mod = SRSRAN_MOD_BPSK; mod < SRSRAN_MOD_NITEMS; mod++) { for (srsran_mod_t mod = SRSRAN_MOD_BPSK; mod < SRSRAN_MOD_NITEMS; mod++) {
if (srsran_modem_table_lte(&q->modem_tables[mod], mod) < SRSRAN_SUCCESS) { if (srsran_modem_table_lte(&q->modem_tables[mod], mod) < SRSRAN_SUCCESS) {
ERROR("Error initialising modem table for %s", srsran_mod_string(mod)); ERROR("Error initialising modem table for %s", srsran_mod_string(mod));
@ -30,6 +34,14 @@ int pdsch_nr_init_common(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* arg
} }
} }
if (!args->disable_zero_re_around_dc) {
if (args->nof_zero_re_around_dc == 0) {
q->nof_zero_re_around_dc = PDSCH_NR_DEFAULT_NOF_ZERO_RE_AROUND_DC;
} else {
q->nof_zero_re_around_dc = args->nof_zero_re_around_dc;
}
}
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }
@ -236,7 +248,23 @@ static int srsran_pdsch_nr_cp(const srsran_pdsch_nr_t* q,
if (put) { if (put) {
count += pdsch_nr_put_rb(&sf_symbols[re_idx], &symbols[count], &rvd_mask[rb * SRSRAN_NRE]); count += pdsch_nr_put_rb(&sf_symbols[re_idx], &symbols[count], &rvd_mask[rb * SRSRAN_NRE]);
} else { } else {
count += pdsch_nr_get_rb(&symbols[count], &sf_symbols[re_idx], &rvd_mask[rb * SRSRAN_NRE]); uint32_t k_begin = rb * SRSRAN_NRE;
uint32_t k_end = (rb + 1) * SRSRAN_NRE;
uint32_t k_dc_begin = q->carrier.nof_prb * SRSRAN_NRE / 2 - q->nof_zero_re_around_dc / 2;
uint32_t k_dc_end = q->carrier.nof_prb * SRSRAN_NRE / 2 + SRSRAN_CEIL(q->nof_zero_re_around_dc, 2);
if (k_begin <= k_dc_end && k_end >= k_dc_begin && q->nof_zero_re_around_dc > 0) {
for (uint32_t k = k_begin; k < k_end; k++) {
if (!rvd_mask[k]) {
if (k >= k_dc_begin && k < k_dc_end) {
symbols[count++] = 0.0f;
} else {
symbols[count++] = sf_symbols[q->carrier.nof_prb * l * SRSRAN_NRE + k];
}
}
}
} else {
count += pdsch_nr_get_rb(&symbols[count], &sf_symbols[re_idx], &rvd_mask[rb * SRSRAN_NRE]);
}
} }
} }
} }
@ -544,7 +572,7 @@ static uint32_t srsran_pdsch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
uint32_t str_len) uint32_t str_len)
{ {
uint32_t len = 0; uint32_t len = 0;
len = srsran_print_check(str, str_len, len, "rnti=0x%x", grant->rnti); len = srsran_print_check(str, str_len, len, "rnti=0x%x ", grant->rnti);
uint32_t first_prb = SRSRAN_MAX_PRB_NR; uint32_t first_prb = SRSRAN_MAX_PRB_NR;
for (uint32_t i = 0; i < SRSRAN_MAX_PRB_NR && first_prb == SRSRAN_MAX_PRB_NR; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_PRB_NR && first_prb == SRSRAN_MAX_PRB_NR; i++) {
@ -557,7 +585,9 @@ static uint32_t srsran_pdsch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
len = srsran_print_check(str, len = srsran_print_check(str,
str_len, str_len,
len, len,
",k0=%d,prb=%d:%d,symb=%d:%d,mapping=%s", "beta_dmrs=%.3f CDM-grp=%d k0=%d prb=%d:%d symb=%d:%d mapping=%s ",
isnormal(grant->beta_dmrs) ? grant->beta_dmrs : 1.0f,
grant->nof_dmrs_cdm_groups_without_data,
grant->k, grant->k,
first_prb, first_prb,
grant->nof_prb, grant->nof_prb,
@ -569,10 +599,10 @@ static uint32_t srsran_pdsch_nr_grant_info(const srsran_sch_cfg_nr_t* cfg,
// ... // ...
// Append spatial resources // Append spatial resources
len = srsran_print_check(str, str_len, len, ",Nl=%d", grant->nof_layers); len = srsran_print_check(str, str_len, len, "Nl=%d ", grant->nof_layers);
// Append scrambling ID // Append scrambling ID
len = srsran_print_check(str, str_len, len, ",n_scid=%d,", grant->n_scid); len = srsran_print_check(str, str_len, len, "n_scid=%d ", grant->n_scid);
// Append TB info // Append TB info
for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) { for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) {

@ -714,7 +714,7 @@ int srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, char* str, uint32_t str_len
len += srsran_print_check(str, len += srsran_print_check(str,
str_len, str_len,
len, len,
"tb={mod=%s,Nl=%d,tbs=%d,R=%.3f,rv=%d,Nre=%d,Nbit=%d,cw=%d}", "CW0: mod=%s Nl=%d tbs=%d R=%.3f rv=%d Nre=%d Nbit=%d cw=%d",
srsran_mod_string(tb->mod), srsran_mod_string(tb->mod),
tb->N_L, tb->N_L,
tb->tbs / 8, tb->tbs / 8,

@ -33,6 +33,8 @@ static uint32_t mcs = 30; // Set to 30 for steering
static srsran_sch_cfg_nr_t pdsch_cfg = {}; static srsran_sch_cfg_nr_t pdsch_cfg = {};
static uint32_t nof_slots = 10; static uint32_t nof_slots = 10;
static uint32_t rv_idx = 0; static uint32_t rv_idx = 0;
static uint32_t delay_n = 4; // Integer delay
static float cfo_hz = 100.0f; // CFO Hz
static void usage(char* prog) static void usage(char* prog)
{ {
@ -46,13 +48,15 @@ static void usage(char* prog)
srsran_mcs_table_to_str(pdsch_cfg.sch_cfg.mcs_table)); srsran_mcs_table_to_str(pdsch_cfg.sch_cfg.mcs_table));
printf("\t-R Reserve RE: [rb_begin] [rb_end] [rb_stride] [sc_mask] [symbol_mask]\n"); printf("\t-R Reserve RE: [rb_begin] [rb_end] [rb_stride] [sc_mask] [symbol_mask]\n");
printf("\t-L Provide number of layers [Default %d]\n", carrier.max_mimo_layers); printf("\t-L Provide number of layers [Default %d]\n", carrier.max_mimo_layers);
printf("\t-D Delay signal an integer number of samples [Default %d samples]\n", delay_n);
printf("\t-C Frequency shift (CFO) signal in Hz [Default %+.0f Hz]\n", cfo_hz);
printf("\t-v [set srsran_verbose to debug, default none]\n"); printf("\t-v [set srsran_verbose to debug, default none]\n");
} }
static int parse_args(int argc, char** argv) static int parse_args(int argc, char** argv)
{ {
int opt; int opt;
while ((opt = getopt(argc, argv, "rRPpmnTLv")) != -1) { while ((opt = getopt(argc, argv, "rRPpmnTLDCv")) != -1) {
switch (opt) { switch (opt) {
case 'P': case 'P':
carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10); carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
@ -93,6 +97,12 @@ static int parse_args(int argc, char** argv)
case 'L': case 'L':
carrier.max_mimo_layers = (uint32_t)strtol(argv[optind], NULL, 10); carrier.max_mimo_layers = (uint32_t)strtol(argv[optind], NULL, 10);
break; break;
case 'D':
delay_n = (uint32_t)strtol(argv[optind], NULL, 10);
break;
case 'C':
cfo_hz = strtof(argv[optind], NULL);
break;
case 'v': case 'v':
srsran_verbose++; srsran_verbose++;
break; break;
@ -187,22 +197,26 @@ int main(int argc, char** argv)
uint8_t* data_tx[SRSRAN_MAX_TB] = {}; uint8_t* data_tx[SRSRAN_MAX_TB] = {};
uint8_t* data_rx[SRSRAN_MAX_CODEWORDS] = {}; uint8_t* data_rx[SRSRAN_MAX_CODEWORDS] = {};
cf_t* buffer = NULL; cf_t* buffer_gnb[SRSRAN_MAX_PORTS] = {};
cf_t* buffer_ue[SRSRAN_MAX_PORTS] = {};
buffer = srsran_vec_cf_malloc(SRSRAN_SF_LEN_PRB(carrier.nof_prb)); uint32_t sf_len = SRSRAN_SF_LEN_PRB(carrier.nof_prb);
if (buffer == NULL) { buffer_gnb[0] = srsran_vec_cf_malloc(sf_len);
buffer_ue[0] = srsran_vec_cf_malloc(sf_len);
if (buffer_gnb[0] == NULL || buffer_ue[0] == NULL) {
ERROR("Error malloc"); ERROR("Error malloc");
goto clean_exit; goto clean_exit;
} }
srsran_ue_dl_nr_args_t ue_dl_args = {}; srsran_ue_dl_nr_args_t ue_dl_args = {};
ue_dl_args.nof_rx_antennas = 1; ue_dl_args.nof_rx_antennas = 1;
ue_dl_args.pdsch.sch.disable_simd = false; ue_dl_args.pdsch.sch.disable_simd = false;
ue_dl_args.pdsch.sch.decoder_use_flooded = false; ue_dl_args.pdsch.sch.decoder_use_flooded = false;
ue_dl_args.pdsch.measure_evm = true; ue_dl_args.pdsch.measure_evm = true;
ue_dl_args.pdcch.disable_simd = false; ue_dl_args.pdsch.disable_zero_re_around_dc = true;
ue_dl_args.pdcch.measure_evm = true; ue_dl_args.pdcch.disable_simd = false;
ue_dl_args.nof_max_prb = carrier.nof_prb; ue_dl_args.pdcch.measure_evm = true;
ue_dl_args.nof_max_prb = carrier.nof_prb;
srsran_enb_dl_nr_args_t enb_dl_args = {}; srsran_enb_dl_nr_args_t enb_dl_args = {};
enb_dl_args.nof_tx_antennas = 1; enb_dl_args.nof_tx_antennas = 1;
@ -239,12 +253,12 @@ int main(int argc, char** argv)
search_space->nof_candidates[L] = srsran_pdcch_nr_max_candidates_coreset(coreset, L); search_space->nof_candidates[L] = srsran_pdcch_nr_max_candidates_coreset(coreset, L);
} }
if (srsran_ue_dl_nr_init(&ue_dl, &buffer, &ue_dl_args)) { if (srsran_ue_dl_nr_init(&ue_dl, buffer_ue, &ue_dl_args)) {
ERROR("Error UE DL"); ERROR("Error UE DL");
goto clean_exit; goto clean_exit;
} }
if (srsran_enb_dl_nr_init(&enb_dl, &buffer, &enb_dl_args)) { if (srsran_enb_dl_nr_init(&enb_dl, buffer_gnb, &enb_dl_args)) {
ERROR("Error UE DL"); ERROR("Error UE DL");
goto clean_exit; goto clean_exit;
} }
@ -309,6 +323,7 @@ int main(int argc, char** argv)
pdsch_cfg.grant.nof_layers = carrier.max_mimo_layers; pdsch_cfg.grant.nof_layers = carrier.max_mimo_layers;
pdsch_cfg.grant.dci_format = srsran_dci_format_nr_1_0; pdsch_cfg.grant.dci_format = srsran_dci_format_nr_1_0;
pdsch_cfg.grant.nof_dmrs_cdm_groups_without_data = 1; pdsch_cfg.grant.nof_dmrs_cdm_groups_without_data = 1;
pdsch_cfg.grant.beta_dmrs = srsran_convert_dB_to_amplitude(3);
pdsch_cfg.grant.rnti_type = srsran_rnti_type_c; pdsch_cfg.grant.rnti_type = srsran_rnti_type_c;
pdsch_cfg.grant.rnti = 0x4601; pdsch_cfg.grant.rnti = 0x4601;
pdsch_cfg.grant.tb[0].rv = rv_idx; pdsch_cfg.grant.tb[0].rv = rv_idx;
@ -381,6 +396,22 @@ int main(int argc, char** argv)
get_time_interval(t); get_time_interval(t);
pdsch_encode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec); pdsch_encode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec);
// Emulate channel delay
if (delay_n >= sf_len) {
ERROR("Delay exceeds SF length");
goto clean_exit;
}
srsran_vec_cf_copy(&buffer_ue[0][0], &buffer_gnb[0][delay_n], sf_len - delay_n);
srsran_vec_cf_copy(&buffer_ue[0][sf_len - delay_n], &buffer_gnb[0][0], delay_n);
// Emulate channel CFO
if (isnormal(cfo_hz) && ue_dl.fft[0].cfg.symbol_sz > 0) {
srsran_vec_apply_cfo(buffer_ue[0],
cfo_hz / (ue_dl.fft[0].cfg.symbol_sz * SRSRAN_SUBC_SPACING_NR(carrier.numerology)),
buffer_ue[0],
sf_len);
}
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) { for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
pdsch_cfg.grant.tb[tb].softbuffer.rx = &softbuffer_rx; pdsch_cfg.grant.tb[tb].softbuffer.rx = &softbuffer_rx;
srsran_softbuffer_rx_reset(pdsch_cfg.grant.tb[tb].softbuffer.rx); srsran_softbuffer_rx_reset(pdsch_cfg.grant.tb[tb].softbuffer.rx);
@ -395,7 +426,7 @@ int main(int argc, char** argv)
get_time_interval(t); get_time_interval(t);
pdsch_decode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec); pdsch_decode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec);
if (pdsch_res->evm > 0.001f) { if (pdsch_res->evm > 0.02f) {
ERROR("Error PDSCH EVM is too high %f", pdsch_res->evm); ERROR("Error PDSCH EVM is too high %f", pdsch_res->evm);
goto clean_exit; goto clean_exit;
} }
@ -447,8 +478,11 @@ clean_exit:
free(data_rx[i]); free(data_rx[i]);
} }
} }
if (buffer) { if (buffer_gnb[0]) {
free(buffer); free(buffer_gnb[0]);
}
if (buffer_ue[0]) {
free(buffer_ue[0]);
} }
srsran_softbuffer_tx_free(&softbuffer_tx); srsran_softbuffer_tx_free(&softbuffer_tx);
srsran_softbuffer_rx_free(&softbuffer_rx); srsran_softbuffer_rx_free(&softbuffer_rx);

Loading…
Cancel
Save