diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 0a0c72f53..7d8bfea76 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -90,10 +90,10 @@ public: virtual int ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack) = 0; virtual int crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc_res) = 0; - virtual int get_dl_sched(uint32_t tti, dl_sched_t* dl_sched_res) = 0; - virtual int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res) = 0; - virtual int get_ul_sched(uint32_t tti, ul_sched_t* ul_sched_res) = 0; - virtual void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0; + virtual int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) = 0; + virtual int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) = 0; + virtual int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) = 0; + virtual void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) = 0; // Radio-Link status virtual void rl_failure(uint16_t rnti) = 0; diff --git a/srsenb/hdr/phy/cc_worker.h b/srsenb/hdr/phy/cc_worker.h index 8ddda152d..3308d3beb 100644 --- a/srsenb/hdr/phy/cc_worker.h +++ b/srsenb/hdr/phy/cc_worker.h @@ -25,7 +25,6 @@ #include #include "phy_common.h" -#include "srslte/srslte.h" #define LOG_EXECTIME diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index 89e751e95..07d5caa40 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -36,15 +36,6 @@ namespace srsenb { -struct phy_cfg_t { - srslte_cell_t cell; - asn1::rrc::prach_cfg_sib_s prach_cnfg; - asn1::rrc::pdsch_cfg_common_s pdsch_cnfg; - asn1::rrc::pusch_cfg_common_s pusch_cnfg; - asn1::rrc::pucch_cfg_common_s pucch_cnfg; - asn1::rrc::srs_ul_cfg_common_c srs_ul_cnfg; -}; - class phy : public enb_phy_base, public phy_interface_stack_lte, public srslte::phy_interface_radio { public: diff --git a/srsenb/hdr/phy/phy_common.h b/srsenb/hdr/phy/phy_common.h index 118ded324..2c3cf4dfa 100644 --- a/srsenb/hdr/phy/phy_common.h +++ b/srsenb/hdr/phy/phy_common.h @@ -22,6 +22,7 @@ #ifndef SRSENB_PHCH_COMMON_H #define SRSENB_PHCH_COMMON_H +#include "phy_interfaces.h" #include "srslte/common/gen_mch_tables.h" #include "srslte/common/interfaces_common.h" #include "srslte/common/log.h" @@ -38,25 +39,6 @@ namespace srsenb { -typedef struct { - std::string type; - srslte::phy_log_args_t log; - - uint32_t nof_carriers; - - float max_prach_offset_us; - int pusch_max_its; - bool pusch_8bit_decoder; - float tx_amplitude; - int nof_phy_threads; - std::string equalizer_mode; - float estimator_fil_w; - bool pregenerate_signals; - - srslte::channel::args_t dl_channel_args; - srslte::channel::args_t ul_channel_args; -} phy_args_t; - class phy_common { public: @@ -65,7 +47,8 @@ public: void set_nof_workers(uint32_t nof_workers); - bool init(const srslte_cell_t& cell_, srslte::radio_interface_phy* radio_handler, stack_interface_phy_lte* mac); + bool + init(const phy_cell_cfg_list_t& cell_list_, srslte::radio_interface_phy* radio_handler, stack_interface_phy_lte* mac); void reset(); void stop(); @@ -73,8 +56,12 @@ public: worker_end(uint32_t tx_mutex_cnt, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); // Common objects - srslte_cell_t cell = {}; - phy_args_t params = {}; + phy_cell_cfg_list_t cell_list; + phy_args_t params = {}; + + uint32_t get_nof_carriers() { return (uint32_t)cell_list.size(); }; + uint32_t get_nof_prb() { return (uint32_t)cell_list[0].cell.nof_prb; }; + uint32_t get_nof_ports() { return (uint32_t)cell_list[0].cell.nof_ports; }; // Physical Uplink Config common srslte_ul_cfg_t ul_cfg_com = {}; @@ -87,8 +74,8 @@ public: srslte::channel_ptr dl_channel = nullptr; // Common objects for schedulign grants - stack_interface_phy_lte::ul_sched_t ul_grants[TTIMOD_SZ] = {}; - stack_interface_phy_lte::dl_sched_t dl_grants[TTIMOD_SZ] = {}; + stack_interface_phy_lte::ul_sched_list_t ul_grants[TTIMOD_SZ] = {}; + stack_interface_phy_lte::dl_sched_list_t dl_grants[TTIMOD_SZ] = {}; // Map of pending ACKs for each user typedef struct { @@ -130,12 +117,12 @@ private: uint32_t nof_workers = 0; uint32_t max_workers = 0; - pthread_mutex_t user_mutex = {}; + std::mutex user_mutex = {}; - bool have_mtch_stop = false; - pthread_mutex_t mtch_mutex = {}; - pthread_cond_t mtch_cvar = {}; - phy_interface_stack_lte::phy_cfg_mbsfn_t mbsfn; + bool have_mtch_stop = false; + pthread_mutex_t mtch_mutex = {}; + pthread_cond_t mtch_cvar = {}; + phy_interface_stack_lte::phy_cfg_mbsfn_t mbsfn = {}; bool sib13_configured = false; bool mcch_configured = false; uint8_t mch_table[40] = {}; diff --git a/srsenb/hdr/phy/phy_interfaces.h b/srsenb/hdr/phy/phy_interfaces.h new file mode 100644 index 000000000..ffc1f6464 --- /dev/null +++ b/srsenb/hdr/phy/phy_interfaces.h @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#ifndef SRSENB_PHY_INTERFACES_H_ +#define SRSENB_PHY_INTERFACES_H_ + +#include +#include +#include +#include +#include + +namespace srsenb { + +struct phy_cell_cfg_t { + srslte_cell_t cell; + uint32_t rf_port; + uint32_t cell_id; + uint32_t dl_earfcn; + uint32_t ul_earfcn; + uint32_t root_seq_idx; +}; + +typedef std::vector phy_cell_cfg_list_t; + +struct phy_args_t { + std::string type; + srslte::phy_log_args_t log; + + float max_prach_offset_us; + int pusch_max_its; + bool pusch_8bit_decoder; + float tx_amplitude; + int nof_phy_threads; + std::string equalizer_mode; + float estimator_fil_w; + bool pregenerate_signals; + + srslte::channel::args_t dl_channel_args; + srslte::channel::args_t ul_channel_args; +}; + +struct phy_cfg_t { + // Individual cell/sector configuration list + phy_cell_cfg_list_t phy_cell_cfg; + + // Common configuration for all cells + asn1::rrc::prach_cfg_sib_s prach_cnfg; + asn1::rrc::pdsch_cfg_common_s pdsch_cnfg; + asn1::rrc::pusch_cfg_common_s pusch_cnfg; + asn1::rrc::pucch_cfg_common_s pucch_cnfg; + asn1::rrc::srs_ul_cfg_common_c srs_ul_cnfg; +}; + +} // namespace srsenb + +#endif // SRSENB_PHY_INTERFACES_H_ diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index ab22b746a..e0cf97112 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -79,12 +79,12 @@ public: { return mac.crc_info(tti, rnti, nof_bytes, crc_res); } - int get_dl_sched(uint32_t tti, dl_sched_t* dl_sched_res) final { return mac.get_dl_sched(tti, dl_sched_res); } - int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res) final + int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) final { return mac.get_dl_sched(tti, dl_sched_res); } + int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) final { return mac.get_mch_sched(tti, is_mcch, dl_sched_res); } - int get_ul_sched(uint32_t tti, ul_sched_t* ul_sched_res) final { return mac.get_ul_sched(tti, ul_sched_res); } + int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) final { return mac.get_ul_sched(tti, ul_sched_res); } void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) final { mac.set_sched_dl_tti_mask(tti_mask, nof_sfs); diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index c92e059b9..17a073866 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -65,9 +65,9 @@ public: int ack_info(uint32_t tti, uint16_t rnti, uint32_t tb_idx, bool ack); int crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc_res); - int get_dl_sched(uint32_t tti, dl_sched_t* dl_sched_res); - int get_ul_sched(uint32_t tti, ul_sched_t* ul_sched_res); - int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res); + int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res); + int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res); + int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res); void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) final { scheduler.set_dl_tti_mask(tti_mask, nof_sfs); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index f87479134..441cdd951 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -792,9 +792,9 @@ int parse_cell_cfg(all_args_t* args_, srslte_cell_t* cell) int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_) { // Parse config files - srslte_cell_t cell_cfg = {}; + srslte_cell_t cell_common_cfg = {}; - if (enb_conf_sections::parse_cell_cfg(args_, &cell_cfg) != SRSLTE_SUCCESS) { + if (enb_conf_sections::parse_cell_cfg(args_, &cell_common_cfg) != SRSLTE_SUCCESS) { fprintf(stderr, "Error parsing Cell configuration\n"); return SRSLTE_ERROR; } @@ -812,11 +812,28 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_) } // Set fields derived from others, and check for correctness of the parsed configuration - return enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, &cell_cfg); + return enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, &cell_common_cfg); } int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, srslte_cell_t* cell_cfg_) { + + // Copy cell struct to rrc and phy + rrc_cfg_->cell = *cell_cfg_; + + // Create dedicated cell configuration from RRC configuration + for (auto& cfg : rrc_cfg_->cell_list) { + phy_cell_cfg_t phy_cell_cfg = {}; + phy_cell_cfg.cell = *cell_cfg_; + phy_cell_cfg.cell.id = cfg.pci; + phy_cell_cfg.cell_id = cfg.cell_id; + phy_cell_cfg.root_seq_idx = cfg.root_seq_idx; + phy_cell_cfg.dl_earfcn = cfg.dl_earfcn; + phy_cell_cfg.ul_earfcn = cfg.ul_earfcn; + phy_cell_cfg.rf_port = cfg.rf_port; + phy_cfg_->phy_cell_cfg.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; @@ -888,13 +905,9 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ } } - // Copy cell struct to rrc and phy - rrc_cfg_->cell = *cell_cfg_; - phy_cfg_->cell = *cell_cfg_; - // Patch certain args that are not exposed yet args_->rf.nof_radios = 1; - args_->rf.nof_rf_channels = args_->phy.nof_carriers; + args_->rf.nof_rf_channels = rrc_cfg_->cell_list.size(); args_->rf.nof_rx_ant = args_->enb.nof_ports; return SRSLTE_SUCCESS; @@ -1371,7 +1384,6 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co } // Copy PHY common configuration - phy_config_common->cell = {}; phy_config_common->prach_cnfg = sib2->rr_cfg_common.prach_cfg; phy_config_common->pdsch_cnfg = sib2->rr_cfg_common.pdsch_cfg_common; phy_config_common->pusch_cnfg = sib2->rr_cfg_common.pusch_cfg_common; diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 30680f427..476cf0f7a 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -184,7 +184,6 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.print_buffer_state", bpo::value(&args->general.print_buffer_state)->default_value(false), "Prints on the console the buffer state every 10 seconds") ("expert.eea_pref_list", bpo::value(&args->general.eea_pref_list)->default_value("EEA0, EEA2, EEA1"), "Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).") ("expert.eia_pref_list", bpo::value(&args->general.eia_pref_list)->default_value("EIA2, EIA1, EIA0"), "Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0).") - ("expert.nof_carriers", bpo::value(&args->phy.nof_carriers)->default_value(1), "Number of carriers") // eMBMS section ("embms.enable", bpo::value(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB") diff --git a/srsenb/src/phy/cc_worker.cc b/srsenb/src/phy/cc_worker.cc index 90a45c558..38602c416 100644 --- a/srsenb/src/phy/cc_worker.cc +++ b/srsenb/src/phy/cc_worker.cc @@ -86,38 +86,40 @@ FILE* f; void cc_worker::init(phy_common* phy_, srslte::log* log_h_, uint32_t cc_idx_) { - phy = phy_; - log_h = log_h_; - cc_idx = cc_idx_; + srslte_cell_t cell = phy_->cell_list[cc_idx_].cell; + uint32_t nof_prb = phy_->get_nof_prb(); + phy = phy_; + log_h = log_h_; + cc_idx = cc_idx_; // Init cell here for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { - signal_buffer_rx[p] = (cf_t*)srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + signal_buffer_rx[p] = srslte_vec_cf_malloc(2 * SRSLTE_SF_LEN_PRB(nof_prb)); if (!signal_buffer_rx[p]) { ERROR("Error allocating memory\n"); return; } - bzero(signal_buffer_rx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); - signal_buffer_tx[p] = (cf_t*)srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + bzero(signal_buffer_rx[p], 2 * SRSLTE_SF_LEN_PRB(phy->get_nof_prb()) * sizeof(cf_t)); + signal_buffer_tx[p] = (cf_t*)srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(nof_prb) * sizeof(cf_t)); if (!signal_buffer_tx[p]) { ERROR("Error allocating memory\n"); return; } - bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + bzero(signal_buffer_tx[p], 2 * SRSLTE_SF_LEN_PRB(nof_prb) * sizeof(cf_t)); } - if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) { + if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->get_nof_prb())) { ERROR("Error initiating ENB DL\n"); return; } - if (srslte_enb_dl_set_cell(&enb_dl, phy->cell)) { + if (srslte_enb_dl_set_cell(&enb_dl, cell)) { ERROR("Error initiating ENB DL\n"); return; } - if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx[0], phy->cell.nof_prb)) { + if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx[0], phy->get_nof_prb())) { ERROR("Error initiating ENB UL\n"); return; } - if (srslte_enb_ul_set_cell(&enb_ul, phy->cell, &phy->ul_cfg_com.dmrs)) { + if (srslte_enb_ul_set_cell(&enb_ul, cell, &phy->ul_cfg_com.dmrs)) { ERROR("Error initiating ENB UL\n"); return; } @@ -133,14 +135,14 @@ void cc_worker::init(phy_common* phy_, srslte::log* log_h_, uint32_t cc_idx_) add_rnti(1 + i, false); } - if (srslte_softbuffer_tx_init(&temp_mbsfn_softbuffer, phy->cell.nof_prb)) { + if (srslte_softbuffer_tx_init(&temp_mbsfn_softbuffer, nof_prb)) { ERROR("Error initiating soft buffer\n"); exit(-1); } srslte_softbuffer_tx_reset(&temp_mbsfn_softbuffer); - Info("Component Carrier Worker %d configured cell %d PRB\n", cc_idx, phy->cell.nof_prb); + Info("Component Carrier Worker %d configured cell %d PRB\n", cc_idx, nof_prb); if (phy->params.pusch_8bit_decoder) { enb_ul.pusch.llr_is_8bit = true; @@ -214,15 +216,21 @@ void cc_worker::rem_rnti(uint16_t rnti) srslte_enb_ul_rem_rnti(&enb_ul, rnti); // remove any pending dci for each subframe - for (uint32_t i = 0; i < TTIMOD_SZ; i++) { - for (uint32_t j = 0; j < phy->ul_grants[i].nof_grants; j++) { - if (phy->ul_grants[i].pusch[j].dci.rnti == rnti) { - phy->ul_grants[i].pusch[j].dci.rnti = 0; + for (auto& list : phy->ul_grants) { + for (auto& q : list) { + for (uint32_t j = 0; j < q.nof_grants; j++) { + if (q.pusch[j].dci.rnti == rnti) { + q.pusch[j].dci.rnti = 0; + } } } - for (uint32_t j = 0; j < phy->dl_grants[i].nof_grants; j++) { - if (phy->dl_grants[i].pdsch[j].dci.rnti == rnti) { - phy->dl_grants[i].pdsch[j].dci.rnti = 0; + } + for (auto& list : phy->dl_grants) { + for (auto& q : list) { + for (uint32_t j = 0; j < q.nof_grants; j++) { + if (q.pdsch[j].dci.rnti == rnti) { + q.pdsch[j].dci.rnti = 0; + } } } } @@ -476,7 +484,7 @@ int cc_worker::decode_pusch(stack_interface_phy_lte::ul_sched_grant_t* grants, u // Compute UL grant srslte_pusch_grant_t* grant = &ue_db[rnti]->ul_cfg.pusch.grant; - if (srslte_ra_ul_dci_to_grant(&phy->cell, &ul_sf, &ue_db[rnti]->ul_cfg.hopping, &grants[i].dci, grant)) { + if (srslte_ra_ul_dci_to_grant(&enb_ul.cell, &ul_sf, &ue_db[rnti]->ul_cfg.hopping, &grants[i].dci, grant)) { Error("Computing PUSCH dci\n"); return SRSLTE_ERROR; } @@ -643,8 +651,8 @@ int cc_worker::encode_pmch(stack_interface_phy_lte::dl_sched_grant_t* grant, srs { srslte_pmch_cfg_t pmch_cfg; ZERO_OBJECT(pmch_cfg); - srslte_configure_pmch(&pmch_cfg, &phy->cell, mbsfn_cfg); - srslte_ra_dl_compute_nof_re(&phy->cell, &dl_sf, &pmch_cfg.pdsch_cfg.grant); + srslte_configure_pmch(&pmch_cfg, &enb_dl.cell, mbsfn_cfg); + srslte_ra_dl_compute_nof_re(&enb_dl.cell, &dl_sf, &pmch_cfg.pdsch_cfg.grant); // Set soft buffer pmch_cfg.pdsch_cfg.softbuffers.tx[0] = &temp_mbsfn_softbuffer; @@ -680,7 +688,7 @@ int cc_worker::encode_pdsch(stack_interface_phy_lte::dl_sched_grant_t* grants, u // Compute DL grant if (srslte_ra_dl_dci_to_grant( - &phy->cell, &dl_sf, ue_db[rnti]->dl_cfg.tm, false, &grants[i].dci, &ue_db[rnti]->dl_cfg.pdsch.grant)) { + &enb_dl.cell, &dl_sf, ue_db[rnti]->dl_cfg.tm, false, &grants[i].dci, &ue_db[rnti]->dl_cfg.pdsch.grant)) { Error("Computing DL grant\n"); } @@ -730,8 +738,7 @@ uint32_t cc_worker::get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) std::lock_guard lock(mutex); uint32_t cnt = 0; for (auto& ue : ue_db) { - if ((SRSLTE_RNTI_ISUSER(ue.first) || ue.first == SRSLTE_MRNTI) && - cnt < ENB_METRICS_MAX_USERS) { + if ((SRSLTE_RNTI_ISUSER(ue.first) || ue.first == SRSLTE_MRNTI) && cnt < ENB_METRICS_MAX_USERS) { ue.second->metrics_read(&metrics[cnt]); cnt++; } @@ -764,19 +771,19 @@ void cc_worker::ue::metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo int cc_worker::read_ce_abs(float* ce_abs) { - int sz = srslte_symbol_sz(phy->cell.nof_prb); + int sz = srslte_symbol_sz(phy->get_nof_prb()); bzero(ce_abs, sizeof(float) * sz); - int g = (sz - 12 * phy->cell.nof_prb) / 2; - srslte_vec_abs_dB_cf(enb_ul.chest_res.ce, -80.0f, &ce_abs[g], SRSLTE_NRE * phy->cell.nof_prb); + int g = (sz - SRSLTE_NRE * phy->get_nof_prb()) / 2; + srslte_vec_abs_dB_cf(enb_ul.chest_res.ce, -80.0f, &ce_abs[g], SRSLTE_NRE * phy->get_nof_prb()); return sz; } int cc_worker::read_ce_arg(float* ce_arg) { - int sz = srslte_symbol_sz(phy->cell.nof_prb); + int sz = srslte_symbol_sz(phy->get_nof_prb()); bzero(ce_arg, sizeof(float) * sz); - int g = (sz - 12 * phy->cell.nof_prb) / 2; - srslte_vec_arg_deg_cf(enb_ul.chest_res.ce, -80.0f, &ce_arg[g], SRSLTE_NRE * phy->cell.nof_prb); + int g = (sz - SRSLTE_NRE * phy->get_nof_prb()) / 2; + srslte_vec_arg_deg_cf(enb_ul.chest_res.ce, -80.0f, &ce_arg[g], SRSLTE_NRE * phy->get_nof_prb()); return sz; } diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 01af691de..19a75b90b 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -141,7 +141,7 @@ int phy::init(const phy_args_t& args, workers_common.params = args; - workers_common.init(cfg.cell, radio, stack_); + workers_common.init(cfg.phy_cell_cfg, radio, stack_); parse_config(cfg); @@ -152,8 +152,9 @@ int phy::init(const phy_args_t& args, } // For each carrier, initialise PRACH worker - for (uint32_t cc = 0; cc < args.nof_carriers; cc++) { - prach.init(cc, cfg.cell, prach_cfg, stack_, log_vec.at(0).get(), PRACH_WORKER_THREAD_PRIO); + for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) { + prach_cfg.root_seq_idx = cfg.phy_cell_cfg[cc].root_seq_idx; + prach.init(cc, cfg.phy_cell_cfg[cc].cell, prach_cfg, stack_, log_vec.at(0).get(), PRACH_WORKER_THREAD_PRIO); } prach.set_max_prach_offset_us(args.max_prach_offset_us); diff --git a/srsenb/src/phy/phy_common.cc b/srsenb/src/phy/phy_common.cc index b1e70c0ef..2c749398f 100644 --- a/srsenb/src/phy/phy_common.cc +++ b/srsenb/src/phy/phy_common.cc @@ -46,11 +46,9 @@ using namespace asn1::rrc; namespace srsenb { -phy_common::phy_common(uint32_t max_workers_) : tx_sem(max_workers_) +phy_common::phy_common(uint32_t max_workers_) : tx_sem(max_workers_), cell_list() { - nof_workers = 0; params.max_prach_offset_us = 20; - have_mtch_stop = false; max_workers = max_workers_; for (uint32_t i = 0; i < max_workers; i++) { @@ -76,35 +74,30 @@ void phy_common::reset() bzero(dl_grants, sizeof(stack_interface_phy_lte::dl_sched_t) * TTIMOD_SZ); } -bool phy_common::init(const srslte_cell_t& cell_, +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_; - cell = cell_; + radio = radio_h_; + stack = stack_; + cell_list = cell_list_; - pthread_mutex_init(&user_mutex, nullptr); pthread_mutex_init(&mtch_mutex, nullptr); pthread_cond_init(&mtch_cvar, nullptr); - // Instantiate UL channel emulator + // Instantiate DL channel emulator if (params.ul_channel_args.enable) { dl_channel = srslte::channel_ptr(new srslte::channel(params.dl_channel_args, 1)); - - dl_channel->set_srate((uint32_t)srslte_sampling_freq_hz(cell.nof_prb)); + dl_channel->set_srate((uint32_t)srslte_sampling_freq_hz(cell_list[0].cell.nof_prb)); } - is_first_tx = true; - - // Instantiate UL channel emulator - if (params.ul_channel_args.enable) { - dl_channel = srslte::channel_ptr(new srslte::channel(params.dl_channel_args, 1)); - - dl_channel->set_srate((uint32_t)srslte_sampling_freq_hz(cell.nof_prb)); + // Create grants + for (auto& q : dl_grants) { + q.resize(cell_list_.size()); } is_first_tx = true; + reset(); return true; } @@ -166,11 +159,10 @@ void phy_common::ue_db_clear(uint32_t tti) void phy_common::ue_db_add_rnti(uint16_t rnti) { - pthread_mutex_lock(&user_mutex); + std::lock_guard lock(user_mutex); if (!common_ue_db.count(rnti)) { add_rnti(rnti); } - pthread_mutex_unlock(&user_mutex); } // Private function not mutexed @@ -185,27 +177,25 @@ void phy_common::add_rnti(uint16_t rnti) void phy_common::ue_db_rem_rnti(uint16_t rnti) { - pthread_mutex_lock(&user_mutex); + std::lock_guard lock(user_mutex); if (!common_ue_db.count(rnti)) { common_ue_db.erase(rnti); } - pthread_mutex_unlock(&user_mutex); } void phy_common::ue_db_set_ack_pending(uint32_t tti, uint16_t rnti, uint32_t tb_idx, uint32_t last_n_pdcch) { - pthread_mutex_lock(&user_mutex); + std::lock_guard lock(user_mutex); if (common_ue_db.count(rnti)) { common_ue_db[rnti].pending_ack.is_pending[TTIMOD(tti)][tb_idx] = true; common_ue_db[rnti].pending_ack.n_pdcch[TTIMOD(tti)] = (uint16_t)last_n_pdcch; } - pthread_mutex_unlock(&user_mutex); } bool phy_common::ue_db_is_ack_pending(uint32_t tti, uint16_t rnti, uint32_t tb_idx, uint32_t* last_n_pdcch) { - bool ret = false; - pthread_mutex_lock(&user_mutex); + bool ret = false; + std::lock_guard lock(user_mutex); if (common_ue_db.count(rnti)) { ret = common_ue_db[rnti].pending_ack.is_pending[TTIMOD(tti)][tb_idx]; common_ue_db[rnti].pending_ack.is_pending[TTIMOD(tti)][tb_idx] = false; @@ -214,48 +204,43 @@ bool phy_common::ue_db_is_ack_pending(uint32_t tti, uint16_t rnti, uint32_t tb_i *last_n_pdcch = common_ue_db[rnti].pending_ack.n_pdcch[TTIMOD(tti)]; } } - pthread_mutex_unlock(&user_mutex); return ret; } void phy_common::ue_db_set_ri(uint16_t rnti, uint8_t ri) { - pthread_mutex_lock(&user_mutex); + std::lock_guard lock(user_mutex); if (common_ue_db.count(rnti)) { common_ue_db[rnti].ri = ri; } - pthread_mutex_unlock(&user_mutex); } uint8_t phy_common::ue_db_get_ri(uint16_t rnti) { - pthread_mutex_lock(&user_mutex); - uint8_t ret = 0; + std::lock_guard lock(user_mutex); + uint8_t ret = 0; if (common_ue_db.count(rnti)) { ret = common_ue_db[rnti].ri; } - pthread_mutex_unlock(&user_mutex); return ret; } void phy_common::ue_db_set_last_ul_tb(uint16_t rnti, uint32_t pid, srslte_ra_tb_t tb) { - pthread_mutex_lock(&user_mutex); + std::lock_guard lock(user_mutex); if (!common_ue_db.count(rnti)) { add_rnti(rnti); } common_ue_db[rnti].last_tb[pid % SRSLTE_MAX_HARQ_PROC] = tb; - pthread_mutex_unlock(&user_mutex); } srslte_ra_tb_t phy_common::ue_db_get_last_ul_tb(uint16_t rnti, uint32_t pid) { - pthread_mutex_lock(&user_mutex); - srslte_ra_tb_t ret = {}; + std::lock_guard lock(user_mutex); + srslte_ra_tb_t ret = {}; if (common_ue_db.count(rnti)) { ret = common_ue_db[rnti].last_tb[pid % SRSLTE_FDD_NOF_HARQ]; } - pthread_mutex_unlock(&user_mutex); return ret; } diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index f57fe99f5..0436a9945 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -78,7 +78,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->params.nof_carriers; i++) { + for (uint32_t i = 0; i < phy->get_nof_carriers(); i++) { // Create pointer auto q = new cc_worker(); @@ -89,14 +89,14 @@ void sf_worker::init(phy_common* phy_, srslte::log* log_h_) cc_workers.push_back(std::unique_ptr(q)); } - if (srslte_softbuffer_tx_init(&temp_mbsfn_softbuffer, phy->cell.nof_prb)) { + if (srslte_softbuffer_tx_init(&temp_mbsfn_softbuffer, phy->get_nof_prb())) { ERROR("Error initiating soft buffer\n"); exit(-1); } srslte_softbuffer_tx_reset(&temp_mbsfn_softbuffer); - Info("Worker %d configured cell %d PRB\n", get_id(), phy->cell.nof_prb); + Info("Worker %d configured cell %d PRB\n", get_id(), phy->get_nof_prb()); initiated = true; running = true; @@ -178,9 +178,9 @@ void sf_worker::work_imp() srslte_mbsfn_cfg_t mbsfn_cfg; srslte_sf_t sf_type = phy->is_mbsfn_sf(&mbsfn_cfg, tti_tx_dl) ? SRSLTE_SF_MBSFN : SRSLTE_SF_NORM; - stack_interface_phy_lte::ul_sched_t* ul_grants = phy->ul_grants; - stack_interface_phy_lte::dl_sched_t* dl_grants = phy->dl_grants; - stack_interface_phy_lte* stack = phy->stack; + stack_interface_phy_lte::ul_sched_list_t* ul_grants = phy->ul_grants; + stack_interface_phy_lte::dl_sched_list_t* dl_grants = phy->dl_grants; + stack_interface_phy_lte* stack = phy->stack; log_h->step(tti_rx); @@ -190,56 +190,56 @@ void sf_worker::work_imp() ul_sf.tti = tti_rx; // Process UL - for (auto& w : cc_workers) { - w->work_ul(&ul_sf, &phy->ul_grants[t_rx]); + for (auto& q : phy->dl_grants[t_tx_dl]) { + q.cfi = mbsfn_cfg.non_mbsfn_region_length; } // Get DL scheduling for the TX TTI from MAC if (sf_type == SRSLTE_SF_NORM) { - if (stack->get_dl_sched(tti_tx_dl, &dl_grants[t_tx_dl]) < 0) { + if (stack->get_dl_sched(tti_tx_dl, dl_grants[t_tx_dl]) < 0) { Error("Getting DL scheduling from MAC\n"); return; } } else { - dl_grants[t_tx_dl].cfi = mbsfn_cfg.non_mbsfn_region_length; - if (stack->get_mch_sched(tti_tx_dl, mbsfn_cfg.is_mcch, &dl_grants[t_tx_dl])) { + dl_grants[t_tx_dl][0].cfi = mbsfn_cfg.non_mbsfn_region_length; + if (stack->get_mch_sched(tti_tx_dl, mbsfn_cfg.is_mcch, dl_grants[t_tx_dl])) { Error("Getting MCH packets from MAC\n"); return; } } - if (dl_grants[t_tx_dl].cfi < 1 || dl_grants[t_tx_dl].cfi > 3) { - Error("Invalid CFI=%d\n", dl_grants[t_tx_dl].cfi); + if (dl_grants[t_tx_dl][0].cfi < 1 || dl_grants[t_tx_dl][0].cfi > 3) { + Error("Invalid CFI=%d\n", dl_grants[t_tx_dl][0].cfi); return; } // Get UL scheduling for the TX TTI from MAC - if (stack->get_ul_sched(tti_tx_ul, &ul_grants[t_tx_ul]) < 0) { + if (stack->get_ul_sched(tti_tx_ul, ul_grants[t_tx_ul]) < 0) { Error("Getting UL scheduling from MAC\n"); return; } // Configure DL subframe dl_sf.tti = tti_tx_dl; - dl_sf.cfi = dl_grants[t_tx_dl].cfi; + dl_sf.cfi = dl_grants[t_tx_dl][0].cfi; dl_sf.sf_type = sf_type; dl_sf.non_mbsfn_region = mbsfn_cfg.non_mbsfn_region_length; // Process DL - for (auto& w : cc_workers) { - w->work_dl(&dl_sf, &phy->dl_grants[t_tx_dl], &phy->ul_grants[t_tx_ul], &mbsfn_cfg); + for (uint32_t cc = 0; cc < cc_workers.size(); cc++) { + cc_workers[cc]->work_dl(&dl_sf, &phy->dl_grants[t_tx_dl][cc], &phy->ul_grants[t_tx_ul][cc], &mbsfn_cfg); } // Get Transmission buffers - for (uint32_t cc = 0, i = 0; cc < phy->params.nof_carriers; cc++) { - for (uint32_t ant = 0; ant < phy->cell.nof_ports; ant++, i++) { + for (uint32_t cc = 0, i = 0; cc < phy->get_nof_carriers(); cc++) { + for (uint32_t ant = 0; ant < phy->get_nof_ports(); ant++, i++) { signal_buffer_tx[i] = cc_workers[cc]->get_buffer_tx(ant); } } Debug("Sending to radio\n"); - phy->worker_end(tx_worker_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); + phy->worker_end(tx_worker_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->get_nof_prb()), tx_time); #ifdef DEBUG_WRITE_FILE fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t), 1, f); @@ -265,7 +265,7 @@ uint32_t sf_worker::get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) { uint32_t cnt = 0; phy_metrics_t _metrics[ENB_METRICS_MAX_USERS] = {}; - for (uint32_t cc = 0; cc < phy->params.nof_carriers; cc++) { + for (uint32_t cc = 0; cc < phy->get_nof_carriers(); cc++) { cnt = cc_workers[cc]->get_metrics(_metrics); for (uint32_t r = 0; r < cnt; r++) { phy_metrics_t* m = &metrics[r]; diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 7e9aae481..a25456bc8 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -68,7 +68,8 @@ bool txrx::init(srslte::radio_interface_phy* radio_h_, nof_workers = workers_pool->get_nof_workers(); worker_com->set_nof_workers(nof_workers); - if (worker_com->params.dl_channel_args.enable) { + // Instantiate UL channel emulator + if (worker_com->params.ul_channel_args.enable) { ul_channel = srslte::channel_ptr(new srslte::channel(worker_com->params.ul_channel_args, 1)); } @@ -88,20 +89,49 @@ void txrx::run_thread() cf_t* buffer[SRSLTE_MAX_PORTS] = {}; srslte_timestamp_t rx_time = {}; srslte_timestamp_t tx_time = {}; - uint32_t sf_len = SRSLTE_SF_LEN_PRB(worker_com->cell.nof_prb); + uint32_t sf_len = SRSLTE_SF_LEN_PRB(worker_com->get_nof_prb()); - float samp_rate = srslte_sampling_freq_hz(worker_com->cell.nof_prb); + float samp_rate = srslte_sampling_freq_hz(worker_com->get_nof_prb()); log_h->console("Setting Sampling frequency %.2f MHz\n", (float)samp_rate / 1000000); // Configure radio radio_h->set_rx_srate(0, samp_rate); radio_h->set_tx_srate(0, samp_rate); + for (auto& cfg : worker_com->cell_list) { + // If there is no UL-EARDCN, deduce it from DL-EARFCN + if (cfg.ul_earfcn == 0) { + cfg.ul_earfcn = srslte_band_ul_earfcn(cfg.dl_earfcn); + } + + // Set Tx/Rx frequencies + float tx_freq_hz = 1e6 * srslte_band_fd(cfg.dl_earfcn); + float rx_freq_hz = 1e6 * srslte_band_fd(cfg.ul_earfcn); + for (uint32_t i = 0; i < worker_com->get_nof_ports(); i++) { + radio_h->set_tx_freq(0, cfg.rf_port + i, tx_freq_hz); + radio_h->set_rx_freq(0, cfg.rf_port + i, rx_freq_hz); + } + } + if (ul_channel) { - ul_channel->set_srate(samp_rate); + ul_channel->set_srate(static_cast(samp_rate)); + for (auto& cfg : worker_com->cell_list) { + // If there is no UL-EARDCN, deduce it from DL-EARFCN + if (cfg.ul_earfcn == 0) { + cfg.ul_earfcn = srslte_band_ul_earfcn(cfg.dl_earfcn); + } + + // Set Tx/Rx frequencies + float tx_freq_hz = 1e6 * srslte_band_fd(cfg.dl_earfcn); + float rx_freq_hz = 1e6 * srslte_band_fd(cfg.ul_earfcn); + for (uint32_t i = 0; i < worker_com->get_nof_ports(); i++) { + radio_h->set_tx_freq(0, cfg.rf_port + i, tx_freq_hz); + radio_h->set_rx_freq(0, cfg.rf_port + i, rx_freq_hz); + } + } } - log_h->info("Starting RX/TX thread nof_prb=%d, sf_len=%d\n", worker_com->cell.nof_prb, sf_len); + log_h->info("Starting RX/TX thread nof_prb=%d, sf_len=%d\n", worker_com->get_nof_prb(), sf_len); // Set TTI so that first TX is at tti=0 tti = 10235; @@ -111,9 +141,10 @@ void txrx::run_thread() tti = (tti + 1) % 10240; worker = (sf_worker*)workers_pool->wait_worker(tti); if (worker) { - for (uint32_t c = 0, i = 0; c < worker_com->params.nof_carriers; c++) { - for (uint32_t p = 0; p < worker_com->cell.nof_ports; p++, i++) { - buffer[i] = worker->get_buffer_rx(c, p); + for (uint32_t cc = 0; cc < worker_com->get_nof_carriers(); cc++) { + uint32_t rf_port = worker_com->cell_list[cc].rf_port; + for (uint32_t p = 0; p < worker_com->get_nof_ports(); p++) { + buffer[rf_port + p] = worker->get_buffer_rx(cc, p); } } @@ -141,8 +172,8 @@ void txrx::run_thread() workers_pool->start_worker(worker); // Trigger prach worker execution - for (uint32_t cc = 0; cc < worker_com->params.nof_carriers; cc++) { - prach->new_tti(cc, tti, buffer[cc * worker_com->cell.nof_ports]); + for (uint32_t cc = 0; cc < worker_com->get_nof_carriers(); cc++) { + prach->new_tti(cc, tti, buffer[worker_com->cell_list[cc].rf_port * worker_com->get_nof_ports()]); } } else { // wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index a643c677f..31548902a 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -216,7 +216,7 @@ int mac::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) } // Update Scheduler configuration - if ((cfg != NULL) ? scheduler.ue_cfg(rnti, cfg) : false) { + if ((cfg != nullptr) ? scheduler.ue_cfg(rnti, cfg) : false) { Error("Registering new UE rnti=0x%x to SCHED\n", rnti); } else { ret = 0; @@ -514,7 +514,7 @@ int mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx, return 0; } -int mac::get_dl_sched(uint32_t tti, dl_sched_t* dl_sched_res) +int mac::get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res_list) { if (!started) { return 0; @@ -522,10 +522,6 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t* dl_sched_res) log_h->step(tti); - if (!dl_sched_res) { - return SRSLTE_ERROR_INVALID_INPUTS; - } - // Run scheduler with current info sched_interface::dl_sched_res_t sched_result = {}; if (scheduler.dl_sched(tti, 0, sched_result) < 0) { @@ -533,8 +529,8 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t* dl_sched_res) return SRSLTE_ERROR; } - int n = 0; - + int n = 0; + dl_sched_t* dl_sched_res = &dl_sched_res_list[0]; pthread_rwlock_rdlock(&rwlock); // Copy data grants @@ -568,7 +564,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t* dl_sched_res) } else { /* TB not enabled OR no data to send: set pointers to NULL */ - dl_sched_res->pdsch[n].data[tb] = NULL; + dl_sched_res->pdsch[n].data[tb] = nullptr; } } n++; @@ -668,8 +664,9 @@ void mac::build_mch_sched(uint32_t tbs) } } -int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res) +int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res_list) { + dl_sched_t* dl_sched_res = &dl_sched_res_list[0]; log_h->step(tti); srslte_ra_tb_t mcs = {}; srslte_ra_tb_t mcs_data = {}; @@ -728,7 +725,7 @@ int mac::get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_t* dl_sched_res) } } else { dl_sched_res->pdsch[0].dci.rnti = 0; - dl_sched_res->pdsch[0].data[0] = NULL; + dl_sched_res->pdsch[0].data[0] = nullptr; } mch.current_sf_allocation_num++; } @@ -760,7 +757,7 @@ uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, return rar_payload[rar_idx].msg; } else { Error("Assembling RAR: pdu_len > rar_payload_len (%d>%d)\n", pdu_len, rar_payload_len); - return NULL; + return nullptr; } } @@ -770,19 +767,15 @@ uint8_t* mac::assemble_si(uint32_t index) return bcch_dlsch_payload; } -int mac::get_ul_sched(uint32_t tti, ul_sched_t* ul_sched_res) +int mac::get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res_list) { - + ul_sched_t* ul_sched_res = &ul_sched_res_list[0]; log_h->step(tti); if (!started) { return 0; } - if (!ul_sched_res) { - return SRSLTE_ERROR_INVALID_INPUTS; - } - // Run scheduler with current info sched_interface::ul_sched_res_t sched_result = {}; if (scheduler.ul_sched(tti, 0, sched_result) < 0) {