From 0b06d55f5fb7c38ff1c53c56a0d511162a722ae4 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 18 Jul 2025 11:47:02 +0000 Subject: [PATCH] NR UE: introduce support to define multiple cells This feature shall allow in future to simulate an arbitratry number of UEs connected to an other arbitrary number of cells. Therefore each RF-frontend (also called RU) needs to be configured for one specific cell. In case of handover of a UE from one cell to another cell, it needs to switch RUs accordingly (TODO). There has to be a 1-to-1 mapping between RUs and cells. Each UE will be assigned to one of the defined cells. Initially all UEs are assigned to cell 0. --- ci-scripts/conf_files/nrue.uicc.ntn-leo.conf | 12 ++ executables/nr-ue-ru.c | 137 ++++++++++++++++++- executables/nr-ue-ru.h | 9 +- executables/nr-uesoftmodem.c | 97 +++++++++---- openair1/PHY/INIT/nr_parms.c | 11 +- openair1/PHY/INIT/nr_phy_init.h | 2 +- openair1/PHY/defs_nr_UE.h | 12 ++ 7 files changed, 247 insertions(+), 33 deletions(-) diff --git a/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf index 9f2787f2d8..96c56e4f80 100644 --- a/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf +++ b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf @@ -29,6 +29,18 @@ RUs = ( } ); +cells = ( + { + ru_id = 0; + band = 254; + rf_freq = 2488400000L; + rf_offset = -873500000L; + numerology = 0; + N_RB_DL = 25; + ssb_start = 60; + } +); + #/* configuration for channel modelisation */ #/* To be included in main config file when */ #/* channel modelisation is used (rfsimulator with chanmod options enabled) */ diff --git a/executables/nr-ue-ru.c b/executables/nr-ue-ru.c index 497bbc309b..c4dcfdf888 100644 --- a/executables/nr-ue-ru.c +++ b/executables/nr-ue-ru.c @@ -68,12 +68,116 @@ } // clang-format on +/* NR UE cell configuration section name */ +#define CONFIG_STRING_NRUE_CELL_LIST "cells" + +#define NRUE_CELL_RU_ID "ru_id" +#define NRUE_CELL_BAND "band" +#define NRUE_CELL_RF_FREQUENCY "rf_freq" +#define NRUE_CELL_RF_FREQ_OFFSET "rf_offset" +#define NRUE_CELL_NUMEROLOGY "numerology" +#define NRUE_CELL_N_RB_DL "N_RB_DL" +#define NRUE_CELL_SSB_START "ssb_start" + +/*------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* NR UE cell configuration parameters */ +/* optname helpstr paramflags XXXptr defXXXval type numelt chkPptr */ +/*------------------------------------------------------------------------------------------------------------------------------------------------*/ +// clang-format off +#define NRUE_CELL_PARAMS_DESC { \ + {NRUE_CELL_RU_ID, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, NULL }, \ + {NRUE_CELL_BAND, CONFIG_HLP_BAND, 0, .iptr=NULL, .defintval=78, TYPE_INT, 0, NULL }, \ + {NRUE_CELL_RF_FREQUENCY, CONFIG_HLP_DLF, 0, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0, NULL }, \ + {NRUE_CELL_RF_FREQ_OFFSET, CONFIG_HLP_ULF, 0, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0, NULL }, \ + {NRUE_CELL_NUMEROLOGY, CONFIG_HLP_NUMEROLOGY, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0, NULL }, \ + {NRUE_CELL_N_RB_DL, CONFIG_HLP_PRB_SA, 0, .iptr=NULL, .defintval=106, TYPE_INT, 0, NULL }, \ + {NRUE_CELL_SSB_START, CONFIG_HLP_SSC, 0, .iptr=NULL, .defintval=516, TYPE_INT, 0, NULL }, \ +} +// clang-format on + +static int nrue_cell_count; +static nrUE_cell_params_t *nrue_cells; +static NR_DL_FRAME_PARMS *nrue_cell_fp; + static int nrue_ru_count; static nrUE_RU_params_t *nrue_rus; openair0_config_t openair0_cfg[MAX_CARDS]; openair0_device_t openair0_dev[MAX_CARDS]; +int nrue_get_cell_count(void) +{ + return nrue_cell_count; +} + +const nrUE_cell_params_t *nrue_get_cell(int cell_id) +{ + AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count); + return &nrue_cells[cell_id]; +} + +NR_DL_FRAME_PARMS *nrue_get_cell_fp(int cell_id) +{ + AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count); + return &nrue_cell_fp[cell_id]; +} + +void nrue_set_cell(int cell_id, const nrUE_cell_params_t *cell) +{ + AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count); + nrue_cells[cell_id] = *cell; +} + +void nrue_set_cell_params(configmodule_interface_t *cfg) +{ + paramdef_t cellParams[] = NRUE_CELL_PARAMS_DESC; + paramlist_def_t cellParamList = {CONFIG_STRING_NRUE_CELL_LIST, NULL, 0}; + config_getlist(cfg, &cellParamList, cellParams, sizeofArray(cellParams), NULL); + + if (cellParamList.numelt <= 0) { + nrue_cell_count = 1; + nrue_cell_fp = calloc_or_fail(nrue_cell_count, sizeof(NR_DL_FRAME_PARMS)); + nrue_cells = calloc_or_fail(nrue_cell_count, sizeof(nrUE_cell_params_t)); + nrue_cells[0] = (nrUE_cell_params_t){.ru_id = 0, + .band = get_softmodem_params()->band, + .rf_frequency = downlink_frequency[0][0], + .rf_freq_offset = uplink_frequency_offset[0][0], + .numerology = get_softmodem_params()->numerology, + .N_RB_DL = get_nrUE_params()->N_RB_DL, + .ssb_start = get_nrUE_params()->ssb_start_subcarrier, + .used_by_ue = -1}; + return; + } + + nrue_cell_count = cellParamList.numelt; + nrue_cell_fp = calloc_or_fail(nrue_cell_count, sizeof(NR_DL_FRAME_PARMS)); + nrue_cells = calloc_or_fail(nrue_cell_count, sizeof(nrUE_cell_params_t)); + + LOG_W(NR_PHY, "Ignoring command line cell parameters, using the following instead:\n"); + + for (int cell_id = 0; cell_id < nrue_cell_count; cell_id++) { + nrue_cells[cell_id].ru_id = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_RU_ID)->iptr); + nrue_cells[cell_id].band = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_BAND)->iptr); + nrue_cells[cell_id].rf_frequency = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_RF_FREQUENCY)->u64ptr); + nrue_cells[cell_id].rf_freq_offset = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_RF_FREQ_OFFSET)->i64ptr); + nrue_cells[cell_id].numerology = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_NUMEROLOGY)->iptr); + nrue_cells[cell_id].N_RB_DL = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_N_RB_DL)->iptr); + nrue_cells[cell_id].ssb_start = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_SSB_START)->iptr); + nrue_cells[cell_id].used_by_ue = -1; + + LOG_I(NR_PHY, + "cell %d: ru_id %d, band %d, DL freq %lu, UL freq_offset %ld, numerology %d, N_RB_DL %d, ssb_start %d\n", + cell_id, + nrue_cells[cell_id].ru_id, + nrue_cells[cell_id].band, + nrue_cells[cell_id].rf_frequency, + nrue_cells[cell_id].rf_freq_offset, + nrue_cells[cell_id].numerology, + nrue_cells[cell_id].N_RB_DL, + nrue_cells[cell_id].ssb_start); + } +} + int nrue_get_ru_count(void) { return nrue_ru_count; @@ -85,6 +189,13 @@ const nrUE_RU_params_t *nrue_get_ru(int ru_id) return &nrue_rus[ru_id]; } +void nrue_set_ru_cell_id(int ru_id, int cell_id) +{ + AssertFatal(ru_id >= 0 && ru_id < nrue_ru_count, "Invalid RU ID %d! RU count = %d\n", ru_id, nrue_ru_count); + AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count); + nrue_rus[ru_id].used_by_cell = cell_id; +} + void nrue_set_ru_params(configmodule_interface_t *cfg) { paramdef_t RUParams[] = NRUE_RU_PARAMS_DESC; @@ -106,7 +217,8 @@ void nrue_set_ru_params(configmodule_interface_t *cfg) .time_source = get_softmodem_params()->timing_source, .tune_offset = get_softmodem_params()->tune_offset, .if_frequency = get_nrUE_params()->if_freq, - .if_freq_offset = get_nrUE_params()->if_freq_off}; + .if_freq_offset = get_nrUE_params()->if_freq_off, + .used_by_cell = -1}; return; } @@ -124,6 +236,7 @@ void nrue_set_ru_params(configmodule_interface_t *cfg) nrue_rus[ru_id].tune_offset = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_TUNE_OFFSET)->dblptr); nrue_rus[ru_id].if_frequency = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_IF_FREQUENCY)->u64ptr); nrue_rus[ru_id].if_freq_offset = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_IF_FREQ_OFFSET)->iptr); + nrue_rus[ru_id].used_by_cell = -1; nrue_rus[ru_id].sdr_addrs = strdup(*(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_SDR_ADDRS)->strptr)); nrue_rus[ru_id].tx_subdev = strdup(*(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_TX_SUBDEV)->strptr)); @@ -157,7 +270,7 @@ void nrue_set_ru_params(configmodule_interface_t *cfg) } } -void nrue_init_openair0(const PHY_VARS_NR_UE *ue) +void nrue_init_openair0(void) { int freq_off = 0; bool is_sidelink = (get_softmodem_params()->sl_mode) ? true : false; @@ -170,11 +283,23 @@ void nrue_init_openair0(const PHY_VARS_NR_UE *ue) nrue_ru_count, MAX_CARDS); - const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - if (is_sidelink) - frame_parms = &ue->SL_UE_PHY_PARAMS.sl_frame_params; - for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) { + int cell_id = nrue_rus[ru_id].used_by_cell; + if (cell_id < 0) { + LOG_W(PHY, "Skipping initialization of RU %d because it is not used by any cell!\n", ru_id); + continue; + } + NR_DL_FRAME_PARMS *frame_parms = &nrue_cell_fp[cell_id]; + if (is_sidelink) { + int UE_id = nrue_cells[cell_id].used_by_ue; + if (UE_id < 0) { + LOG_W(PHY, "Skipping initialization of RU %d because it is not used by any UE!\n", ru_id); + continue; + } + extern PHY_VARS_NR_UE ***PHY_vars_UE_g; + frame_parms = &PHY_vars_UE_g[UE_id][0]->SL_UE_PHY_PARAMS.sl_frame_params; + } + openair0_config_t *cfg = &openair0_cfg[ru_id]; cfg->configFilename = NULL; cfg->sample_rate = frame_parms->samples_per_subframe * 1e3; diff --git a/executables/nr-ue-ru.h b/executables/nr-ue-ru.h index 4f5aee107a..91b86d487b 100644 --- a/executables/nr-ue-ru.h +++ b/executables/nr-ue-ru.h @@ -25,11 +25,18 @@ #include "PHY/defs_nr_UE.h" #include "radio/COMMON/common_lib.h" +int nrue_get_cell_count(void); +const nrUE_cell_params_t *nrue_get_cell(int cell_id); +NR_DL_FRAME_PARMS *nrue_get_cell_fp(int cell_id); +void nrue_set_cell(int cell_id, const nrUE_cell_params_t *cell); +void nrue_set_cell_params(configmodule_interface_t *cfg); + int nrue_get_ru_count(void); const nrUE_RU_params_t *nrue_get_ru(int ru_id); +void nrue_set_ru_cell_id(int ru_id, int cell_id); void nrue_set_ru_params(configmodule_interface_t *cfg); -void nrue_init_openair0(const PHY_VARS_NR_UE *ue); +void nrue_init_openair0(void); void nrue_ru_start(void); void nrue_ru_end(void); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index b40901e435..71c0f8f996 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -175,9 +175,8 @@ static void get_options(configmodule_interface_t *cfg) } // set PHY vars from command line -static void set_options(int CC_id, PHY_VARS_NR_UE *UE, int ru_id) +static void set_UE_options(int CC_id, PHY_VARS_NR_UE *UE, int ru_id) { - NR_DL_FRAME_PARMS *fp = &UE->frame_parms; const nrUE_RU_params_t *RU = nrue_get_ru(ru_id); // Set UE variables @@ -200,6 +199,12 @@ static void set_options(int CC_id, PHY_VARS_NR_UE *UE, int ru_id) LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n", UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time); +} + +static void set_fp_options(int cell_id, int ru_id) +{ + NR_DL_FRAME_PARMS *fp = nrue_get_cell_fp(cell_id); + const nrUE_RU_params_t *RU = nrue_get_ru(ru_id); // Set FP variables fp->nb_antennas_rx = RU->nb_rx; @@ -307,7 +312,14 @@ int main(int argc, char **argv) nr_pdcp_layer_init(); nas_init_nrue(NB_UE_INST); - init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file, get_softmodem_params()->numerology); + nrue_set_ru_params(uniqCfg); + nrue_set_cell_params(uniqCfg); + + init_NR_UE(NB_UE_INST, + get_nrUE_params()->uecap_file, + get_nrUE_params()->reconfig_file, + get_nrUE_params()->rbconfig_file, + nrue_get_cell(0)->numerology); // start time manager with some reasonable default for the running mode // (may be overwritten in configuration file or command line) @@ -324,29 +336,52 @@ int main(int argc, char **argv) IS_SOFTMODEM_RFSIM ? TIME_SOURCE_IQ_SAMPLES : TIME_SOURCE_REALTIME); - nrue_set_ru_params(uniqCfg); + // initialize per-cell frame parameters + for (int cell_id = 0; cell_id < nrue_get_cell_count(); cell_id++) { + int ru_id = nrue_get_cell(cell_id)->ru_id; + AssertFatal(ru_id >= 0 && ru_id < nrue_get_ru_count(), + "Invalid ru_id (%d) for cell %d. Should be >= 0 and < %d\n", + ru_id, + cell_id, + nrue_get_ru_count()); + AssertFatal(nrue_get_ru(ru_id)->used_by_cell == -1, + "RU %d is already used by cell %d and therefore cannot also be used by cell %d\n", + ru_id, + nrue_get_ru(ru_id)->used_by_cell, + cell_id); + nrue_set_ru_cell_id(ru_id, cell_id); - int ru_id = 0; // initialize all UEs to RU 0 for now + set_fp_options(cell_id, ru_id); + if (IS_SA_MODE(get_softmodem_params()) || get_softmodem_params()->sl_mode) + nr_init_frame_parms_ue_sa(nrue_get_cell_fp(cell_id), nrue_get_cell(cell_id)); + } + + int cell_id = 0; for (int inst = 0; inst < NB_UE_INST; inst++) { + NR_UE_MAC_INST_t *mac = get_mac_inst(inst); + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { PHY_VARS_NR_UE *UE_CC = PHY_vars_UE_g[inst][CC_id]; - set_options(CC_id, UE_CC, ru_id); - NR_UE_MAC_INST_t *mac = get_mac_inst(inst); + + AssertFatal(cell_id >= 0 && cell_id < nrue_get_cell_count(), + "There are not enough cell definitions for all UEs! NB_UE_INST = %d, MAX_NUM_CCs = %d, nrue_cell_count = %d\n", + NB_UE_INST, + MAX_NUM_CCs, + nrue_get_cell_count()); + nrUE_cell_params_t cell = *nrue_get_cell(cell_id); + + AssertFatal(cell.used_by_ue == -1, + "Cell %d is already used by UE %d and cannot also be used by UE %d as cells map 1:1 to RUs and RU sharing is not implemented\n", + cell_id, + cell.used_by_ue, + inst); + cell.used_by_ue = inst; + + set_UE_options(CC_id, UE_CC, cell.ru_id); init_nr_ue_phy_cpu_stats(&UE_CC->phy_cpu_stats); - // set frame config to initial values from command line and assume that the SSB is centered on the grid - if (IS_SA_MODE(get_softmodem_params()) || get_softmodem_params()->sl_mode) { - uint16_t nr_band = get_softmodem_params()->band; - mac->nr_band = nr_band; - mac->ssb_start_subcarrier = UE_CC->frame_parms.ssb_start_subcarrier; - mac->dl_frequency = downlink_frequency[CC_id][0]; - nr_init_frame_parms_ue_sa(&UE_CC->frame_parms, - downlink_frequency[CC_id][0], - uplink_frequency_offset[CC_id][0], - get_softmodem_params()->numerology, - nrUE_params.N_RB_DL, - nrUE_params.ssb_start_subcarrier, - nr_band); - } else { + + NR_DL_FRAME_PARMS *fp = nrue_get_cell_fp(cell_id); + if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) { do { notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&mac->input_nf); if (!elt) { @@ -356,8 +391,21 @@ int main(int argc, char **argv) delNotifiedFIFO_elt(elt); } while (true); fapi_nr_config_request_t *nrUE_config = &UE_CC->nrUE_config; - nr_init_frame_parms_ue(&UE_CC->frame_parms, nrUE_config, mac->nr_band); + nr_init_frame_parms_ue(fp, nrUE_config, mac->nr_band); + + cell.band = fp->nr_band; + cell.rf_frequency = fp->dl_CarrierFreq; + cell.rf_freq_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; + cell.numerology = fp->numerology_index; + cell.N_RB_DL = fp->N_RB_DL; + cell.ssb_start = fp->ssb_start_subcarrier; } + nrue_set_cell(cell_id, &cell); + + UE_CC->frame_parms = *fp; + mac->nr_band = cell.band; + mac->ssb_start_subcarrier = cell.ssb_start; + mac->dl_frequency = cell.rf_frequency; UE_CC->sl_mode = get_softmodem_params()->sl_mode; init_actor(&UE_CC->sync_actor, "SYNC_", -1); @@ -389,10 +437,13 @@ int main(int argc, char **argv) get_nrUE_params()->ofdm_offset_divisor); sl_ue_phy_init(UE_CC); } - nrue_init_openair0(UE_CC); + + cell_id++; // initially connect each UE and carrier to its own cell } } + nrue_init_openair0(); + lock_memory_to_ram(); if (IS_SOFTMODEM_DOSCOPE) { diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index f50b5ab728..d6043775af 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -525,9 +525,16 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, return 0; } -void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t delta_duplex, uint8_t mu, int N_RB_DL, int ssb_start_subcarrier, uint16_t nr_band) +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, const nrUE_cell_params_t *cell) { - LOG_I(PHY,"SA init parameters. DL freq %lu UL offset %d SSB numerology %d N_RB_DL %d\n", + const uint64_t downlink_frequency = cell->rf_frequency; + const int64_t delta_duplex = cell->rf_freq_offset; + const uint8_t mu = cell->numerology; + const int N_RB_DL = cell->N_RB_DL; + const int ssb_start_subcarrier = cell->ssb_start; + const uint16_t nr_band = cell->band; + + LOG_I(PHY,"SA init parameters. DL freq %lu UL offset %ld SSB numerology %d N_RB_DL %d\n", downlink_frequency, delta_duplex, mu, diff --git a/openair1/PHY/INIT/nr_phy_init.h b/openair1/PHY/INIT/nr_phy_init.h index af44571a7b..ec4a8de71b 100644 --- a/openair1/PHY/INIT/nr_phy_init.h +++ b/openair1/PHY/INIT/nr_phy_init.h @@ -28,7 +28,7 @@ int nr_get_ssb_start_symbol(const NR_DL_FRAME_PARMS *fp, uint8_t i_ssb); void nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band); -void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t delta_duplex, uint8_t mu, int N_RB_DL, int ssb_start_subcarrier, uint16_t nr_band); +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, const nrUE_cell_params_t *cell); int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, sl_nr_phy_config_request_t *config, int threequarter_fs, diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 2eba24f6d1..8d2dcbd58d 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -356,8 +356,20 @@ typedef struct { double tune_offset; uint64_t if_frequency; int if_freq_offset; + int used_by_cell; } nrUE_RU_params_t; +typedef struct { + int ru_id; + int band; + uint64_t rf_frequency; + int64_t rf_freq_offset; + int numerology; + int N_RB_DL; + int ssb_start; + int used_by_ue; +} nrUE_cell_params_t; + /// Top-level PHY Data Structure for UE typedef struct PHY_VARS_NR_UE_s { /// \brief Module ID indicator for this instance