From 407903e0d616a2e47dd26573b0739eef5fb04d32 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 19 Apr 2021 20:50:11 +0200 Subject: [PATCH] SRSUE: refactor carrier setting for accepting a dynamic carrier configuration --- .../interfaces/rrc_nr_interface_types.h | 4 +- .../srsran/interfaces/ue_nr_interfaces.h | 23 ++-- .../srsran/interfaces/ue_phy_interfaces.h | 2 +- lib/include/srsran/phy/common/phy_common_nr.h | 4 +- lib/include/srsran/phy/phch/pdsch_nr.h | 2 + lib/include/srsran/phy/phch/pusch_nr.h | 2 + lib/src/phy/ch_estimation/dmrs_sch.c | 118 ++++++++++-------- lib/src/phy/common/phy_common_nr.c | 31 +++++ lib/src/phy/phch/pdsch_nr.c | 53 +++++--- lib/src/phy/phch/pusch_nr.c | 53 +++++--- lib/src/phy/ue/ue_dl_nr.c | 2 +- srsenb/src/phy/nr/cc_worker.cc | 2 +- srsue/hdr/phy/nr/cc_worker.h | 1 - srsue/hdr/phy/nr/sf_worker.h | 1 - srsue/hdr/phy/nr/state.h | 14 +-- srsue/src/main.cc | 2 +- srsue/src/phy/nr/cc_worker.cc | 27 ++-- srsue/src/phy/nr/sf_worker.cc | 11 +- srsue/src/phy/nr/worker_pool.cc | 44 ++++--- srsue/src/ue.cc | 6 +- 20 files changed, 237 insertions(+), 165 deletions(-) diff --git a/lib/include/srsran/interfaces/rrc_nr_interface_types.h b/lib/include/srsran/interfaces/rrc_nr_interface_types.h index 0f796b646..c2930a54b 100644 --- a/lib/include/srsran/interfaces/rrc_nr_interface_types.h +++ b/lib/include/srsran/interfaces/rrc_nr_interface_types.h @@ -33,13 +33,13 @@ struct phy_cfg_nr_t { srsran_ue_dl_nr_harq_ack_cfg_t harq_ack = {}; srsran_csi_hl_cfg_t csi = {}; srsran_carrier_nr_t carrier = {}; - + phy_cfg_nr_t() {} /** * @param carrier */ - srsran_dci_cfg_nr_t get_dci_cfg(const srsran_carrier_nr_t& carrier) const + srsran_dci_cfg_nr_t get_dci_cfg() const { srsran_dci_cfg_nr_t dci_cfg = {}; diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index c355440cc..3b85c0cbd 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -45,12 +45,12 @@ public: } tb_action_dl_t; typedef struct { - uint16_t rnti; - uint32_t tti; - uint8_t pid; // HARQ process ID - uint8_t rv; // Redundancy Version - uint8_t ndi; // Raw new data indicator extracted from DCI - uint32_t tbs; // Transport block size in Bytes + uint16_t rnti; + uint32_t tti; + uint8_t pid; // HARQ process ID + uint8_t rv; // Redundancy Version + uint8_t ndi; // Raw new data indicator extracted from DCI + uint32_t tbs; // Transport block size in Bytes } mac_nr_grant_dl_t; typedef struct { @@ -167,7 +167,7 @@ public: struct phy_args_nr_t { uint32_t nof_carriers = 1; - uint32_t nof_prb = 52; + uint32_t max_nof_prb = 106; uint32_t nof_phy_threads = 3; uint32_t worker_cpu_mask = 0; srsran::phy_log_args_t log = {}; @@ -179,11 +179,16 @@ struct phy_args_nr_t { phy_args_nr_t() { dl.nof_rx_antennas = 1; - dl.nof_max_prb = 100; + dl.nof_max_prb = 106; + dl.pdsch.max_prb = 106; + dl.pdsch.max_layers = 1; dl.pdsch.measure_evm = true; dl.pdsch.measure_time = true; dl.pdsch.sch.disable_simd = false; - ul.nof_max_prb = 100; + dl.pdsch.sch.max_nof_iter = 10; + ul.nof_max_prb = 106; + ul.pusch.max_prb = 106; + ul.pusch.max_layers = 1; ul.pusch.measure_time = true; ul.pusch.sch.disable_simd = false; diff --git a/lib/include/srsran/interfaces/ue_phy_interfaces.h b/lib/include/srsran/interfaces/ue_phy_interfaces.h index 3ed10ee08..245b671b5 100644 --- a/lib/include/srsran/interfaces/ue_phy_interfaces.h +++ b/lib/include/srsran/interfaces/ue_phy_interfaces.h @@ -53,7 +53,7 @@ struct phy_args_t { uint32_t nof_lte_carriers = 1; uint32_t nof_nr_carriers = 0; - uint32_t nr_nof_prb = 50; + uint32_t nr_max_nof_prb = 106; double nr_freq_hz = 2630e6; uint32_t nof_rx_ant = 1; std::string equalizer_mode = "mmse"; diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 5acd3fafe..7a4fb454b 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -281,7 +281,7 @@ typedef struct SRSRAN_API { uint32_t absolute_frequency_ssb; uint32_t absolute_frequency_point_a; srsran_subcarrier_spacing_t scs; - uint32_t nof_prb; + uint32_t nof_prb; ///< @brief See TS 38.101-1 Table 5.3.2-1 for more details uint32_t start; uint32_t max_mimo_layers; ///< @brief DL: Indicates the maximum number of MIMO layers to be used for PDSCH in all BWPs ///< of this serving cell. (see TS 38.212 [17], clause 5.4.2.1). UL: Indicates the maximum @@ -466,6 +466,8 @@ SRSRAN_API bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t */ SRSRAN_API bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); +SRSRAN_API int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell); + #ifdef __cplusplus } #endif diff --git a/lib/include/srsran/phy/phch/pdsch_nr.h b/lib/include/srsran/phy/phch/pdsch_nr.h index f3326f55f..2d84f78e9 100644 --- a/lib/include/srsran/phy/phch/pdsch_nr.h +++ b/lib/include/srsran/phy/phch/pdsch_nr.h @@ -37,6 +37,8 @@ typedef struct SRSRAN_API { srsran_sch_nr_args_t sch; bool measure_evm; bool measure_time; + uint32_t max_prb; + uint32_t max_layers; } srsran_pdsch_nr_args_t; /** diff --git a/lib/include/srsran/phy/phch/pusch_nr.h b/lib/include/srsran/phy/phch/pusch_nr.h index f61755caa..5073fd9ec 100644 --- a/lib/include/srsran/phy/phch/pusch_nr.h +++ b/lib/include/srsran/phy/phch/pusch_nr.h @@ -31,6 +31,8 @@ typedef struct SRSRAN_API { srsran_uci_nr_args_t uci; bool measure_evm; bool measure_time; + uint32_t max_layers; + uint32_t max_prb; } srsran_pusch_nr_args_t; /** diff --git a/lib/src/phy/ch_estimation/dmrs_sch.c b/lib/src/phy/ch_estimation/dmrs_sch.c index 5153c8bf6..37dd0b410 100644 --- a/lib/src/phy/ch_estimation/dmrs_sch.c +++ b/lib/src/phy/ch_estimation/dmrs_sch.c @@ -39,6 +39,11 @@ */ #define DMRS_SCH_SMOOTH_FILTER_STDDEV 2 +/** + * @brief Default number of PRB at initialization + */ +#define DMRS_SCH_MAX_NOF_PRB 106 + int srsran_dmrs_sch_cfg_to_str(const srsran_dmrs_sch_cfg_t* cfg, char* msg, uint32_t max_len) { int type = (int)cfg->type + 1; @@ -517,6 +522,58 @@ static uint32_t srsran_dmrs_sch_seed(const srsran_carrier_nr_t* carrier, (2UL * n_id + n_scid)); } +static int dmrs_sch_alloc(srsran_dmrs_sch_t* q, uint32_t max_nof_prb) +{ + bool max_nof_prb_changed = q->max_nof_prb < max_nof_prb; + + // Update maximum number of PRB + q->max_nof_prb = max_nof_prb; + + // Resize/allocate temp for gNb and UE + if (max_nof_prb_changed) { + if (q->temp) { + free(q->temp); + } + + q->temp = srsran_vec_cf_malloc(max_nof_prb * SRSRAN_NRE); + if (!q->temp) { + ERROR("malloc"); + return SRSRAN_ERROR; + } + } + + // If it is not UE, quit now + if (!q->is_rx) { + return SRSRAN_SUCCESS; + } + + if (max_nof_prb_changed) { + // Resize interpolator only if the number of PRB has increased + srsran_interp_linear_free(&q->interpolator_type1); + srsran_interp_linear_free(&q->interpolator_type2); + + if (srsran_interp_linear_init(&q->interpolator_type1, max_nof_prb * SRSRAN_NRE / 2, 2) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + if (srsran_interp_linear_init(&q->interpolator_type2, max_nof_prb * SRSRAN_NRE / 3, 6) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (q->pilot_estimates) { + free(q->pilot_estimates); + } + + // The maximum number of pilots is for Type 1 + q->pilot_estimates = srsran_vec_cf_malloc(SRSRAN_DMRS_SCH_MAX_SYMBOLS * max_nof_prb * SRSRAN_NRE / 2); + if (!q->pilot_estimates) { + ERROR("malloc"); + return SRSRAN_ERROR; + } + } + + return SRSRAN_SUCCESS; +} + int srsran_dmrs_sch_init(srsran_dmrs_sch_t* q, bool is_rx) { if (q == NULL) { @@ -539,6 +596,10 @@ int srsran_dmrs_sch_init(srsran_dmrs_sch_t* q, bool is_rx) } #endif // DMRS_SCH_SMOOTH_FILTER_LEN + if (dmrs_sch_alloc(q, DMRS_SCH_MAX_NOF_PRB) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } @@ -565,52 +626,11 @@ void srsran_dmrs_sch_free(srsran_dmrs_sch_t* q) int srsran_dmrs_sch_set_carrier(srsran_dmrs_sch_t* q, const srsran_carrier_nr_t* carrier) { - bool max_nof_prb_changed = q->max_nof_prb < carrier->nof_prb; - - // Set carrier and update maximum number of PRB - q->carrier = *carrier; - q->max_nof_prb = SRSRAN_MAX(q->max_nof_prb, carrier->nof_prb); - - // Resize/allocate temp for gNb and UE - if (max_nof_prb_changed) { - if (q->temp) { - free(q->temp); - } - - q->temp = srsran_vec_cf_malloc(q->max_nof_prb * SRSRAN_NRE); - if (!q->temp) { - ERROR("malloc"); - return SRSRAN_ERROR; - } - } - - // If it is not UE, quit now - if (!q->is_rx) { - return SRSRAN_SUCCESS; - } - - if (max_nof_prb_changed) { - // Resize interpolator only if the number of PRB has increased - srsran_interp_linear_free(&q->interpolator_type1); - srsran_interp_linear_free(&q->interpolator_type2); - - if (srsran_interp_linear_init(&q->interpolator_type1, carrier->nof_prb * SRSRAN_NRE / 2, 2) != SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - if (srsran_interp_linear_init(&q->interpolator_type2, carrier->nof_prb * SRSRAN_NRE / 3, 6) != SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - - if (q->pilot_estimates) { - free(q->pilot_estimates); - } + // Set carrier + q->carrier = *carrier; - // The maximum number of pilots is for Type 1 - q->pilot_estimates = srsran_vec_cf_malloc(SRSRAN_DMRS_SCH_MAX_SYMBOLS * q->max_nof_prb * SRSRAN_NRE / 2); - if (!q->pilot_estimates) { - ERROR("malloc"); - return SRSRAN_ERROR; - } + if (dmrs_sch_alloc(q, carrier->nof_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; } return SRSRAN_SUCCESS; @@ -639,7 +659,7 @@ int srsran_dmrs_sch_put_sf(srsran_dmrs_sch_t* q, // Iterate symbols for (uint32_t i = 0; i < nof_symbols; i++) { - uint32_t l = symbols[i]; // Symbol index inside the slot + uint32_t l = symbols[i]; // Symbol index inside the slot uint32_t slot_idx = SRSRAN_SLOT_NR_MOD(q->carrier.scs, slot_cfg->idx); // Slot index in the frame uint32_t cinit = srsran_dmrs_sch_seed(&q->carrier, pdsch_cfg, grant, slot_idx, l); @@ -770,8 +790,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q, for (uint32_t i = 0; i < nof_symbols; i++) { uint32_t l = symbols[i]; // Symbol index inside the slot - uint32_t cinit = - srsran_dmrs_sch_seed(&q->carrier, cfg, grant, SRSRAN_SLOT_NR_MOD(q->carrier.scs, slot->idx), l); + uint32_t cinit = srsran_dmrs_sch_seed(&q->carrier, cfg, grant, SRSRAN_SLOT_NR_MOD(q->carrier.scs, slot->idx), l); nof_pilots_x_symbol = srsran_dmrs_sch_get_symbol( q, cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l], &q->pilot_estimates[nof_pilots_x_symbol * i]); @@ -842,8 +861,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q, cf_t cfo_correction[SRSRAN_NSYMB_PER_SLOT_NR] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; if (isnormal(cfo_avg)) { // Calculate phase of the first OFDM symbol (l = 0) - float arg0 = - cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.scs) * cfo_avg; + float arg0 = cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.scs) * cfo_avg; // Calculate CFO corrections for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) { diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 360f4ca7b..1f88ba9bc 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -11,6 +11,7 @@ */ #include "srsran/phy/common/phy_common_nr.h" +#include "srsran/phy/utils/vector.h" #include const char* srsran_rnti_type_str(srsran_rnti_type_t rnti_type) @@ -236,3 +237,33 @@ bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, // Check UL boundaries return (slot_idx_period > start_ul || (slot_idx_period == start_ul && pattern->nof_ul_symbols != 0)); } + +int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell) +{ + // Protect memory access + if (carrier == NULL || cell == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Ensure cell is initialised+ + SRSRAN_MEM_ZERO(cell, srsran_cell_t, 1); + + // Select number of PRB + if (carrier->nof_prb <= 25) { + cell->nof_prb = 25; + } else if (carrier->nof_prb <= 52) { + cell->nof_prb = 50; + } else if (carrier->nof_prb <= 79) { + cell->nof_prb = 75; + } else if (carrier->nof_prb <= 106) { + cell->nof_prb = 100; + } else { + return SRSRAN_ERROR_OUT_OF_BOUNDS; + } + + // Set other parameters + cell->id = carrier->pci; + cell->nof_ports = carrier->max_mimo_layers; + + return SRSRAN_SUCCESS; +} diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 5c184cbc7..0f3da4783 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -17,6 +17,33 @@ #include "srsran/phy/mimo/precoding.h" #include "srsran/phy/modem/demod_soft.h" +static int pdsch_nr_alloc(srsran_pdsch_nr_t* q, uint32_t max_mimo_layers, uint32_t max_prb) +{ + // Reallocate symbols if necessary + if (q->max_layers < max_mimo_layers || q->max_prb < max_prb) { + q->max_layers = max_mimo_layers; + q->max_prb = max_prb; + + // Free current allocations + for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) { + if (q->x[i] != NULL) { + free(q->x[i]); + } + } + + // Allocate for new sizes + for (uint32_t i = 0; i < q->max_layers; i++) { + q->x[i] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb)); + if (q->x[i] == NULL) { + ERROR("Malloc"); + return SRSRAN_ERROR; + } + } + } + + return SRSRAN_SUCCESS; +} + 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); @@ -31,6 +58,10 @@ int pdsch_nr_init_common(srsran_pdsch_nr_t* q, const srsran_pdsch_nr_args_t* arg } } + if (pdsch_nr_alloc(q, args->max_layers, args->max_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } @@ -85,26 +116,8 @@ int srsran_pdsch_nr_set_carrier(srsran_pdsch_nr_t* q, const srsran_carrier_nr_t* // Set carrier q->carrier = *carrier; - // Reallocate symbols if necessary - if (q->max_layers < carrier->max_mimo_layers || q->max_prb < carrier->nof_prb) { - q->max_layers = carrier->max_mimo_layers; - q->max_prb = carrier->nof_prb; - - // Free current allocations - for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) { - if (q->x[i] != NULL) { - free(q->x[i]); - } - } - - // Allocate for new sizes - for (uint32_t i = 0; i < q->max_layers; i++) { - q->x[i] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb)); - if (q->x[i] == NULL) { - ERROR("Malloc"); - return SRSRAN_ERROR; - } - } + if (pdsch_nr_alloc(q, carrier->max_mimo_layers, carrier->nof_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; } // Allocate code words according to table 7.3.1.3-1 diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 1d7c8e880..1a7bd672c 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -18,6 +18,33 @@ #include "srsran/phy/phch/ra_nr.h" #include "srsran/phy/phch/uci_cfg.h" +static int pusch_nr_alloc(srsran_pusch_nr_t* q, uint32_t max_mimo_layers, uint32_t max_prb) +{ + // Reallocate symbols if necessary + if (q->max_layers < max_mimo_layers || q->max_prb < max_prb) { + q->max_layers = max_mimo_layers; + q->max_prb = max_prb; + + // Free current allocations + for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) { + if (q->x[i] != NULL) { + free(q->x[i]); + } + } + + // Allocate for new sizes + for (uint32_t i = 0; i < q->max_layers; i++) { + q->x[i] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb)); + if (q->x[i] == NULL) { + ERROR("Malloc"); + return SRSRAN_ERROR; + } + } + } + + return SRSRAN_SUCCESS; +} + int pusch_nr_init_common(srsran_pusch_nr_t* q, const srsran_pusch_nr_args_t* args) { for (srsran_mod_t mod = SRSRAN_MOD_BPSK; mod < SRSRAN_MOD_NITEMS; mod++) { @@ -30,6 +57,10 @@ int pusch_nr_init_common(srsran_pusch_nr_t* q, const srsran_pusch_nr_args_t* arg } } + if (pusch_nr_alloc(q, args->max_layers, args->max_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + if (srsran_uci_nr_init(&q->uci, &args->uci) < SRSRAN_SUCCESS) { ERROR("Initialising UCI"); return SRSRAN_ERROR; @@ -107,26 +138,8 @@ int srsran_pusch_nr_set_carrier(srsran_pusch_nr_t* q, const srsran_carrier_nr_t* // Set carrier q->carrier = *carrier; - // Reallocate symbols if necessary - if (q->max_layers < carrier->max_mimo_layers || q->max_prb < carrier->nof_prb) { - q->max_layers = carrier->max_mimo_layers; - q->max_prb = carrier->nof_prb; - - // Free current allocations - for (uint32_t i = 0; i < SRSRAN_MAX_LAYERS_NR; i++) { - if (q->x[i] != NULL) { - free(q->x[i]); - } - } - - // Allocate for new sizes - for (uint32_t i = 0; i < q->max_layers; i++) { - q->x[i] = srsran_vec_cf_malloc(SRSRAN_SLOT_LEN_RE_NR(q->max_prb)); - if (q->x[i] == NULL) { - ERROR("Malloc"); - return SRSRAN_ERROR; - } - } + if (pusch_nr_alloc(q, carrier->max_mimo_layers, carrier->nof_prb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; } // Allocate code words according to table 7.3.1.3-1 diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index 7c0cf344f..cf45ea0fc 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -87,7 +87,7 @@ int srsran_ue_dl_nr_init(srsran_ue_dl_nr_t* q, cf_t* input[SRSRAN_MAX_PORTS], co srsran_ofdm_cfg_t fft_cfg = {}; fft_cfg.nof_prb = args->nof_max_prb; - fft_cfg.symbol_sz = srsran_symbol_sz(args->nof_max_prb); + fft_cfg.symbol_sz = srsran_min_symbol_sz_rb(args->nof_max_prb); fft_cfg.keep_dc = true; fft_cfg.rx_window_offset = UE_DL_NR_FFT_WINDOW_OFFSET; diff --git a/srsenb/src/phy/nr/cc_worker.cc b/srsenb/src/phy/nr/cc_worker.cc index b0fa34099..d6e182be0 100644 --- a/srsenb/src/phy/nr/cc_worker.cc +++ b/srsenb/src/phy/nr/cc_worker.cc @@ -60,7 +60,7 @@ bool cc_worker::set_carrier(const srsran_carrier_nr_t* carrier) coreset.freq_resources[0] = true; // Enable the bottom 6 PRB for PDCCH coreset.duration = 2; - srsran_dci_cfg_nr_t dci_cfg = phy_state->cfg.get_dci_cfg(*carrier); + srsran_dci_cfg_nr_t dci_cfg = phy_state->cfg.get_dci_cfg(); if (srsran_enb_dl_nr_set_pdcch_config(&enb_dl, &phy_state->cfg.pdcch, &dci_cfg) < SRSRAN_SUCCESS) { ERROR("Error setting coreset"); return false; diff --git a/srsue/hdr/phy/nr/cc_worker.h b/srsue/hdr/phy/nr/cc_worker.h index c75f60d9a..9ea44588e 100644 --- a/srsue/hdr/phy/nr/cc_worker.h +++ b/srsue/hdr/phy/nr/cc_worker.h @@ -25,7 +25,6 @@ public: cc_worker(uint32_t cc_idx, srslog::basic_logger& log, state* phy_state_); ~cc_worker(); - bool set_carrier(const srsran_carrier_nr_t* carrier); bool update_cfg(); void set_tti(uint32_t tti); diff --git a/srsue/hdr/phy/nr/sf_worker.h b/srsue/hdr/phy/nr/sf_worker.h index 20782b83e..61eee0535 100644 --- a/srsue/hdr/phy/nr/sf_worker.h +++ b/srsue/hdr/phy/nr/sf_worker.h @@ -34,7 +34,6 @@ public: sf_worker(phy_common* phy, state* phy_state_, srslog::basic_logger& logger); ~sf_worker() = default; - bool set_carrier_unlocked(uint32_t cc_idx, const srsran_carrier_nr_t* carrier_); bool update_cfg(uint32_t cc_idx); /* Functions used by main PHY thread */ diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index 4c90767b1..12bfb01fd 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -48,6 +48,7 @@ private: srsran::circular_array pending_ack = {}; mutable std::mutex pending_ack_mutex; + /// Metrics section info_metrics_t info_metrics = {}; sync_metrics_t sync_metrics = {}; ch_metrics_t ch_metrics = {}; @@ -70,8 +71,7 @@ private: } public: - mac_interface_phy_nr* stack = nullptr; - srsran_carrier_nr_t carrier = {}; + mac_interface_phy_nr* stack = nullptr; /// Physical layer user configuration phy_args_nr_t args = {}; @@ -86,12 +86,6 @@ public: state() { - carrier.pci = 500; - carrier.nof_prb = 100; - carrier.max_mimo_layers = 1; - - info_metrics.pci = carrier.pci; - // Hard-coded values, this should be set when the measurements take place csi_measurements[0].K_csi_rs = 1; csi_measurements[0].nof_ports = 1; @@ -108,7 +102,7 @@ public: { // Convert UL DCI to grant srsran_sch_cfg_nr_t pusch_cfg = {}; - if (srsran_ra_ul_dci_to_grant_nr(&carrier, &cfg.pusch, &dci_ul, &pusch_cfg, &pusch_cfg.grant)) { + if (srsran_ra_ul_dci_to_grant_nr(&cfg.carrier, &cfg.pusch, &dci_ul, &pusch_cfg, &pusch_cfg.grant)) { std::array str; srsran_dci_ul_nr_to_str(&dci_ul, str.data(), str.size()); ERROR("Computing UL grant %s", str.data()); @@ -167,7 +161,7 @@ public: { // Convert DL DCI to grant srsran_sch_cfg_nr_t pdsch_cfg = {}; - if (srsran_ra_dl_dci_to_grant_nr(&carrier, &slot, &cfg.pdsch, &dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) { + if (srsran_ra_dl_dci_to_grant_nr(&cfg.carrier, &slot, &cfg.pdsch, &dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) { ERROR("Computing UL grant"); return; } diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 6b1f3d68e..585c5ca10 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -119,7 +119,7 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("rat.nr.dl_arfcn", bpo::value(&args->phy.dl_nr_arfcn)->default_value("634240"), "Downlink NR-ARFCN list") ("rat.nr.dl_freq", bpo::value(&args->phy.nr_freq_hz)->default_value(3513.6e6), "NR DL frequency") ("rat.nr.nof_carriers", bpo::value(&args->phy.nof_nr_carriers)->default_value(0), "Number of NR carriers") - ("rat.nr.nof_prb", bpo::value(&args->phy.nr_nof_prb)->default_value(52), "NR carrier bandwidth") + ("rat.nr.max_nof_prb", bpo::value(&args->phy.nr_max_nof_prb)->default_value(106), "Maximum NR carrier bandwidth in PRB") ("rrc.feature_group", bpo::value(&args->stack.rrc.feature_group)->default_value(0xe6041000), "Hex value of the featureGroupIndicators field in the" "UECapabilityInformation message. Default 0xe6041000") diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 164c7419e..1b5d25440 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -56,28 +56,19 @@ cc_worker::~cc_worker() } } -bool cc_worker::set_carrier(const srsran_carrier_nr_t* carrier) +bool cc_worker::update_cfg() { - if (srsran_ue_dl_nr_set_carrier(&ue_dl, carrier) < SRSRAN_SUCCESS) { + if (srsran_ue_dl_nr_set_carrier(&ue_dl, &phy->cfg.carrier) < SRSRAN_SUCCESS) { ERROR("Error setting carrier"); return false; } - if (srsran_ue_ul_nr_set_carrier(&ue_ul, carrier) < SRSRAN_SUCCESS) { + if (srsran_ue_ul_nr_set_carrier(&ue_ul, &phy->cfg.carrier) < SRSRAN_SUCCESS) { ERROR("Error setting carrier"); return false; } - // Set default PDSCH config - phy->cfg.pdsch.rbg_size_cfg_1 = false; - - return true; -} - -bool cc_worker::update_cfg() -{ - srsran_dci_cfg_nr_t dci_cfg = phy->cfg.get_dci_cfg(phy->carrier); - + srsran_dci_cfg_nr_t dci_cfg = phy->cfg.get_dci_cfg(); if (srsran_ue_dl_nr_set_pdcch_config(&ue_dl, &phy->cfg.pdcch, &dci_cfg) < SRSRAN_SUCCESS) { logger.error("Error setting NR PDCCH configuration"); return false; @@ -278,12 +269,8 @@ bool cc_worker::work_dl() str.data(), str_extra.data()); } else { - logger.info(pdsch_res.tb[0].payload, - pdsch_cfg.grant.tb[0].tbs / 8, - "PDSCH: cc=%d pid=%d %s", - cc_idx, - pid, - str.data()); + logger.info( + pdsch_res.tb[0].payload, pdsch_cfg.grant.tb[0].tbs / 8, "PDSCH: cc=%d pid=%d %s", cc_idx, pid, str.data()); } } @@ -391,7 +378,7 @@ bool cc_worker::work_ul() } // Set UCI configuration following procedures - srsran_ra_ul_set_grant_uci_nr(&phy->carrier, &phy->cfg.pusch, &uci_data.cfg, &pusch_cfg); + srsran_ra_ul_set_grant_uci_nr(&phy->cfg.carrier, &phy->cfg.pusch, &uci_data.cfg, &pusch_cfg); // Assigning MAC provided values to PUSCH config structs pusch_cfg.grant.tb[0].softbuffer.tx = ul_action.tb.softbuffer; diff --git a/srsue/src/phy/nr/sf_worker.cc b/srsue/src/phy/nr/sf_worker.cc index cf6ace0e1..a9e004276 100644 --- a/srsue/src/phy/nr/sf_worker.cc +++ b/srsue/src/phy/nr/sf_worker.cc @@ -36,15 +36,6 @@ sf_worker::sf_worker(phy_common* phy_, state* phy_state_, srslog::basic_logger& } } -bool sf_worker::set_carrier_unlocked(uint32_t cc_idx, const srsran_carrier_nr_t* carrier_) -{ - if (cc_idx >= cc_workers.size()) { - return false; - } - - return cc_workers.at(cc_idx)->set_carrier(carrier_); -} - bool sf_worker::update_cfg(uint32_t cc_idx) { if (cc_idx >= cc_workers.size()) { @@ -99,7 +90,7 @@ void sf_worker::work_imp() // Notify MAC about PRACH transmission phy_state->stack->prach_sent(TTI_TX(tti_rx), srsran_prach_nr_start_symbol_fr1_unpaired(phy_state->cfg.prach.config_idx), - SRSRAN_SLOT_NR_MOD(phy_state->carrier.scs, TTI_TX(tti_rx)), + SRSRAN_SLOT_NR_MOD(phy_state->cfg.carrier.scs, TTI_TX(tti_rx)), 0, 0); diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index 31f10a20b..e5865c671 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -22,12 +22,15 @@ bool worker_pool::init(const phy_args_nr_t& args, phy_common* common, stack_inte phy_state.args = args; // Set carrier attributes - phy_state.carrier.pci = 500; - phy_state.carrier.nof_prb = args.nof_prb; + phy_state.cfg.carrier.pci = 500; + phy_state.cfg.carrier.nof_prb = args.max_nof_prb; // Set NR arguments - phy_state.args.nof_carriers = args.nof_carriers; - phy_state.args.dl.nof_max_prb = args.nof_prb; + phy_state.args.nof_carriers = args.nof_carriers; + phy_state.args.dl.nof_max_prb = args.max_nof_prb; + phy_state.args.dl.pdsch.max_prb = args.max_nof_prb; + phy_state.args.ul.nof_max_prb = args.max_nof_prb; + phy_state.args.ul.pusch.max_prb = args.max_nof_prb; // Skip init of workers if no NR carriers if (phy_state.args.nof_carriers == 0) { @@ -43,10 +46,6 @@ bool worker_pool::init(const phy_args_nr_t& args, phy_common* common, stack_inte auto w = new sf_worker(common, &phy_state, log); pool.init_worker(i, w, prio, args.worker_cpu_mask); workers.push_back(std::unique_ptr(w)); - - if (not w->set_carrier_unlocked(0, &phy_state.carrier)) { - return false; - } } // Set PHY loglevel @@ -74,7 +73,7 @@ sf_worker* worker_pool::wait_worker(uint32_t tti) sf_worker* worker = (sf_worker*)pool.wait_worker(tti); // Generate PRACH if ready - if (prach_buffer->is_ready_to_send(tti, phy_state.carrier.pci)) { + if (prach_buffer->is_ready_to_send(tti, phy_state.cfg.carrier.pci)) { uint32_t nof_prach_sf = 0; float prach_target_power = 0.0f; cf_t* prach_ptr = prach_buffer->generate(0.0f, &nof_prach_sf, &prach_target_power); @@ -128,12 +127,14 @@ bool worker_pool::set_config(const srsran::phy_cfg_nr_t& cfg) { phy_state.cfg = cfg; - // Set PRACH hard-coded cell + logger.error( + "Setting new PHY configuration ARFCN=%d, PCI=%d", cfg.carrier.absolute_frequency_point_a, cfg.carrier.pci); + + // Best effort to convert NR carrier into LTE cell srsran_cell_t cell = {}; - cell.nof_prb = 50; - cell.id = phy_state.carrier.pci; - if (not prach_buffer->set_cell(cell, phy_state.cfg.prach)) { - logger.error("Error setting PRACH cell"); + int ret = srsran_carrier_to_cell(&phy_state.cfg.carrier, &cell); + if (ret < SRSRAN_SUCCESS) { + logger.error("Converting carrier to cell for PRACH (%d)", ret); return false; } @@ -144,6 +145,21 @@ bool worker_pool::set_config(const srsran::phy_cfg_nr_t& cfg) } } + // Best effort to set up NR-PRACH config reused for NR + srsran_prach_cfg_t prach_cfg = cfg.prach; + uint32_t lte_nr_prach_offset = (phy_state.cfg.carrier.nof_prb - cell.nof_prb) / 2; + if (prach_cfg.freq_offset < lte_nr_prach_offset) { + logger.error("prach_cfg.freq_offset=%d is not compatible with LTE", prach_cfg.freq_offset); + return false; + } + prach_cfg.freq_offset -= lte_nr_prach_offset; + + // Set the PRACH configuration + if (not prach_buffer->set_cell(cell, prach_cfg)) { + logger.error("Error setting PRACH cell"); + return false; + } + return true; } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 19b15d55a..0197d04a7 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -93,7 +93,7 @@ int ue::init(const all_args_t& args_) } srsue::phy_args_nr_t phy_args_nr = {}; - phy_args_nr.nof_prb = args.phy.nr_nof_prb; + phy_args_nr.max_nof_prb = args.phy.nr_max_nof_prb; phy_args_nr.nof_carriers = args.phy.nof_nr_carriers; phy_args_nr.nof_phy_threads = args.phy.nof_phy_threads; phy_args_nr.worker_cpu_mask = args.phy.worker_cpu_mask; @@ -209,8 +209,8 @@ int ue::parse_args(const all_args_t& args_) } // replicate some RF parameter to make them available to PHY - args.phy.nof_rx_ant = args.rf.nof_antennas; - args.phy.agc_enable = args.rf.rx_gain < 0.0f; + args.phy.nof_rx_ant = args.rf.nof_antennas; + args.phy.agc_enable = args.rf.rx_gain < 0.0f; // populate DL EARFCN list if (not args.phy.dl_earfcn.empty()) {