diff --git a/srsenb/hdr/stack/mac/sched_ue.h b/srsenb/hdr/stack/mac/sched_ue.h index 56c31d26b..3a53caffd 100644 --- a/srsenb/hdr/stack/mac/sched_ue.h +++ b/srsenb/hdr/stack/mac/sched_ue.h @@ -27,7 +27,6 @@ namespace srsenb { typedef enum { UCI_PUSCH_NONE = 0, UCI_PUSCH_CQI, UCI_PUSCH_ACK, UCI_PUSCH_ACK_CQI } uci_pusch_t; -enum class cc_st { active, idle, activating, deactivating }; struct tbs_info { int tbs_bytes = -1; @@ -35,14 +34,9 @@ struct tbs_info { }; struct cc_sched_ue { - cc_sched_ue(const sched_interface::ue_cfg_t& cfg_, - sched_ue_cell& cell_ue_, - uint16_t rnti_, - uint32_t ue_cc_idx, - srslte::tti_point current_tti); + cc_sched_ue(const sched_interface::ue_cfg_t& cfg_, sched_ue_cell& cell_ue_, uint16_t rnti_, uint32_t ue_cc_idx); void reset(); void set_cfg(const sched_interface::ue_cfg_t& cfg); ///< reconfigure ue carrier - void finish_tti(srslte::tti_point tti_rx); uint32_t get_aggr_level(uint32_t nof_bits); tbs_info alloc_tbs(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, bool is_ul); @@ -52,23 +46,7 @@ struct cc_sched_ue { uint32_t get_required_prb_ul(uint32_t req_bytes); const sched_cell_params_t* get_cell_cfg() const { return cell_ue->cell_cfg; } uint32_t get_ue_cc_idx() const { return ue_cc_idx; } - void set_dl_cqi(tti_point tti_rx, uint32_t dl_cqi); int cqi_to_tbs(uint32_t nof_prb, uint32_t nof_re, bool is_ul, uint32_t* mcs); - cc_st cc_state() const { return cc_state_; } - - uint32_t dl_ri = 0; - tti_point dl_ri_tti_rx{}; - uint32_t dl_pmi = 0; - tti_point dl_pmi_tti_rx{}; - uint32_t dl_cqi = 1; - tti_point dl_cqi_tti_rx{0}; - uint32_t ul_cqi = 1; - tti_point ul_cqi_tti_rx{}; - bool dl_cqi_rx = false; - - uint32_t max_mcs_dl = 28, max_mcs_ul = 28; - uint32_t max_aggr_level = 3; - int fixed_mcs_ul = 0, fixed_mcs_dl = 0; private: // config @@ -78,10 +56,6 @@ private: uint16_t rnti; uint32_t ue_cc_idx = 0; srslte::tti_point cfg_tti; - - // state - srslte::tti_point last_tti; - cc_st cc_state_ = cc_st::idle; }; /** This class is designed to be thread-safe because it is called from workers through scheduler thread and from @@ -185,7 +159,7 @@ public: srslte_dci_format_t get_dci_format(); const sched_dci_cce_t* get_locations(uint32_t enb_cc_idx, uint32_t current_cfi, uint32_t sf_idx) const; - cc_sched_ue* find_ue_carrier(uint32_t enb_cc_idx); + sched_ue_cell* find_ue_carrier(uint32_t enb_cc_idx); size_t nof_carriers_configured() const { return carriers.size(); } std::bitset scell_activation_mask() const; int enb_to_ue_cc_idx(uint32_t enb_cc_idx) const; diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h index e54198581..840374cb6 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_ue_cell.h @@ -19,18 +19,26 @@ namespace srsenb { +enum class cc_st { active, idle, activating, deactivating }; + struct sched_ue_cell { using ue_cc_cfg = sched_interface::ue_cfg_t::cc_cfg_t; const static int SCHED_MAX_HARQ_PROC = FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS; - sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg_); + sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg_, tti_point current_tti); void set_ue_cfg(const sched_interface::ue_cfg_t& ue_cfg_); + void new_tti(tti_point tti_rx); void reset(); void finish_tti(tti_point tti_rx); + void set_dl_cqi(tti_point tti_rx, uint32_t dl_cqi_); + bool configured() const { return ue_cc_idx >= 0; } int get_ue_cc_idx() const { return ue_cc_idx; } const ue_cc_cfg* get_ue_cc_cfg() const { return configured() ? &ue_cfg->supported_cc_list[ue_cc_idx] : nullptr; } + cc_st cc_state() const { return cc_state_; } + + const uint16_t rnti; /// Cell const configuration const sched_cell_params_t* cell_cfg = nullptr; @@ -44,9 +52,32 @@ struct sched_ue_cell { /// Cell Transmit Power Control state machine tpc tpc_fsm; + /// UCI Feedback + uint32_t dl_ri = 0; + tti_point dl_ri_tti_rx{}; + uint32_t dl_pmi = 0; + tti_point dl_pmi_tti_rx{}; + uint32_t dl_cqi = 1; + tti_point dl_cqi_tti_rx{0}; + uint32_t ul_cqi = 1; + tti_point ul_cqi_tti_rx{}; + bool dl_cqi_rx = false; + + uint32_t max_mcs_dl = 28, max_mcs_ul = 28; + uint32_t max_aggr_level = 3; + int fixed_mcs_ul = 0, fixed_mcs_dl = 0; + private: - const sched_interface::ue_cfg_t* ue_cfg = nullptr; + srslte::log_ref log_h{"MAC"}; + + const sched_interface::ue_cfg_t* ue_cfg = nullptr; + tti_point cfg_tti; int ue_cc_idx = -1; + + // state + tti_point current_tti; + srslte::tti_point last_tti; + cc_st cc_state_ = cc_st::idle; }; } // namespace srsenb diff --git a/srsenb/src/stack/mac/sched.cc b/srsenb/src/stack/mac/sched.cc index 464ac75e5..467fdf754 100644 --- a/srsenb/src/stack/mac/sched.cc +++ b/srsenb/src/stack/mac/sched.cc @@ -258,7 +258,7 @@ std::array sched::get_enb_ue_cc_map(uint16_t rnti) rnti, [this, &ret](sched_ue& ue) { for (size_t enb_cc_idx = 0; enb_cc_idx < carrier_schedulers.size(); ++enb_cc_idx) { - const cc_sched_ue* cc_ue = ue.find_ue_carrier(enb_cc_idx); + const sched_ue_cell* cc_ue = ue.find_ue_carrier(enb_cc_idx); if (cc_ue != nullptr) { ret[enb_cc_idx] = cc_ue->get_ue_cc_idx(); } diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 6e15fa052..4508f8f1b 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -52,9 +52,9 @@ cc_sched_result* sf_sched_result::new_cc(uint32_t enb_cc_idx) bool sf_sched_result::is_ul_alloc(uint16_t rnti) const { - for (uint32_t i = 0; i < enb_cc_list.size(); ++i) { - for (uint32_t j = 0; j < enb_cc_list[i].ul_sched_result.nof_dci_elems; ++j) { - if (enb_cc_list[i].ul_sched_result.pusch[j].dci.rnti == rnti) { + for (const auto& cc : enb_cc_list) { + for (uint32_t j = 0; j < cc.ul_sched_result.nof_dci_elems; ++j) { + if (cc.ul_sched_result.pusch[j].dci.rnti == rnti) { return true; } } @@ -63,9 +63,9 @@ bool sf_sched_result::is_ul_alloc(uint16_t rnti) const } bool sf_sched_result::is_dl_alloc(uint16_t rnti) const { - for (uint32_t i = 0; i < enb_cc_list.size(); ++i) { - for (uint32_t j = 0; j < enb_cc_list[i].dl_sched_result.nof_data_elems; ++j) { - if (enb_cc_list[i].dl_sched_result.data[j].dci.rnti == rnti) { + for (const auto& cc : enb_cc_list) { + for (uint32_t j = 0; j < cc.dl_sched_result.nof_data_elems; ++j) { + if (cc.dl_sched_result.data[j].dci.rnti == rnti) { return true; } } @@ -456,7 +456,7 @@ alloc_outcome_t sf_grid_t::alloc_dl_data(sched_ue* user, const rbgmask_t& user_m { srslte_dci_format_t dci_format = user->get_dci_format(); uint32_t nof_bits = srslte_dci_format_sizeof(&cc_cfg->cfg.cell, nullptr, nullptr, dci_format); - uint32_t aggr_idx = user->find_ue_carrier(cc_cfg->enb_cc_idx)->get_aggr_level(nof_bits); + uint32_t aggr_idx = user->get_aggr_level(cc_cfg->enb_cc_idx, nof_bits); alloc_outcome_t ret = alloc_dl(aggr_idx, alloc_type_t::DL_DATA, user_mask, user); return ret; @@ -477,7 +477,7 @@ alloc_outcome_t sf_grid_t::alloc_ul_data(sched_ue* user, prb_interval alloc, boo // Generate PDCCH except for RAR and non-adaptive retx if (needs_pdcch) { uint32_t nof_bits = srslte_dci_format_sizeof(&cc_cfg->cfg.cell, nullptr, nullptr, SRSLTE_DCI_FORMAT0); - uint32_t aggr_idx = user->find_ue_carrier(cc_cfg->enb_cc_idx)->get_aggr_level(nof_bits); + uint32_t aggr_idx = user->get_aggr_level(cc_cfg->enb_cc_idx, nof_bits); if (not pdcch_alloc.alloc_dci(alloc_type_t::UL_DATA, aggr_idx, user)) { if (log_h->get_level() == srslte::LOG_LEVEL_DEBUG) { log_h->debug("No space in PDCCH for rnti=0x%x UL tx. Current PDCCH allocation: %s\n", diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index 9215f0a0b..f962d25cc 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -104,7 +104,7 @@ void sched_ue::init(uint16_t rnti_, const std::vector& cell rnti = rnti_; cells.reserve(cell_list_params_.size()); for (auto& c : cell_list_params_) { - cells.emplace_back(rnti_, c); + cells.emplace_back(rnti_, c, current_tti); } Info("SCHED: Added user rnti=0x%x\n", rnti); } @@ -149,10 +149,10 @@ void sched_ue::set_cfg(const ue_cfg_t& cfg_) if (ue_idx >= prev_supported_cc_list.size()) { // New carrier needs to be added - carriers.emplace_back(cfg, cells[cc_cfg.enb_cc_idx], rnti, ue_idx, current_tti); + carriers.emplace_back(cfg, cells[cc_cfg.enb_cc_idx], rnti, ue_idx); } else if (cc_cfg.enb_cc_idx != prev_supported_cc_list[ue_idx].enb_cc_idx) { // One carrier was added in the place of another - carriers[ue_idx] = cc_sched_ue{cfg, cells[cc_cfg.enb_cc_idx], rnti, ue_idx, current_tti}; + carriers[ue_idx] = cc_sched_ue{cfg, cells[cc_cfg.enb_cc_idx], rnti, ue_idx}; if (ue_idx == 0) { log_h->info("SCHED: rnti=0x%x PCell is now enb_cc_idx=%d.\n", rnti, cc_cfg.enb_cc_idx); } @@ -160,8 +160,8 @@ void sched_ue::set_cfg(const ue_cfg_t& cfg_) // The SCell internal configuration may have changed carriers[ue_idx].set_cfg(cfg); } - scell_activation_state_changed |= ue_idx > 0 and (carriers[ue_idx].cc_state() == cc_st::activating or - carriers[ue_idx].cc_state() == cc_st::deactivating); + scell_activation_state_changed |= ue_idx > 0 and (cells[cc_cfg.enb_cc_idx].cc_state() == cc_st::activating or + cells[cc_cfg.enb_cc_idx].cc_state() == cc_st::deactivating); } if (scell_activation_state_changed) { lch_handler.pending_ces.emplace_back(srslte::dl_sch_lcid::SCELL_ACTIVATION); @@ -222,8 +222,10 @@ void sched_ue::rem_bearer(uint32_t lc_id) void sched_ue::phy_config_enabled(tti_point tti_rx, bool enabled) { - for (cc_sched_ue& c : carriers) { - c.dl_cqi_tti_rx = tti_rx; + for (sched_ue_cell& c : cells) { + if (c.configured()) { + c.dl_cqi_tti_rx = tti_rx; + } } phy_config_dedicated_enabled = enabled; } @@ -345,9 +347,8 @@ bool sched_ue::pusch_enabled(tti_point tti_rx, uint32_t enb_cc_idx, bool needs_p int sched_ue::set_ack_info(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack) { - int tbs_acked = -1; - cc_sched_ue* c = find_ue_carrier(enb_cc_idx); - if (c != nullptr and c->cc_state() != cc_st::idle) { + int tbs_acked = -1; + if (cells[enb_cc_idx].cc_state() != cc_st::idle) { std::pair p2 = cells[enb_cc_idx].harq_ent.set_ack_info(tti_rx, tb_idx, ack); tbs_acked = p2.second; if (tbs_acked > 0) { @@ -364,8 +365,7 @@ int sched_ue::set_ack_info(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t tb_id void sched_ue::set_ul_crc(tti_point tti_rx, uint32_t enb_cc_idx, bool crc_res) { - cc_sched_ue* c = find_ue_carrier(enb_cc_idx); - if (c != nullptr and c->cc_state() != cc_st::idle) { + if (cells[enb_cc_idx].cc_state() != cc_st::idle) { int ret = cells[enb_cc_idx].harq_ent.set_ul_crc(tti_rx, 0, crc_res); if (ret < 0) { log_h->warning("Received UL CRC for invalid tti_rx=%d\n", (int)tti_rx.to_uint()); @@ -377,10 +377,9 @@ void sched_ue::set_ul_crc(tti_point tti_rx, uint32_t enb_cc_idx, bool crc_res) void sched_ue::set_dl_ri(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t ri) { - cc_sched_ue* c = find_ue_carrier(enb_cc_idx); - if (c != nullptr and c->cc_state() != cc_st::idle) { - c->dl_ri = ri; - c->dl_ri_tti_rx = tti_rx; + if (cells[enb_cc_idx].cc_state() != cc_st::idle) { + cells[enb_cc_idx].dl_ri = ri; + cells[enb_cc_idx].dl_ri_tti_rx = tti_rx; } else { log_h->warning("Received DL RI for invalid cell index %d\n", enb_cc_idx); } @@ -388,10 +387,9 @@ void sched_ue::set_dl_ri(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t ri) void sched_ue::set_dl_pmi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t pmi) { - cc_sched_ue* c = find_ue_carrier(enb_cc_idx); - if (c != nullptr and c->cc_state() != cc_st::idle) { - c->dl_pmi = pmi; - c->dl_pmi_tti_rx = tti_rx; + if (cells[enb_cc_idx].cc_state() != cc_st::idle) { + cells[enb_cc_idx].dl_pmi = pmi; + cells[enb_cc_idx].dl_pmi_tti_rx = tti_rx; } else { log_h->warning("Received DL PMI for invalid cell index %d\n", enb_cc_idx); } @@ -399,9 +397,8 @@ void sched_ue::set_dl_pmi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t pmi) void sched_ue::set_dl_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi) { - cc_sched_ue* c = find_ue_carrier(enb_cc_idx); - if (c != nullptr and c->cc_state() != cc_st::idle) { - c->set_dl_cqi(tti_rx, cqi); + if (cells[enb_cc_idx].cc_state() != cc_st::idle) { + cells[enb_cc_idx].set_dl_cqi(tti_rx, cqi); } else { log_h->warning("Received DL CQI for invalid enb cell index %d\n", enb_cc_idx); } @@ -409,11 +406,10 @@ void sched_ue::set_dl_cqi(tti_point tti_rx, uint32_t enb_cc_idx, uint32_t cqi) void sched_ue::set_ul_snr(tti_point tti_rx, uint32_t enb_cc_idx, float snr, uint32_t ul_ch_code) { - cc_sched_ue* c = find_ue_carrier(enb_cc_idx); - if (c != nullptr and c->cc_state() != cc_st::idle) { + if (cells[enb_cc_idx].cc_state() != cc_st::idle) { cells[enb_cc_idx].tpc_fsm.set_snr(snr, ul_ch_code); - c->ul_cqi = srslte_cqi_from_snr(snr); - c->ul_cqi_tti_rx = tti_rx; + cells[enb_cc_idx].ul_cqi = srslte_cqi_from_snr(snr); + cells[enb_cc_idx].ul_cqi_tti_rx = tti_rx; } else { log_h->warning("Received SNR info for invalid cell index %d\n", enb_cc_idx); } @@ -606,7 +602,7 @@ int sched_ue::generate_format2a(uint32_t pid, bool no_retx = true; - if (carriers[ue_cc_idx].dl_ri == 0) { + if (cells[enb_cc_idx].dl_ri == 0) { if (h->is_empty(1)) { /* One layer, tb1 buffer is empty, send tb0 only */ tb_en[0] = true; @@ -677,12 +673,11 @@ int sched_ue::generate_format2(uint32_t pid, int ret = generate_format2a(pid, data, tti_tx_dl, enb_cc_idx, cfi, user_mask); /* Compute precoding information */ - uint32_t ue_cc_idx = enb_to_ue_cc_idx(enb_cc_idx); - data->dci.format = SRSLTE_DCI_FORMAT2; + data->dci.format = SRSLTE_DCI_FORMAT2; if ((SRSLTE_DCI_IS_TB_EN(data->dci.tb[0]) + SRSLTE_DCI_IS_TB_EN(data->dci.tb[1])) == 1) { - data->dci.pinfo = (uint8_t)(carriers[ue_cc_idx].dl_pmi + 1) % (uint8_t)5; + data->dci.pinfo = (uint8_t)(cells[enb_cc_idx].dl_pmi + 1) % (uint8_t)5; } else { - data->dci.pinfo = (uint8_t)(carriers[ue_cc_idx].dl_pmi & 1u); + data->dci.pinfo = (uint8_t)(cells[enb_cc_idx].dl_pmi & 1u); } return ret; @@ -708,7 +703,7 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, dci->location = dci_pos; tbs_info tbinfo; - tbinfo.mcs = (explicit_mcs >= 0) ? explicit_mcs : carriers[ue_cc_idx].fixed_mcs_ul; + tbinfo.mcs = (explicit_mcs >= 0) ? explicit_mcs : cells[enb_cc_idx].fixed_mcs_ul; tbinfo.tbs_bytes = 0; bool is_newtx = h->is_empty(0); @@ -819,7 +814,7 @@ bool sched_ue::needs_cqi(uint32_t tti, uint32_t enb_cc_idx, bool will_send) bool ret = false; if (phy_config_dedicated_enabled && cfg.supported_cc_list[0].aperiodic_cqi_period && lch_handler.has_pending_dl_txs()) { - uint32_t interval = srslte_tti_interval(tti, carriers[enb_to_ue_cc_idx(enb_cc_idx)].dl_cqi_tti_rx.to_uint()); + uint32_t interval = srslte_tti_interval(tti, cells[enb_cc_idx].dl_cqi_tti_rx.to_uint()); bool needscqi = interval >= cfg.supported_cc_list[0].aperiodic_cqi_period; if (needscqi) { uint32_t interval_sent = srslte_tti_interval(tti, cqi_request_tti); @@ -854,7 +849,7 @@ rbg_interval sched_ue::get_required_dl_rbgs(uint32_t enb_cc_idx) // Cannot fit allocation in given PRBs log_h->error("SCHED: DL CQI=%d does now allow fitting %d non-segmentable DL tx bytes into the cell bandwidth. " "Consider increasing initial CQI value.\n", - carriers[ue_cc_idx].dl_cqi, + cells[enb_cc_idx].dl_cqi, req_bytes.start()); return {cellparams->nof_prb(), cellparams->nof_prb()}; } @@ -892,7 +887,7 @@ srslte::interval sched_ue::get_requested_dl_bytes(uint32_t enb_cc_idx) log_h->error("SRB0 must always be activated for DL\n"); return {}; } - if (carriers[ue_cc_idx].cc_state() != cc_st::active) { + if (cells[enb_cc_idx].cc_state() != cc_st::active) { return {}; } @@ -941,10 +936,10 @@ uint32_t sched_ue::get_pending_dl_rlc_data() const uint32_t sched_ue::get_expected_dl_bitrate(uint32_t enb_cc_idx, int nof_rbgs) const { - const cc_sched_ue* cc = &carriers[cells.at(enb_cc_idx).get_ue_cc_idx()]; - uint32_t nof_re = cc->get_cell_cfg()->get_dl_lb_nof_re( - to_tx_dl(current_tti), count_prb_per_tb_approx(nof_rbgs, cc->get_cell_cfg()->nof_prb())); - float max_coderate = srslte_cqi_to_coderate(std::min(cc->dl_cqi + 1u, 15u), cfg.use_tbs_index_alt); + auto& cc = cells[enb_cc_idx]; + uint32_t nof_re = + cc.cell_cfg->get_dl_lb_nof_re(to_tx_dl(current_tti), count_prb_per_tb_approx(nof_rbgs, cc.cell_cfg->nof_prb())); + float max_coderate = srslte_cqi_to_coderate(std::min(cc.dl_cqi + 1u, 15u), cfg.use_tbs_index_alt); // Inverse of srslte_coderate(tbs, nof_re) uint32_t tbs = max_coderate * nof_re - 24; @@ -953,13 +948,12 @@ uint32_t sched_ue::get_expected_dl_bitrate(uint32_t enb_cc_idx, int nof_rbgs) co uint32_t sched_ue::get_expected_ul_bitrate(uint32_t enb_cc_idx, int nof_prbs) const { - const cc_sched_ue* cc = &carriers[cells.at(enb_cc_idx).get_ue_cc_idx()]; - uint32_t nof_prbs_alloc = nof_prbs < 0 ? cell.nof_prb : nof_prbs; + uint32_t nof_prbs_alloc = nof_prbs < 0 ? cell.nof_prb : nof_prbs; uint32_t N_srs = 0; uint32_t nof_symb = 2 * (SRSLTE_CP_NSYMB(cell.cp) - 1) - N_srs; uint32_t nof_re = nof_symb * nof_prbs_alloc * SRSLTE_NRE; - float max_coderate = srslte_cqi_to_coderate(std::min(cc->ul_cqi + 1u, 15u), false); + float max_coderate = srslte_cqi_to_coderate(std::min(cells[enb_cc_idx].ul_cqi + 1u, 15u), false); // Inverse of srslte_coderate(tbs, nof_re) uint32_t tbs = max_coderate * nof_re - 24; @@ -992,7 +986,6 @@ uint32_t sched_ue::get_pending_ul_old_data() uint32_t sched_ue::get_pending_ul_data_total(tti_point tti_tx_ul, int this_enb_cc_idx) { static constexpr uint32_t lbsr_size = 4, sbsr_size = 2; - uint32_t this_ue_cc_idx = enb_to_ue_cc_idx(this_enb_cc_idx); // Note: If there are no active bearers, scheduling requests are also ignored. uint32_t pending_data = 0; @@ -1013,14 +1006,16 @@ uint32_t sched_ue::get_pending_ul_data_total(tti_point tti_tx_ul, int this_enb_c if (is_sr_triggered() and this_enb_cc_idx >= 0) { // Check if this_cc_idx is the carrier with highest CQI uint32_t max_cqi = 0, max_cc_idx = 0; - for (uint32_t cc_idx = 0; cc_idx < carriers.size(); ++cc_idx) { - uint32_t sum_cqi = carriers[cc_idx].dl_cqi + carriers[cc_idx].ul_cqi; - if (carriers[cc_idx].cc_state() == cc_st::active and sum_cqi > max_cqi) { - max_cqi = sum_cqi; - max_cc_idx = cc_idx; + for (uint32_t cc = 0; cc < cells.size(); ++cc) { + if (cells[cc].configured()) { + uint32_t sum_cqi = cells[cc].dl_cqi + cells[cc].ul_cqi; + if (cells[cc].cc_state() == cc_st::active and sum_cqi > max_cqi) { + max_cqi = sum_cqi; + max_cc_idx = cc; + } } } - if (max_cc_idx == this_ue_cc_idx) { + if ((int)max_cc_idx == this_enb_cc_idx) { return 512; } } @@ -1064,8 +1059,7 @@ bool sched_ue::is_sr_triggered() /* Gets HARQ process with oldest pending retx */ dl_harq_proc* sched_ue::get_pending_dl_harq(tti_point tti_tx_dl, uint32_t enb_cc_idx) { - uint32_t ue_cc_idx = enb_to_ue_cc_idx(enb_cc_idx); - if (cells[enb_cc_idx].configured() and carriers[ue_cc_idx].cc_state() == cc_st::active) { + if (cells[enb_cc_idx].cc_state() == cc_st::active) { return cells[enb_cc_idx].harq_ent.get_pending_dl_harq(tti_tx_dl); } return nullptr; @@ -1073,8 +1067,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(tti_point tti_tx_dl, uint32_t enb_cc dl_harq_proc* sched_ue::get_empty_dl_harq(tti_point tti_tx_dl, uint32_t enb_cc_idx) { - uint32_t ue_cc_idx = enb_to_ue_cc_idx(enb_cc_idx); - if (cells[enb_cc_idx].configured() and carriers[ue_cc_idx].cc_state() == cc_st::active) { + if (cells[enb_cc_idx].cc_state() == cc_st::active) { return cells[enb_cc_idx].harq_ent.get_empty_dl_harq(tti_tx_dl); } return nullptr; @@ -1082,8 +1075,7 @@ dl_harq_proc* sched_ue::get_empty_dl_harq(tti_point tti_tx_dl, uint32_t enb_cc_i ul_harq_proc* sched_ue::get_ul_harq(tti_point tti_tx_ul, uint32_t enb_cc_idx) { - uint32_t ue_cc_idx = enb_to_ue_cc_idx(enb_cc_idx); - if (cells[enb_cc_idx].configured() and carriers[ue_cc_idx].cc_state() == cc_st::active) { + if (cells[enb_cc_idx].cc_state() == cc_st::active) { return cells[enb_cc_idx].harq_ent.get_ul_harq(tti_tx_ul); } return nullptr; @@ -1102,7 +1094,7 @@ std::pair sched_ue::get_active_cell_index(uint32_t enb_cc_idx) c [enb_cc_idx](const sched_interface::ue_cfg_t::cc_cfg_t& u) { return u.enb_cc_idx == enb_cc_idx and u.active; }); if (it != cfg.supported_cc_list.end()) { uint32_t ue_cc_idx = std::distance(cfg.supported_cc_list.begin(), it); - return {carriers[ue_cc_idx].cc_state() == cc_st::active, ue_cc_idx}; + return {cells[enb_cc_idx].cc_state() == cc_st::active, ue_cc_idx}; } return {false, std::numeric_limits::max()}; } @@ -1115,12 +1107,8 @@ uint32_t sched_ue::get_aggr_level(uint32_t enb_cc_idx, uint32_t nof_bits) void sched_ue::finish_tti(tti_point tti_rx, uint32_t enb_cc_idx) { - cc_sched_ue* c = find_ue_carrier(enb_cc_idx); - - if (c != nullptr) { - // Check that scell state needs to change - c->finish_tti(tti_rx); - } + // Check that scell state needs to change + cells[enb_cc_idx].finish_tti(tti_rx); } srslte_dci_format_t sched_ue::get_dci_format() @@ -1162,17 +1150,16 @@ const sched_dci_cce_t* sched_ue::get_locations(uint32_t enb_cc_idx, uint32_t cfi } } -cc_sched_ue* sched_ue::find_ue_carrier(uint32_t enb_cc_idx) +sched_ue_cell* sched_ue::find_ue_carrier(uint32_t enb_cc_idx) { - int ue_cc_idx = enb_to_ue_cc_idx(enb_cc_idx); - return ue_cc_idx >= 0 ? &carriers[ue_cc_idx] : nullptr; + return cells[enb_cc_idx].configured() ? &cells[enb_cc_idx] : nullptr; } std::bitset sched_ue::scell_activation_mask() const { std::bitset ret{0}; for (size_t i = 1; i < carriers.size(); ++i) { - if (carriers[i].cc_state() == cc_st::active) { + if (cells[carriers[i].get_cell_cfg()->enb_cc_idx].cc_state() == cc_st::active) { ret[i] = true; } } @@ -1207,13 +1194,13 @@ int cc_sched_ue::cqi_to_tbs(uint32_t nof_prb, uint32_t nof_re, bool is_ul, uint3 int max_mcs; float max_coderate; if (is_ul) { - max_mcs = max_mcs_ul; + max_mcs = cell_ue->max_mcs_ul; max_Qm = cfg->support_ul64qam == ul64qam_cap::enabled ? 6 : 4; - max_coderate = srslte_cqi_to_coderate(std::min(ul_cqi + 1u, 15u), false); + max_coderate = srslte_cqi_to_coderate(std::min(cell_ue->ul_cqi + 1u, 15u), false); } else { - max_mcs = max_mcs_dl; + max_mcs = cell_ue->max_mcs_dl; max_Qm = cfg->use_tbs_index_alt ? 8 : 6; - max_coderate = srslte_cqi_to_coderate(std::min(dl_cqi + 1u, 15u), cfg->use_tbs_index_alt); + max_coderate = srslte_cqi_to_coderate(std::min(cell_ue->dl_cqi + 1u, 15u), cfg->use_tbs_index_alt); } // function with sign-flip at solution @@ -1252,96 +1239,26 @@ int cc_sched_ue::cqi_to_tbs(uint32_t nof_prb, uint32_t nof_re, bool is_ul, uint3 cc_sched_ue::cc_sched_ue(const sched_interface::ue_cfg_t& cfg_, sched_ue_cell& cell_ue_, uint16_t rnti_, - uint32_t ue_cc_idx_, - tti_point current_tti) : - cell_ue(&cell_ue_), rnti(rnti_), log_h(srslte::logmap::get("MAC")), ue_cc_idx(ue_cc_idx_), last_tti(current_tti) + uint32_t ue_cc_idx_) : + cell_ue(&cell_ue_), rnti(rnti_), log_h(srslte::logmap::get("MAC")), ue_cc_idx(ue_cc_idx_) { - dl_cqi_rx = false; - dl_cqi = (ue_cc_idx == 0) ? cell_ue_.cell_cfg->cfg.initial_dl_cqi : 0; set_cfg(cfg_); - - max_aggr_level = cell_ue->cell_cfg->sched_cfg->max_aggr_level >= 0 ? cell_ue->cell_cfg->sched_cfg->max_aggr_level : 3; - - // set fixed mcs - fixed_mcs_dl = cell_ue->cell_cfg->sched_cfg->pdsch_mcs; - fixed_mcs_ul = cell_ue->cell_cfg->sched_cfg->pusch_mcs; } void cc_sched_ue::reset() { - dl_ri = 0; - dl_ri_tti_rx = tti_point{}; - dl_pmi = 0; - dl_pmi_tti_rx = tti_point{}; - dl_cqi = 1; - dl_cqi_tti_rx = tti_point{}; - ul_cqi = 1; - ul_cqi_tti_rx = tti_point{}; cell_ue->reset(); } void cc_sched_ue::set_cfg(const sched_interface::ue_cfg_t& cfg_) { - cfg = &cfg_; - cfg_tti = last_tti; - - // set max mcs - max_mcs_ul = get_cell_cfg()->sched_cfg->pusch_max_mcs >= 0 ? get_cell_cfg()->sched_cfg->pusch_max_mcs : 28u; - if (get_cell_cfg()->cfg.enable_64qam) { - const uint32_t max_64qam_mcs[] = {20, 24, 28}; - max_mcs_ul = std::min(max_mcs_ul, max_64qam_mcs[(size_t)cfg->support_ul64qam]); - } - max_mcs_dl = - get_cell_cfg()->sched_cfg->pdsch_max_mcs >= 0 ? std::min(get_cell_cfg()->sched_cfg->pdsch_max_mcs, 28) : 28u; - if (cfg->use_tbs_index_alt) { - max_mcs_dl = std::min(max_mcs_dl, 27u); - } - - if (ue_cc_idx == 0) { - // PCell is always active - cc_state_ = cc_st::active; - } else { - switch (cc_state()) { - case cc_st::activating: - case cc_st::active: - if (not cfg->supported_cc_list[ue_cc_idx].active) { - cc_state_ = cc_st::deactivating; - log_h->info("SCHED: Deactivating rnti=0x%x, SCellIndex=%d...\n", rnti, ue_cc_idx); - } - break; - case cc_st::deactivating: - case cc_st::idle: - if (cfg->supported_cc_list[ue_cc_idx].active) { - cc_state_ = cc_st::activating; - dl_cqi_rx = false; - dl_cqi = 0; - log_h->info("SCHED: Activating rnti=0x%x, SCellIndex=%d...\n", rnti, ue_cc_idx); - } - break; - default: - break; - } - } -} - -void cc_sched_ue::finish_tti(tti_point tti_rx) -{ - last_tti = tti_rx; - cell_ue->finish_tti(tti_rx); - - // Check if cell state needs to be updated - if (ue_cc_idx > 0 and cc_state_ == cc_st::deactivating) { - // wait for all ACKs to be received before completely deactivating SCell - if (last_tti > to_tx_dl_ack(cfg_tti)) { - cc_state_ = cc_st::idle; - reset(); - } - } + cfg = &cfg_; } uint32_t cc_sched_ue::get_aggr_level(uint32_t nof_bits) { - return srsenb::get_aggr_level(nof_bits, dl_cqi, max_aggr_level, get_cell_cfg()->nof_prb(), cfg->use_tbs_index_alt); + return srsenb::get_aggr_level( + nof_bits, cell_ue->dl_cqi, cell_ue->max_aggr_level, get_cell_cfg()->nof_prb(), cfg->use_tbs_index_alt); } /* In this scheduler we tend to use all the available bandwidth and select the MCS @@ -1367,8 +1284,9 @@ tbs_info cc_sched_ue::alloc_tbs(uint32_t nof_prb, uint32_t nof_re, uint32_t req_ if (req_mcs >= 0 and req_mcs < (int)sel_mcs) { uint32_t max_Qm = (is_ul) ? (cfg->support_ul64qam == sched_interface::ue_cfg_t::ul64qam_cap::enabled ? 6 : 4) : (cfg->use_tbs_index_alt ? 8 : 6); - float max_coderate = (is_ul) ? srslte_cqi_to_coderate(std::min(ul_cqi + 1u, 15u), false) - : srslte_cqi_to_coderate(std::min(dl_cqi + 1u, 15u), cfg->use_tbs_index_alt); + float max_coderate = (is_ul) + ? srslte_cqi_to_coderate(std::min(cell_ue->ul_cqi + 1u, 15u), false) + : srslte_cqi_to_coderate(std::min(cell_ue->dl_cqi + 1u, 15u), cfg->use_tbs_index_alt); if (diff_coderate_maxcoderate(req_mcs, nof_prb, nof_re, max_Qm, max_coderate, cfg->use_tbs_index_alt, is_ul) < 0) { sel_mcs = req_mcs; @@ -1395,13 +1313,13 @@ tbs_info cc_sched_ue::alloc_tbs_dl(uint32_t nof_prb, uint32_t nof_re, uint32_t r tbs_info ret; // Use a higher MCS for the Msg4 to fit in the 6 PRB case - if (fixed_mcs_dl < 0 or not dl_cqi_rx) { + if (cell_ue->fixed_mcs_dl < 0 or not cell_ue->dl_cqi_rx) { // Dynamic MCS ret = alloc_tbs(nof_prb, nof_re, req_bytes, false); } else { // Fixed MCS - ret.mcs = fixed_mcs_dl; - ret.tbs_bytes = get_tbs_bytes((uint32_t)fixed_mcs_dl, nof_prb, cfg->use_tbs_index_alt, false); + ret.mcs = cell_ue->fixed_mcs_dl; + ret.tbs_bytes = get_tbs_bytes((uint32_t)cell_ue->fixed_mcs_dl, nof_prb, cfg->use_tbs_index_alt, false); } return ret; } @@ -1409,7 +1327,7 @@ tbs_info cc_sched_ue::alloc_tbs_dl(uint32_t nof_prb, uint32_t nof_re, uint32_t r tbs_info cc_sched_ue::alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int explicit_mcs) { tbs_info ret; - int mcs = explicit_mcs >= 0 ? explicit_mcs : fixed_mcs_ul; + int mcs = explicit_mcs >= 0 ? explicit_mcs : cell_ue->fixed_mcs_ul; if (mcs < 0) { // Dynamic MCS @@ -1461,16 +1379,4 @@ uint32_t cc_sched_ue::get_required_prb_ul(uint32_t req_bytes) return req_prbs; } -void cc_sched_ue::set_dl_cqi(tti_point tti_rx, uint32_t dl_cqi_) -{ - dl_cqi = dl_cqi_; - dl_cqi_tti_rx = tti_rx; - dl_cqi_rx = dl_cqi_rx or dl_cqi > 0; - if (ue_cc_idx > 0 and cc_state_ == cc_st::activating and dl_cqi_rx) { - // Wait for SCell to receive a positive CQI before activating it - cc_state_ = cc_st::active; - log_h->info("SCHED: SCell index=%d is now active\n", ue_cc_idx); - } -} - } // namespace srsenb diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc index 3a6b1da7c..7614db3c8 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_ue_cell.cc @@ -20,25 +20,100 @@ namespace srsenb { * sched_ue_cell *******************************************************/ -sched_ue_cell::sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg_) : +sched_ue_cell::sched_ue_cell(uint16_t rnti_, const sched_cell_params_t& cell_cfg_, tti_point current_tti_) : + rnti(rnti_), cell_cfg(&cell_cfg_), dci_locations(generate_cce_location_table(rnti_, cell_cfg_)), harq_ent(SCHED_MAX_HARQ_PROC, SCHED_MAX_HARQ_PROC), - tpc_fsm(cell_cfg->nof_prb(), cell_cfg->cfg.target_ul_sinr, cell_cfg->cfg.enable_phr_handling) -{} + tpc_fsm(cell_cfg->nof_prb(), cell_cfg->cfg.target_ul_sinr, cell_cfg->cfg.enable_phr_handling), + fixed_mcs_dl(cell_cfg_.sched_cfg->pdsch_mcs), + fixed_mcs_ul(cell_cfg_.sched_cfg->pusch_mcs), + current_tti(current_tti_) +{ + max_aggr_level = cell_cfg->sched_cfg->max_aggr_level >= 0 ? cell_cfg->sched_cfg->max_aggr_level : 3; +} void sched_ue_cell::set_ue_cfg(const sched_interface::ue_cfg_t& ue_cfg_) { - ue_cfg = &ue_cfg_; + cfg_tti = current_tti; + ue_cfg = &ue_cfg_; + ue_cc_idx = -1; for (size_t i = 0; i < ue_cfg_.supported_cc_list.size(); ++i) { if (ue_cfg_.supported_cc_list[i].enb_cc_idx == cell_cfg->enb_cc_idx) { ue_cc_idx = i; } } + + // set max mcs + max_mcs_ul = cell_cfg->sched_cfg->pusch_max_mcs >= 0 ? cell_cfg->sched_cfg->pusch_max_mcs : 28u; + if (cell_cfg->cfg.enable_64qam) { + const uint32_t max_64qam_mcs[] = {20, 24, 28}; + max_mcs_ul = std::min(max_mcs_ul, max_64qam_mcs[(size_t)ue_cfg->support_ul64qam]); + } + max_mcs_dl = cell_cfg->sched_cfg->pdsch_max_mcs >= 0 ? std::min(cell_cfg->sched_cfg->pdsch_max_mcs, 28) : 28u; + if (ue_cfg->use_tbs_index_alt) { + max_mcs_dl = std::min(max_mcs_dl, 27u); + } + + // Update carrier state + if (ue_cc_idx == 0) { + if (cc_state() == cc_st::idle) { + reset(); + // PCell is always active + cc_state_ = cc_st::active; + + // set initial DL CQI + dl_cqi = cell_cfg->cfg.initial_dl_cqi; + } + } else { + // SCell case + switch (cc_state()) { + case cc_st::activating: + case cc_st::active: + if (not ue_cfg->supported_cc_list[ue_cc_idx].active) { + cc_state_ = cc_st::deactivating; + log_h->info("SCHED: Deactivating rnti=0x%x, SCellIndex=%d...\n", rnti, ue_cc_idx); + } + break; + case cc_st::deactivating: + case cc_st::idle: + if (ue_cfg->supported_cc_list[ue_cc_idx].active) { + reset(); + cc_state_ = cc_st::activating; + dl_cqi = 0; + log_h->info("SCHED: Activating rnti=0x%x, SCellIndex=%d...\n", rnti, ue_cc_idx); + } + break; + default: + break; + } + } +} + +void sched_ue_cell::new_tti(tti_point tti_rx) +{ + current_tti = tti_rx; + + // Check if cell state needs to be updated + if (ue_cc_idx > 0 and cc_state_ == cc_st::deactivating) { + // wait for all ACKs to be received before completely deactivating SCell + if (current_tti > to_tx_dl_ack(cfg_tti)) { + cc_state_ = cc_st::idle; + } + } } void sched_ue_cell::reset() { + dl_ri = 0; + dl_ri_tti_rx = tti_point{}; + dl_pmi = 0; + dl_pmi_tti_rx = tti_point{}; + dl_cqi = 1; + dl_cqi_tti_rx = tti_point{}; + dl_cqi_rx = false; + ul_cqi = 1; + ul_cqi_tti_rx = tti_point{}; harq_ent.reset(); } @@ -48,4 +123,16 @@ void sched_ue_cell::finish_tti(tti_point tti_rx) harq_ent.reset_pending_data(tti_rx); } +void sched_ue_cell::set_dl_cqi(tti_point tti_rx, uint32_t dl_cqi_) +{ + dl_cqi = dl_cqi_; + dl_cqi_tti_rx = tti_rx; + dl_cqi_rx = dl_cqi_rx or dl_cqi > 0; + if (ue_cc_idx > 0 and cc_state_ == cc_st::activating and dl_cqi_rx) { + // Wait for SCell to receive a positive CQI before activating it + cc_state_ = cc_st::active; + log_h->info("SCHED: SCell index=%d is now active\n", ue_cc_idx); + } +} + } // namespace srsenb