From b501f2eeafc18109767c80c68892dbf17765e254 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 23 Nov 2020 09:43:12 +0100 Subject: [PATCH] SRSENB/UE: Added NR workers --- lib/include/srslte/interfaces/ue_interfaces.h | 1 + lib/include/srslte/phy/enb/enb_dl_nr.h | 6 +++ lib/src/phy/enb/enb_dl_nr.c | 16 +++++- srsenb/hdr/phy/nr/cc_worker.h | 16 +++--- srsenb/hdr/phy/phy.h | 7 +-- srsenb/hdr/phy/phy_common.h | 14 +++--- srsenb/hdr/phy/phy_interfaces.h | 6 +-- srsenb/hdr/phy/txrx.h | 3 +- srsenb/hdr/stack/rrc/rrc_config.h | 1 + srsenb/src/enb_cfg_parser.cc | 50 +++++++++++++++++-- srsenb/src/phy/lte/cc_worker.cc | 4 +- srsenb/src/phy/lte/sf_worker.cc | 10 ++-- srsenb/src/phy/nr/cc_worker.cc | 36 +++++++++---- srsenb/src/phy/nr/sf_worker.cc | 15 +++++- srsenb/src/phy/nr/worker_pool.cc | 13 +++-- srsenb/src/phy/phy.cc | 8 ++- srsenb/src/phy/phy_common.cc | 24 +++++++-- srsenb/src/phy/txrx.cc | 12 ++++- srsue/src/main.cc | 1 + srsue/src/phy/nr/cc_worker.cc | 2 +- srsue/src/phy/sync.cc | 5 ++ 21 files changed, 191 insertions(+), 59 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 42f5f8b78..6e1bf4190 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -489,6 +489,7 @@ typedef struct { uint32_t nof_lte_carriers = 1; uint32_t nof_nr_carriers = 0; uint32_t nr_nof_prb = 50; + double nr_freq_hz = 2630e6; uint32_t nof_rx_ant = 1; std::string equalizer_mode = "mmse"; int cqi_max = 15; diff --git a/lib/include/srslte/phy/enb/enb_dl_nr.h b/lib/include/srslte/phy/enb/enb_dl_nr.h index a203ca075..44e7ad276 100644 --- a/lib/include/srslte/phy/enb/enb_dl_nr.h +++ b/lib/include/srslte/phy/enb/enb_dl_nr.h @@ -53,6 +53,12 @@ SRSLTE_API int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q, const srslte_pdsch_grant_nr_t* grant, uint8_t* data[SRSLTE_MAX_TB]); +SRSLTE_API int srslte_enb_dl_nr_pdsch_info(const srslte_enb_dl_nr_t* q, + const srslte_pdsch_cfg_nr_t* cfg, + const srslte_pdsch_grant_nr_t* grant, + char* str, + uint32_t str_len); + #ifdef __cplusplus } #endif diff --git a/lib/src/phy/enb/enb_dl_nr.c b/lib/src/phy/enb/enb_dl_nr.c index 5558cceaa..cc1d7361a 100644 --- a/lib/src/phy/enb/enb_dl_nr.c +++ b/lib/src/phy/enb/enb_dl_nr.c @@ -148,4 +148,18 @@ int srslte_enb_dl_nr_pdsch_put(srslte_enb_dl_nr_t* q, } return SRSLTE_SUCCESS; -} \ No newline at end of file +} + +int srslte_enb_dl_nr_pdsch_info(const srslte_enb_dl_nr_t* q, + const srslte_pdsch_cfg_nr_t* cfg, + const srslte_pdsch_grant_nr_t* grant, + char* str, + uint32_t str_len) +{ + int len = 0; + + // Append PDSCH info + len += srslte_pdsch_nr_tx_info(&q->pdsch, cfg, grant, &str[len], str_len - len); + + return len; +} diff --git a/srsenb/hdr/phy/nr/cc_worker.h b/srsenb/hdr/phy/nr/cc_worker.h index b70168229..83feb2a7b 100644 --- a/srsenb/hdr/phy/nr/cc_worker.h +++ b/srsenb/hdr/phy/nr/cc_worker.h @@ -49,9 +49,10 @@ public: phy_nr_state() { args.nof_carriers = 1; - args.max_prb = SRSLTE_MAX_PRB; + args.max_prb = 100; args.dl.nof_tx_antennas = 1; args.dl.pdsch.measure_evm = true; + args.dl.pdsch.measure_time = true; args.dl.pdsch.sch.disable_simd = true; } }; @@ -72,12 +73,13 @@ public: bool work_dl(); private: - srslte_dl_slot_cfg_t dl_slot_cfg = {}; - uint32_t cc_idx = 0; - std::array, SRSLTE_MAX_PORTS> tx_buffer = {}; - std::array, SRSLTE_MAX_PORTS> rx_buffer = {}; - phy_nr_state* phy_state; - srslte_enb_dl_nr_t enb_dl = {}; + srslte_dl_slot_cfg_t dl_slot_cfg = {}; + uint32_t cc_idx = 0; + std::array tx_buffer = {}; + std::array rx_buffer = {}; + phy_nr_state* phy_state; + srslte_enb_dl_nr_t enb_dl = {}; + srslte::log* log_h = nullptr; // Temporal attributes srslte_softbuffer_tx_t softbuffer_tx = {}; diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index 12e6fefbe..3338057b5 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -76,11 +76,12 @@ private: srslte::radio_interface_phy* radio = nullptr; - srslte::logger* logger = nullptr; - std::unique_ptr log_h = nullptr; - std::unique_ptr log_phy_lib_h = nullptr; + srslte::logger* logger = nullptr; + std::unique_ptr log_h = nullptr; + std::unique_ptr log_phy_lib_h = nullptr; lte::worker_pool lte_workers; + nr::worker_pool nr_workers; phy_common workers_common; prach_worker_pool prach; txrx tx_rx; diff --git a/srsenb/hdr/phy/phy_common.h b/srsenb/hdr/phy/phy_common.h index bfb4225ed..c287f669c 100644 --- a/srsenb/hdr/phy/phy_common.h +++ b/srsenb/hdr/phy/phy_common.h @@ -54,8 +54,9 @@ public: * @param tx_sem_id Semaphore identifier, the worker thread pointer is used * @param buffer baseband IQ sample buffer * @param tx_time timestamp to transmit samples + * @param is_nr flag is true if it is called from NR */ - void worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time); + void worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time, bool is_nr = false); // Common objects phy_args_t params = {}; @@ -92,7 +93,7 @@ public: } for (auto& cell : cell_list_nr) { - count += cell.cell.max_mimo_layers; + count += cell.carrier.max_mimo_layers; } return count; @@ -153,13 +154,8 @@ public: srslte_carrier_nr_t get_cell_nr(uint32_t cc_idx) { srslte_carrier_nr_t c = {}; - if (cc_idx < cell_list_lte.size()) { - return c; - } - - cc_idx -= cell_list_lte.size(); if (cc_idx < cell_list_nr.size()) { - c = cell_list_nr[cc_idx].cell; + c = cell_list_nr[cc_idx].carrier; } return c; @@ -246,6 +242,8 @@ private: uint32_t mch_period_stop = 0; bool is_mch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti); bool is_mcch_subframe(srslte_mbsfn_cfg_t* cfg, uint32_t phy_tti); + srslte::rf_buffer_t nr_tx_buffer; + bool nr_tx_buffer_ready = false; }; } // namespace srsenb diff --git a/srsenb/hdr/phy/phy_interfaces.h b/srsenb/hdr/phy/phy_interfaces.h index 5049f2831..7d2d5e343 100644 --- a/srsenb/hdr/phy/phy_interfaces.h +++ b/srsenb/hdr/phy/phy_interfaces.h @@ -34,7 +34,7 @@ struct phy_cell_cfg_t { }; struct phy_cell_cfg_nr_t { - srslte_carrier_nr_t cell; + srslte_carrier_nr_t carrier; uint32_t rf_port; uint32_t cell_id; double dl_freq_hz; @@ -44,7 +44,7 @@ struct phy_cell_cfg_nr_t { float gain_db; }; -typedef std::vector phy_cell_cfg_list_t; +typedef std::vector phy_cell_cfg_list_t; typedef std::vector phy_cell_cfg_list_nr_t; struct phy_args_t { @@ -71,7 +71,7 @@ struct phy_args_t { struct phy_cfg_t { // Individual cell/sector configuration list - phy_cell_cfg_list_t phy_cell_cfg; + phy_cell_cfg_list_t phy_cell_cfg; phy_cell_cfg_list_nr_t phy_cell_cfg_nr; // Common configuration for all cells diff --git a/srsenb/hdr/phy/txrx.h b/srsenb/hdr/phy/txrx.h index 76ea7eab9..d4749b22a 100644 --- a/srsenb/hdr/phy/txrx.h +++ b/srsenb/hdr/phy/txrx.h @@ -30,7 +30,8 @@ public: txrx(); bool init(stack_interface_phy_lte* stack_, srslte::radio_interface_phy* radio_handler, - lte::worker_pool* _workers_pool, + lte::worker_pool* lte_workers_, + nr::worker_pool* nr_workers_, phy_common* worker_com, prach_worker_pool* prach_, srslte::log* log_h, diff --git a/srsenb/hdr/stack/rrc/rrc_config.h b/srsenb/hdr/stack/rrc/rrc_config.h index a94b57fd9..e2834c830 100644 --- a/srsenb/hdr/stack/rrc/rrc_config.h +++ b/srsenb/hdr/stack/rrc/rrc_config.h @@ -59,6 +59,7 @@ struct rrc_cfg_t { bool meas_cfg_present = false; srslte_cell_t cell; cell_list_t cell_list; + cell_list_t cell_list_nr; }; constexpr uint32_t UE_PCELL_CC_IDX = 0; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 59e125cb9..8dbbbda5c 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -719,10 +719,9 @@ static int parse_scell_list(cell_cfg_t& cell_cfg, Setting& cellroot) static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) { - rrc_cfg->cell_list.resize(root.getLength()); - for (uint32_t n = 0; n < rrc_cfg->cell_list.size(); ++n) { - cell_cfg_t& cell_cfg = rrc_cfg->cell_list[n]; - auto& cellroot = root[n]; + for (uint32_t n = 0; n < (uint32_t)root.getLength(); ++n) { + cell_cfg_t cell_cfg = {}; + auto& cellroot = root[n]; parse_opt_field(cell_cfg.rf_port, cellroot, "rf_port"); HANDLEPARSERCODE(parse_required_field(cell_cfg.cell_id, cellroot, "cell_id")); @@ -744,6 +743,16 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) if (cellroot.exists("scell_list")) { parse_scell_list(cell_cfg, cellroot); } + + std::string type = "lte"; + if (cellroot.exists("type")) { + cellroot.lookupValue("type", type); + } + if (type == "lte") { + rrc_cfg->cell_list.push_back(cell_cfg); + } else if (type == "nr") { + rrc_cfg->cell_list_nr.push_back(cell_cfg); + } } // Configuration check @@ -961,6 +970,37 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ phy_cfg_->phy_cell_cfg.push_back(phy_cell_cfg); } + // Create NR dedicated cell configuration from RRC configuration + for (auto it = rrc_cfg_->cell_list_nr.begin(); it != rrc_cfg_->cell_list_nr.end(); ++it) { + auto& cfg = *it; + phy_cell_cfg_nr_t phy_cell_cfg = {}; + phy_cell_cfg.carrier.max_mimo_layers = cell_cfg_.nof_ports; + phy_cell_cfg.carrier.nof_prb = cell_cfg_.nof_prb; + phy_cell_cfg.carrier.id = cfg.pci; + phy_cell_cfg.cell_id = cfg.cell_id; + phy_cell_cfg.root_seq_idx = cfg.root_seq_idx; + phy_cell_cfg.rf_port = cfg.rf_port; + phy_cell_cfg.num_ra_preambles = + rrc_cfg_->sibs[1].sib2().rr_cfg_common.rach_cfg_common.preamb_info.nof_ra_preambs.to_number(); + + if (cfg.dl_freq_hz > 0) { + phy_cell_cfg.dl_freq_hz = cfg.dl_freq_hz; + } else { + phy_cell_cfg.dl_freq_hz = 1e6 * srslte_band_fd(cfg.dl_earfcn); + } + + if (cfg.ul_freq_hz > 0) { + phy_cell_cfg.ul_freq_hz = cfg.ul_freq_hz; + } else { + if (cfg.ul_earfcn == 0) { + cfg.ul_earfcn = srslte_band_ul_earfcn(cfg.dl_earfcn); + } + phy_cell_cfg.ul_freq_hz = 1e6 * srslte_band_fu(cfg.ul_earfcn); + } + + phy_cfg_->phy_cell_cfg_nr.push_back(phy_cell_cfg); + } + if (args_->enb.transmission_mode == 1) { phy_cfg_->pdsch_cnfg.p_b = 0; // Default TM1 rrc_cfg_->sibs[1].sib2().rr_cfg_common.pdsch_cfg_common.p_b = 0; @@ -1080,7 +1120,7 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ } // Patch certain args that are not exposed yet - args_->rf.nof_carriers = rrc_cfg_->cell_list.size(); + args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_cfg_->cell_list_nr.size(); args_->rf.nof_antennas = args_->enb.nof_ports; // MAC needs to know the cell bandwidth to dimension softbuffers diff --git a/srsenb/src/phy/lte/cc_worker.cc b/srsenb/src/phy/lte/cc_worker.cc index 982a649f7..b72197248 100644 --- a/srsenb/src/phy/lte/cc_worker.cc +++ b/srsenb/src/phy/lte/cc_worker.cc @@ -101,11 +101,11 @@ void cc_worker::init(phy_common* phy_, srslte::log* log_h_, uint32_t cc_idx_) srslte_vec_cf_zero(signal_buffer_tx[p], 2 * sf_len); } if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, nof_prb)) { - ERROR("Error initiating ENB DL\n"); + ERROR("Error initiating ENB DL (cc=%d)\n", cc_idx); return; } if (srslte_enb_dl_set_cell(&enb_dl, cell)) { - ERROR("Error initiating ENB DL\n"); + ERROR("Error initiating ENB DL (cc=%d)\n", cc_idx); return; } if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx[0], nof_prb)) { diff --git a/srsenb/src/phy/lte/sf_worker.cc b/srsenb/src/phy/lte/sf_worker.cc index 7c9810231..056f277b7 100644 --- a/srsenb/src/phy/lte/sf_worker.cc +++ b/srsenb/src/phy/lte/sf_worker.cc @@ -70,7 +70,7 @@ void sf_worker::init(phy_common* phy_, srslte::log* log_h_) log_h = log_h_; // Initialise each component carrier workers - for (uint32_t i = 0; i < phy->get_nof_carriers(); i++) { + for (uint32_t i = 0; i < phy->get_nof_carriers_lte(); i++) { // Create pointer auto q = new cc_worker(); @@ -164,7 +164,7 @@ void sf_worker::work_imp() // Get Transmission buffers srslte::rf_buffer_t tx_buffer = {}; - for (uint32_t cc = 0; cc < phy->get_nof_carriers(); cc++) { + for (uint32_t cc = 0; cc < phy->get_nof_carriers_lte(); cc++) { for (uint32_t ant = 0; ant < phy->get_nof_ports(0); ant++) { tx_buffer.set(cc, ant, phy->get_nof_ports(0), cc_workers[cc]->get_buffer_tx(ant)); } @@ -184,7 +184,7 @@ void sf_worker::work_imp() stack_interface_phy_lte::ul_sched_list_t ul_grants_tx = phy->get_ul_grants(t_tx_ul); // Downlink grants to transmit this TTI - stack_interface_phy_lte::dl_sched_list_t dl_grants(phy->get_nof_carriers()); + stack_interface_phy_lte::dl_sched_list_t dl_grants(phy->get_nof_carriers_lte()); stack_interface_phy_lte* stack = phy->stack; @@ -276,7 +276,7 @@ uint32_t sf_worker::get_metrics(std::vector& metrics) { uint32_t cnt = 0; std::vector metrics_; - for (uint32_t cc = 0; cc < phy->get_nof_carriers(); cc++) { + for (uint32_t cc = 0; cc < phy->get_nof_carriers_lte(); cc++) { cnt = cc_workers[cc]->get_metrics(metrics_); metrics.resize(std::max(metrics_.size(), metrics.size())); for (uint32_t r = 0; r < cnt; r++) { @@ -312,7 +312,7 @@ void sf_worker::start_plot() uint32_t sf_worker::get_nof_carriers() { - return phy->get_nof_carriers(); + return phy->get_nof_carriers_lte(); } int sf_worker::get_carrier_pci(uint32_t cc_idx) { diff --git a/srsenb/src/phy/nr/cc_worker.cc b/srsenb/src/phy/nr/cc_worker.cc index c2b33c5eb..4740131cd 100644 --- a/srsenb/src/phy/nr/cc_worker.cc +++ b/srsenb/src/phy/nr/cc_worker.cc @@ -27,15 +27,16 @@ namespace srsenb { namespace nr { cc_worker::cc_worker(uint32_t cc_idx_, srslte::log* log, phy_nr_state* phy_state_) : - cc_idx(cc_idx_), phy_state(phy_state_) + cc_idx(cc_idx_), phy_state(phy_state_), log_h(log) { cf_t* buffer_c[SRSLTE_MAX_PORTS] = {}; // Allocate buffers - for (uint32_t i = 0; phy_state_->args.dl.nof_tx_antennas; i++) { - tx_buffer[i].resize(SRSLTE_SF_LEN_PRB(phy_state->args.max_prb)); - rx_buffer[i].resize(SRSLTE_SF_LEN_PRB(phy_state->args.max_prb)); - buffer_c[i] = tx_buffer[i].data(); + uint32_t sf_len = SRSLTE_SF_LEN_PRB(phy_state->args.max_prb); + for (uint32_t i = 0; i < phy_state_->args.dl.nof_tx_antennas; i++) { + tx_buffer[i] = srslte_vec_cf_malloc(sf_len); + rx_buffer[i] = srslte_vec_cf_malloc(sf_len); + buffer_c[i] = tx_buffer[i]; } if (srslte_enb_dl_nr_init(&enb_dl, buffer_c, &phy_state_->args.dl)) { @@ -60,6 +61,16 @@ cc_worker::~cc_worker() { srslte_enb_dl_nr_free(&enb_dl); srslte_softbuffer_tx_free(&softbuffer_tx); + for (cf_t* p : rx_buffer) { + if (p != nullptr) { + free(p); + } + } + for (cf_t* p : tx_buffer) { + if (p != nullptr) { + free(p); + } + } } bool cc_worker::set_carrier(const srslte_carrier_nr_t* carrier) @@ -82,7 +93,7 @@ cf_t* cc_worker::get_tx_buffer(uint32_t antenna_idx) return nullptr; } - return tx_buffer.at(antenna_idx).data(); + return tx_buffer.at(antenna_idx); } cf_t* cc_worker::get_rx_buffer(uint32_t antenna_idx) @@ -91,7 +102,7 @@ cf_t* cc_worker::get_rx_buffer(uint32_t antenna_idx) return nullptr; } - return rx_buffer.at(antenna_idx).data(); + return rx_buffer.at(antenna_idx); } uint32_t cc_worker::get_buffer_len() @@ -103,7 +114,6 @@ bool cc_worker::work_dl() { srslte_pdsch_grant_nr_t pdsch_grant = {}; srslte_pdsch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch; - // Use grant default A time resources with m=0 if (srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) { @@ -112,12 +122,13 @@ bool cc_worker::work_dl() } pdsch_grant.nof_layers = enb_dl.carrier.max_mimo_layers; pdsch_grant.dci_format = srslte_dci_format_nr_1_0; + pdsch_grant.rnti = 0x1234; for (uint32_t i = 0; i < enb_dl.carrier.nof_prb; i++) { pdsch_grant.prb_idx[i] = true; } - if (srslte_ra_nr_fill_tb(&pdsch_cfg, &pdsch_grant, 20, &pdsch_grant.tb[0]) < SRSLTE_SUCCESS) { + if (srslte_ra_nr_fill_tb(&pdsch_cfg, &pdsch_grant, 27, &pdsch_grant.tb[0]) < SRSLTE_SUCCESS) { ERROR("Error filing tb\n"); return false; } @@ -131,6 +142,13 @@ bool cc_worker::work_dl() return false; } + // Logging + if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) { + char str[512]; + srslte_enb_dl_nr_pdsch_info(&enb_dl, &pdsch_cfg, &pdsch_grant, str, sizeof(str)); + log_h->info("PDSCH: cc=%d, %s\n", cc_idx, str); + } + srslte_enb_dl_nr_gen_signal(&enb_dl); return true; diff --git a/srsenb/src/phy/nr/sf_worker.cc b/srsenb/src/phy/nr/sf_worker.cc index 98ee740b3..41bc4f224 100644 --- a/srsenb/src/phy/nr/sf_worker.cc +++ b/srsenb/src/phy/nr/sf_worker.cc @@ -73,10 +73,21 @@ void sf_worker::set_tti(uint32_t tti) void sf_worker::work_imp() { + // Get Transmission buffers + srslte::rf_buffer_t tx_buffer = {}; + srslte::rf_timestamp_t dummy_ts = {}; + for (uint32_t cc = 0; cc < phy->get_nof_carriers_nr(); cc++) { + for (uint32_t ant = 0; ant < phy->get_nof_ports(0); ant++) { + tx_buffer.set(cc, ant, phy->get_nof_ports(0), cc_workers[cc]->get_tx_buffer(ant)); + } + } + for (auto& w : cc_workers) { w->work_dl(); } + + phy->worker_end(this, tx_buffer, dummy_ts, true); } -}; // namespace nr -}; // namespace srsenb \ No newline at end of file +} // namespace nr +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index 484324436..8c3eda018 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -41,9 +41,12 @@ bool worker_pool::init(const phy_args_t& args, phy_common* common, srslte::logge // Add workers to workers pool and start threads for (uint32_t i = 0; i < args.nof_phy_threads; i++) { - auto w = std::unique_ptr(new sf_worker(common, &phy_state, (srslte::log*)log_vec[i].get())); - pool.init_worker(i, w.get(), prio); - workers.push_back(std::move(w)); + auto w = new sf_worker(common, &phy_state, (srslte::log*)log_vec[i].get()); + pool.init_worker(i, w, prio); + workers.push_back(std::unique_ptr(w)); + + srslte_carrier_nr_t c = common->get_cell_nr(0); + w->set_carrier_unlocked(0, &c); } return true; @@ -69,5 +72,5 @@ void worker_pool::stop() pool.stop(); } -}; // namespace nr -}; // namespace srsenb \ No newline at end of file +} // namespace nr +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index e65b70737..624e770a2 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -67,7 +67,9 @@ void phy::srslte_phy_logger(phy_logger_level_t log_level, char* str) } } -phy::phy(srslte::logger* logger_) : logger(logger_), lte_workers(MAX_WORKERS), workers_common(), nof_workers(0) {} +phy::phy(srslte::logger* logger_) : + logger(logger_), lte_workers(MAX_WORKERS), nr_workers(MAX_WORKERS), workers_common(), nof_workers(0) +{} phy::~phy() { @@ -125,6 +127,7 @@ int phy::init(const phy_args_t& args, // Add workers to workers pool and start threads lte_workers.init(args, &workers_common, logger, WORKERS_THREAD_PRIO); + nr_workers.init(args, &workers_common, logger, WORKERS_THREAD_PRIO); // For each carrier, initialise PRACH worker for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) { @@ -134,7 +137,7 @@ int phy::init(const phy_args_t& args, prach.set_max_prach_offset_us(args.max_prach_offset_us); // Warning this must be initialized after all workers have been added to the pool - tx_rx.init(stack_, radio, <e_workers, &workers_common, &prach, log_h.get(), SF_RECV_THREAD_PRIO); + tx_rx.init(stack_, radio, <e_workers, &nr_workers, &workers_common, &prach, log_h.get(), SF_RECV_THREAD_PRIO); initialized = true; @@ -147,6 +150,7 @@ void phy::stop() tx_rx.stop(); workers_common.stop(); lte_workers.stop(); + nr_workers.stop(); prach.stop(); initialized = false; diff --git a/srsenb/src/phy/phy_common.cc b/srsenb/src/phy/phy_common.cc index f533d62b3..6d895fe1b 100644 --- a/srsenb/src/phy/phy_common.cc +++ b/srsenb/src/phy/phy_common.cc @@ -49,8 +49,8 @@ bool phy_common::init(const phy_cell_cfg_list_t& cell_list_, srslte::radio_interface_phy* radio_h_, stack_interface_phy_lte* stack_) { - radio = radio_h_; - stack = stack_; + radio = radio_h_; + stack = stack_; cell_list_lte = cell_list_; cell_list_nr = cell_list_nr_; @@ -116,11 +116,29 @@ void phy_common::set_ul_grants(uint32_t tti, const stack_interface_phy_lte::ul_s * Each worker uses this function to indicate that all processing is done and data is ready for transmission or * there is no transmission at all (tx_enable). In that case, the end of burst message will be sent to the radio */ -void phy_common::worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time) +void phy_common::worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time, bool is_nr) { // Wait for the green light to transmit in the current TTI semaphore.wait(tx_sem_id); + // If this is for NR, save Tx buffers... + if (is_nr) { + nr_tx_buffer = buffer; + nr_tx_buffer_ready = true; + semaphore.release(); + return; + } else if (nr_tx_buffer_ready) { + // ... otherwise, append NR baseband from saved buffer if available + uint32_t j = 0; + for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) { + if (buffer.get(i) == nullptr) { + buffer.set(i, nr_tx_buffer.get(j)); + j++; + } + } + nr_tx_buffer_ready = false; + } + // Run DL channel emulator if created if (dl_channel) { dl_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), buffer.get_nof_samples(), tx_time.get(0)); diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 1c3f64511..a0821112d 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -42,7 +42,8 @@ txrx::txrx() : thread("TXRX") bool txrx::init(stack_interface_phy_lte* stack_, srslte::radio_interface_phy* radio_h_, - lte::worker_pool* workers_pool_, + lte::worker_pool* lte_workers_, + nr::worker_pool* nr_workers_, phy_common* worker_com_, prach_worker_pool* prach_, srslte::log* log_h_, @@ -51,7 +52,8 @@ bool txrx::init(stack_interface_phy_lte* stack_, stack = stack_; radio_h = radio_h_; log_h = log_h_; - lte_workers = workers_pool_; + lte_workers = lte_workers_; + nr_workers = nr_workers_; worker_com = worker_com_; prach = prach_; tx_worker_cnt = 0; @@ -181,6 +183,12 @@ void txrx::run_thread() lte_worker->set_time(tti, tx_worker_cnt, timestamp); tx_worker_cnt = (tx_worker_cnt + 1) % nof_workers; + // Launch NR worker only if available + if (nr_worker != nullptr) { + worker_com->semaphore.push(nr_worker); + nr_workers->start_worker(nr_worker); + } + // Trigger phy worker execution worker_com->semaphore.push(lte_worker); lte_workers->start_worker(lte_worker); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 12da698d0..e5b918ae3 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -428,6 +428,7 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("vnf.port", bpo::value(&args->phy.vnf_args.bind_port)->default_value(3334), "Bind port") ("nr.nof_carriers", bpo::value(&args->phy.nof_nr_carriers)->default_value(1), "Number of NR carriers") ("nr.nof_prb", bpo::value(&args->phy.nr_nof_prb)->default_value(50), "NR carrier bandwidth") + ("nr.freq", bpo::value(&args->phy.nr_freq_hz)->default_value(2630e6), "NR carrier bandwidth") ; // Positional options - config file location diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index ff98b61ea..9d7fd644a 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -143,4 +143,4 @@ bool cc_worker::work_dl() } } // namespace nr -} // namespace srsue \ No newline at end of file +} // namespace srsue diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 86e99777b..bd3aaf96b 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -855,6 +855,11 @@ bool sync::set_frequency() radio_h->set_rx_freq(0, set_dl_freq); radio_h->set_tx_freq(0, set_ul_freq); + for (uint32_t i = 0; i < worker_com->args->nof_nr_carriers; i++) { + radio_h->set_rx_freq(i + worker_com->args->nof_lte_carriers, worker_com->args->nr_freq_hz); + // radio_h->set_tx_freq(0, set_ul_freq); + } + ul_dl_factor = (float)(set_ul_freq / set_dl_freq); srslte_ue_sync_reset(&ue_sync);