From 20b69fb22e8bfb70fe1b4c10150ecfbda7e8ca77 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 11 Aug 2020 17:06:12 +0100 Subject: [PATCH] substitution of ul_alloc_t for prb_interval --- lib/include/srslte/adt/interval.h | 127 +++++++++++++++++++++ lib/test/adt/CMakeLists.txt | 4 + lib/test/adt/interval_test.cc | 72 ++++++++++++ srsenb/hdr/stack/mac/scheduler_common.h | 26 ++--- srsenb/hdr/stack/mac/scheduler_grid.h | 44 ++++---- srsenb/hdr/stack/mac/scheduler_harq.h | 29 ++--- srsenb/hdr/stack/mac/scheduler_metric.h | 2 +- srsenb/hdr/stack/mac/scheduler_ue.h | 14 +-- srsenb/src/stack/mac/scheduler.cc | 16 +-- srsenb/src/stack/mac/scheduler_grid.cc | 134 ++++++++++------------- srsenb/src/stack/mac/scheduler_harq.cc | 8 +- srsenb/src/stack/mac/scheduler_metric.cc | 41 ++++--- srsenb/src/stack/mac/scheduler_ue.cc | 42 +++---- srsenb/test/mac/scheduler_test_common.cc | 27 ++--- 14 files changed, 373 insertions(+), 213 deletions(-) create mode 100644 lib/include/srslte/adt/interval.h create mode 100644 lib/test/adt/interval_test.cc diff --git a/lib/include/srslte/adt/interval.h b/lib/include/srslte/adt/interval.h new file mode 100644 index 000000000..8e675906f --- /dev/null +++ b/lib/include/srslte/adt/interval.h @@ -0,0 +1,127 @@ +/* + * Copyright 2013-2020 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 SRSLTE_INTERVAL_H +#define SRSLTE_INTERVAL_H + +#include + +namespace srslte { + +template +class interval +{ +public: + T start; + T stop; + + interval() : start(T{}), stop(T{}) {} + interval(const T& start_, const T& stop_) : start(start_), stop(stop_) {} + + bool is_empty() const { return stop <= start; } + + T length() const { return stop - start; } + + void set_length(const T& len) { stop = start + len; } + + void add_offset(int offset) + { + start += offset; + stop += offset; + } + + void shift_to(int new_start) + { + stop = new_start + length(); + start = new_start; + } + + bool overlaps(const interval& other) const { return start < other.stop and other.start < stop; } + + bool contains(const T& point) const { return start <= point and point < stop; } + + std::string to_string() const + { + std::string s = "[" + std::to_string(start) + ", " + std::to_string(stop) + ")"; + return s; + } +}; + +template +bool operator==(const interval& lhs, const interval& rhs) +{ + return lhs.start == rhs.start and lhs.stop == rhs.stop; +} + +template +bool operator!=(const interval& lhs, const interval& rhs) +{ + return not(lhs == rhs); +} + +template +bool operator<(const interval& lhs, const interval& rhs) +{ + return lhs.start < rhs.start or (lhs.start == rhs.start and lhs.stop < rhs.stop); +} + +//! Union of intervals +template +interval operator|(const interval& lhs, const interval& rhs) +{ + if (not lhs.overlaps(rhs)) { + return interval{}; + } + return {std::min(lhs.start, rhs.start), std::max(lhs.stop, rhs.stop)}; +} + +template +interval make_union(const interval& lhs, const interval& rhs) +{ + return lhs | rhs; +} + +//! Intersection of intervals +template +interval operator&(const interval& lhs, const interval& rhs) +{ + if (not lhs.overlaps(rhs)) { + return interval{}; + } + return interval{std::max(lhs.start, rhs.start), std::min(lhs.stop, rhs.stop)}; +} + +template +interval make_intersection(const interval& lhs, const interval& rhs) +{ + return lhs & rhs; +} + +template +std::ostream& operator<<(std::ostream& out, const interval& interv) +{ + out << interv.to_string(); + return out; +} + +} // namespace srslte + +#endif // SRSLTE_INTERVAL_H diff --git a/lib/test/adt/CMakeLists.txt b/lib/test/adt/CMakeLists.txt index eed219eaa..25b575f75 100644 --- a/lib/test/adt/CMakeLists.txt +++ b/lib/test/adt/CMakeLists.txt @@ -37,3 +37,7 @@ add_test(bounded_bitset_test bounded_bitset_test) add_executable(span_test span_test.cc) target_link_libraries(span_test srslte_common) add_test(span_test span_test) + +add_executable(interval_test interval_test.cc) +target_link_libraries(interval_test srslte_common) +add_test(interval_test interval_test) diff --git a/lib/test/adt/interval_test.cc b/lib/test/adt/interval_test.cc new file mode 100644 index 000000000..5cd8e9c59 --- /dev/null +++ b/lib/test/adt/interval_test.cc @@ -0,0 +1,72 @@ +/* + * Copyright 2013-2020 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/. + * + */ + +#include "srslte/adt/interval.h" +#include "srslte/common/test_common.h" + +int test_interval_overlaps() +{ + srslte::interval I{10, 15}, I2{9, 11}, I3{11, 14}, I4{9, 16}, I5{14, 16}, I6{4, 10}, I7{15, 17}; + + TESTASSERT(I.overlaps(I2)); + TESTASSERT(I.overlaps(I3)); + TESTASSERT(I.overlaps(I4)); + TESTASSERT(I.overlaps(I5)); + TESTASSERT(not I.overlaps(I6)); + TESTASSERT(not I.overlaps(I7)); + + return SRSLTE_SUCCESS; +} + +int test_interval_contains() +{ + srslte::interval I{5, 10}; + + TESTASSERT(I.contains(5)); + TESTASSERT(I.contains(6)); + TESTASSERT(I.contains(9)); + TESTASSERT(not I.contains(10)); + TESTASSERT(not I.contains(11)); + TESTASSERT(not I.contains(4)); + + return SRSLTE_SUCCESS; +} + +int test_interval_intersect() +{ + srslte::interval I{5, 10}, I2{3, 6}, I3{9, 12}, I4{10, 13}; + + TESTASSERT(srslte::make_intersection(I, I2) == (I & I2)); + TESTASSERT((I & I2) == srslte::interval(5, 6)); + TESTASSERT((I & I3) == srslte::interval(9, 10)); + TESTASSERT(not(I & I3).is_empty()); + TESTASSERT((I & I4).is_empty()); + + return SRSLTE_SUCCESS; +} + +int main() +{ + TESTASSERT(test_interval_overlaps() == SRSLTE_SUCCESS); + TESTASSERT(test_interval_contains() == SRSLTE_SUCCESS); + TESTASSERT(test_interval_intersect() == SRSLTE_SUCCESS); + return 0; +} diff --git a/srsenb/hdr/stack/mac/scheduler_common.h b/srsenb/hdr/stack/mac/scheduler_common.h index 70ff35503..6ce1f2c26 100644 --- a/srsenb/hdr/stack/mac/scheduler_common.h +++ b/srsenb/hdr/stack/mac/scheduler_common.h @@ -22,6 +22,7 @@ #ifndef SRSLTE_SCHEDULER_COMMON_H #define SRSLTE_SCHEDULER_COMMON_H +#include "srslte/adt/interval.h" #include "srslte/adt/bounded_bitset.h" #include "srslte/interfaces/sched_interface.h" @@ -80,25 +81,18 @@ using rbgmask_t = srslte::bounded_bitset<25, true>; using prbmask_t = srslte::bounded_bitset<100, true>; //! Struct to express a {min,...,max} range of RBGs -struct prb_range_t; -struct rbg_range_t { - uint32_t rbg_min = 0, rbg_max = 0; - rbg_range_t() = default; - rbg_range_t(uint32_t s, uint32_t e) : rbg_min(s), rbg_max(e) {} - uint32_t nof_rbgs() const { return rbg_max - rbg_min; } - - static rbg_range_t prbs_to_rbgs(const prb_range_t& prbs, uint32_t P); +struct prb_interval; +struct rbg_interval : public srslte::interval { + using interval::interval; + static rbg_interval prbs_to_rbgs(const prb_interval& prbs, uint32_t P); }; //! Struct to express a {min,...,max} range of PRBs -struct prb_range_t { - uint32_t prb_min = 0, prb_max = 0; - prb_range_t() = default; - prb_range_t(uint32_t s, uint32_t e) : prb_min(s), prb_max(e) {} - uint32_t nof_prbs() { return prb_max - prb_min; } - - static prb_range_t rbgs_to_prbs(const rbg_range_t& rbgs, uint32_t P); - static prb_range_t riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs = -1); +struct prb_interval : public srslte::interval { + using interval::interval; + + static prb_interval rbgs_to_prbs(const rbg_interval& rbgs, uint32_t P); + static prb_interval riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs = -1); }; /*********************** diff --git a/srsenb/hdr/stack/mac/scheduler_grid.h b/srsenb/hdr/stack/mac/scheduler_grid.h index 804fa8522..90d81b8fd 100644 --- a/srsenb/hdr/stack/mac/scheduler_grid.h +++ b/srsenb/hdr/stack/mac/scheduler_grid.h @@ -160,7 +160,7 @@ class sf_grid_t public: struct dl_ctrl_alloc_t { alloc_outcome_t outcome; - rbg_range_t rbg_range; + rbg_interval rbg_range; }; void init(const sched_cell_params_t& cell_params_); @@ -168,9 +168,9 @@ public: dl_ctrl_alloc_t alloc_dl_ctrl(uint32_t aggr_lvl, alloc_type_t alloc_type); alloc_outcome_t alloc_dl_data(sched_ue* user, const rbgmask_t& user_mask); bool reserve_dl_rbgs(uint32_t start_rbg, uint32_t end_rbg); - alloc_outcome_t alloc_ul_data(sched_ue* user, ul_harq_proc::ul_alloc_t alloc, bool needs_pdcch); + alloc_outcome_t alloc_ul_data(sched_ue* user, prb_interval alloc, bool needs_pdcch); bool reserve_ul_prbs(const prbmask_t& prbmask, bool strict); - bool find_ul_alloc(uint32_t L, ul_harq_proc::ul_alloc_t* alloc) const; + bool find_ul_alloc(uint32_t L, prb_interval* alloc) const; // getters const rbgmask_t& get_dl_mask() const { return dl_mask; } @@ -213,10 +213,10 @@ public: class ul_sf_sched_itf { public: - virtual alloc_outcome_t alloc_ul_user(sched_ue* user, ul_harq_proc::ul_alloc_t alloc) = 0; - virtual const prbmask_t& get_ul_mask() const = 0; - virtual uint32_t get_tti_tx_ul() const = 0; - virtual bool is_ul_alloc(const sched_ue* user) const = 0; + virtual alloc_outcome_t alloc_ul_user(sched_ue* user, prb_interval alloc) = 0; + virtual const prbmask_t& get_ul_mask() const = 0; + virtual uint32_t get_tti_tx_ul() const = 0; + virtual bool is_ul_alloc(const sched_ue* user) const = 0; }; /** Description: Stores the RAR, broadcast, paging, DL data, UL data allocations for the given subframe @@ -228,7 +228,7 @@ class sf_sched : public dl_sf_sched_itf, public ul_sf_sched_itf public: struct ctrl_alloc_t { size_t dci_idx; - rbg_range_t rbg_range; + rbg_interval rbg_range; uint16_t rnti; uint32_t req_bytes; alloc_type_t alloc_type; @@ -253,14 +253,14 @@ public: }; struct ul_alloc_t { enum type_t { NEWTX, NOADAPT_RETX, ADAPT_RETX, MSG3 }; - size_t dci_idx; - type_t type; - sched_ue* user_ptr; - ul_harq_proc::ul_alloc_t alloc; - uint32_t mcs = 0; - bool is_retx() const { return type == NOADAPT_RETX or type == ADAPT_RETX; } - bool is_msg3() const { return type == MSG3; } - bool needs_pdcch() const { return type == NEWTX or type == ADAPT_RETX; } + size_t dci_idx; + type_t type; + sched_ue* user_ptr; + prb_interval alloc; + uint32_t mcs = 0; + bool is_retx() const { return type == NOADAPT_RETX or type == ADAPT_RETX; } + bool is_msg3() const { return type == MSG3; } + bool needs_pdcch() const { return type == NEWTX or type == ADAPT_RETX; } }; struct pending_msg3_t { uint16_t rnti = 0; @@ -290,8 +290,7 @@ public: // UL alloc methods alloc_outcome_t alloc_msg3(sched_ue* user, const sched_interface::dl_sched_rar_grant_t& rargrant); - alloc_outcome_t - alloc_ul(sched_ue* user, ul_harq_proc::ul_alloc_t alloc, sf_sched::ul_alloc_t::type_t alloc_type, uint32_t mcs = 0); + alloc_outcome_t alloc_ul(sched_ue* user, prb_interval alloc, ul_alloc_t::type_t alloc_type, uint32_t mcs = 0); bool reserve_ul_prbs(const prbmask_t& ulmask, bool strict) { return tti_alloc.reserve_ul_prbs(ulmask, strict); } bool alloc_phich(sched_ue* user, sched_interface::ul_sched_res_t* ul_sf_result); @@ -304,7 +303,7 @@ public: uint32_t get_nof_ctrl_symbols() const final; const rbgmask_t& get_dl_mask() const final { return tti_alloc.get_dl_mask(); } // ul_tti_sched itf - alloc_outcome_t alloc_ul_user(sched_ue* user, ul_harq_proc::ul_alloc_t alloc) final; + alloc_outcome_t alloc_ul_user(sched_ue* user, prb_interval alloc) final; const prbmask_t& get_ul_mask() const final { return tti_alloc.get_ul_mask(); } uint32_t get_tti_tx_ul() const final { return tti_params.tti_tx_ul; } @@ -316,12 +315,7 @@ public: private: ctrl_code_t alloc_dl_ctrl(uint32_t aggr_lvl, uint32_t tbs_bytes, uint16_t rnti); - int generate_format1a(uint32_t rb_start, - uint32_t l_crb, - uint32_t tbs, - uint32_t rv, - uint16_t rnti, - srslte_dci_dl_t* dci); + int generate_format1a(prb_interval prb_range, uint32_t tbs, uint32_t rv, uint16_t rnti, srslte_dci_dl_t* dci); void set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_result, sched_interface::dl_sched_res_t* dl_result); void set_rar_sched_result(const pdcch_grid_t::alloc_result_t& dci_result, sched_interface::dl_sched_res_t* dl_result); void set_dl_data_sched_result(const pdcch_grid_t::alloc_result_t& dci_result, diff --git a/srsenb/hdr/stack/mac/scheduler_harq.h b/srsenb/hdr/stack/mac/scheduler_harq.h index a8fde7a45..2e85caa0c 100644 --- a/srsenb/hdr/stack/mac/scheduler_harq.h +++ b/srsenb/hdr/stack/mac/scheduler_harq.h @@ -90,24 +90,13 @@ private: class ul_harq_proc : public harq_proc { public: - struct ul_alloc_t { - uint32_t RB_start; - uint32_t L; - void set(uint32_t start, uint32_t len) - { - RB_start = start; - L = len; - } - uint32_t RB_end() const { return RB_start + L; } - }; - - void new_tx(uint32_t tti, int mcs, int tbs, ul_alloc_t alloc, uint32_t max_retx_); - void new_retx(uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs, ul_alloc_t alloc); + void new_tx(uint32_t tti, int mcs, int tbs, prb_interval alloc, uint32_t max_retx_); + void new_retx(uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs, prb_interval alloc); bool set_ack(uint32_t tb_idx, bool ack); - ul_alloc_t get_alloc() const; - bool has_pending_retx() const; - bool is_adaptive_retx() const; + prb_interval get_alloc() const; + bool has_pending_retx() const; + bool is_adaptive_retx() const; void reset_pending_data(); bool has_pending_ack() const; @@ -115,10 +104,10 @@ public: uint32_t get_pending_data() const; private: - ul_alloc_t allocation; - int pending_data; - bool is_adaptive; - ack_t pending_ack; + prb_interval allocation; + int pending_data; + bool is_adaptive; + ack_t pending_ack; }; class harq_entity diff --git a/srsenb/hdr/stack/mac/scheduler_metric.h b/srsenb/hdr/stack/mac/scheduler_metric.h index c6f0a4baf..b51cbc894 100644 --- a/srsenb/hdr/stack/mac/scheduler_metric.h +++ b/srsenb/hdr/stack/mac/scheduler_metric.h @@ -50,7 +50,7 @@ public: void sched_users(std::map& ue_db, ul_sf_sched_itf* tti_sched) final; private: - bool find_allocation(uint32_t L, ul_harq_proc::ul_alloc_t* alloc); + bool find_allocation(uint32_t L, prb_interval* alloc); ul_harq_proc* allocate_user_newtx_prbs(sched_ue* user); ul_harq_proc* allocate_user_retx_prbs(sched_ue* user); diff --git a/srsenb/hdr/stack/mac/scheduler_ue.h b/srsenb/hdr/stack/mac/scheduler_ue.h index b589865ce..aa82c6207 100644 --- a/srsenb/hdr/stack/mac/scheduler_ue.h +++ b/srsenb/hdr/stack/mac/scheduler_ue.h @@ -172,12 +172,12 @@ public: uint32_t get_required_prb_ul(uint32_t cc_idx, uint32_t req_bytes); - rbg_range_t get_required_dl_rbgs(uint32_t ue_cc_idx); - std::pair get_requested_dl_bytes(uint32_t ue_cc_idx); - uint32_t get_pending_dl_new_data(); - uint32_t get_pending_ul_new_data(uint32_t tti); - uint32_t get_pending_ul_old_data(uint32_t cc_idx); - uint32_t get_pending_dl_new_data_total(); + rbg_interval get_required_dl_rbgs(uint32_t ue_cc_idx); + srslte::interval get_requested_dl_bytes(uint32_t ue_cc_idx); + uint32_t get_pending_dl_new_data(); + uint32_t get_pending_ul_new_data(uint32_t tti); + uint32_t get_pending_ul_old_data(uint32_t cc_idx); + uint32_t get_pending_dl_new_data_total(); dl_harq_proc* get_pending_dl_harq(uint32_t tti_tx_dl, uint32_t cc_idx); dl_harq_proc* get_empty_dl_harq(uint32_t tti_tx_dl, uint32_t cc_idx); @@ -205,7 +205,7 @@ public: int generate_format0(sched_interface::ul_sched_data_t* data, uint32_t tti, uint32_t cc_idx, - ul_harq_proc::ul_alloc_t alloc, + prb_interval alloc, bool needs_pdcch, srslte_dci_location_t cce_range, int explicit_mcs = -1, diff --git a/srsenb/src/stack/mac/scheduler.cc b/srsenb/src/stack/mac/scheduler.cc index 9b4ab21ce..72446dcb5 100644 --- a/srsenb/src/stack/mac/scheduler.cc +++ b/srsenb/src/stack/mac/scheduler.cc @@ -450,24 +450,24 @@ void sched_cell_params_t::regs_deleter::operator()(srslte_regs_t* p) } } -rbg_range_t rbg_range_t::prbs_to_rbgs(const prb_range_t& prbs, uint32_t P) +rbg_interval rbg_interval::prbs_to_rbgs(const prb_interval& prbs, uint32_t P) { - return rbg_range_t{srslte::ceil_div(prbs.prb_min, P), srslte::ceil_div(prbs.prb_min, P)}; + return rbg_interval{srslte::ceil_div(prbs.start, P), srslte::ceil_div(prbs.start, P)}; } -prb_range_t prb_range_t::rbgs_to_prbs(const rbg_range_t& rbgs, uint32_t P) +prb_interval prb_interval::rbgs_to_prbs(const rbg_interval& rbgs, uint32_t P) { - return prb_range_t{rbgs.rbg_min * P, rbgs.rbg_max * P}; + return prb_interval{rbgs.start * P, rbgs.stop * P}; } -prb_range_t prb_range_t::riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs) +prb_interval prb_interval::riv_to_prbs(uint32_t riv, uint32_t nof_prbs, int nof_vrbs) { - prb_range_t p; + prb_interval p; if (nof_vrbs < 0) { nof_vrbs = nof_prbs; } - srslte_ra_type2_from_riv(riv, &p.prb_max, &p.prb_min, nof_prbs, (uint32_t)nof_vrbs); - p.prb_max += p.prb_min; + srslte_ra_type2_from_riv(riv, &p.stop, &p.start, nof_prbs, (uint32_t)nof_vrbs); + p.stop += p.start; return p; } diff --git a/srsenb/src/stack/mac/scheduler_grid.cc b/srsenb/src/stack/mac/scheduler_grid.cc index 5ad366535..28ff4a1b6 100644 --- a/srsenb/src/stack/mac/scheduler_grid.cc +++ b/srsenb/src/stack/mac/scheduler_grid.cc @@ -444,9 +444,9 @@ alloc_outcome_t sf_grid_t::alloc_dl(uint32_t aggr_idx, alloc_type_t alloc_type, //! Allocates CCEs and RBs for control allocs. It allocates RBs in a contiguous manner. sf_grid_t::dl_ctrl_alloc_t sf_grid_t::alloc_dl_ctrl(uint32_t aggr_idx, alloc_type_t alloc_type) { - rbg_range_t range; - range.rbg_min = nof_rbgs - avail_rbg; - range.rbg_max = range.rbg_min + ((alloc_type == alloc_type_t::DL_RAR) ? rar_n_rbg : si_n_rbg); + rbg_interval range; + range.start = nof_rbgs - avail_rbg; + range.set_length((alloc_type == alloc_type_t::DL_RAR) ? rar_n_rbg : si_n_rbg); if (alloc_type != alloc_type_t::DL_RAR and alloc_type != alloc_type_t::DL_BC and alloc_type != alloc_type_t::DL_PCCH) { @@ -454,13 +454,13 @@ sf_grid_t::dl_ctrl_alloc_t sf_grid_t::alloc_dl_ctrl(uint32_t aggr_idx, alloc_typ return {alloc_outcome_t::ERROR, range}; } // Setup range starting from left - if (range.rbg_max > nof_rbgs) { + if (range.stop > nof_rbgs) { return {alloc_outcome_t::RB_COLLISION, range}; } // allocate DCI and RBGs rbgmask_t new_mask(dl_mask.size()); - new_mask.fill(range.rbg_min, range.rbg_max); + new_mask.fill(range.start, range.stop); return {alloc_dl(aggr_idx, alloc_type, new_mask), range}; } @@ -475,14 +475,14 @@ alloc_outcome_t sf_grid_t::alloc_dl_data(sched_ue* user, const rbgmask_t& user_m return ret; } -alloc_outcome_t sf_grid_t::alloc_ul_data(sched_ue* user, ul_harq_proc::ul_alloc_t alloc, bool needs_pdcch) +alloc_outcome_t sf_grid_t::alloc_ul_data(sched_ue* user, prb_interval alloc, bool needs_pdcch) { - if (alloc.RB_start + alloc.L > ul_mask.size()) { + if (alloc.stop > ul_mask.size()) { return alloc_outcome_t::ERROR; } prbmask_t newmask(ul_mask.size()); - newmask.fill(alloc.RB_start, alloc.RB_start + alloc.L); + newmask.fill(alloc.start, alloc.stop); if ((ul_mask & newmask).any()) { return alloc_outcome_t::RB_COLLISION; } @@ -531,34 +531,34 @@ bool sf_grid_t::reserve_ul_prbs(const prbmask_t& prbmask, bool strict) * @param alloc Found allocation. It is guaranteed that 0 <= alloc->L <= L * @return true if the requested allocation of size L was strictly met */ -bool sf_grid_t::find_ul_alloc(uint32_t L, ul_harq_proc::ul_alloc_t* alloc) const +bool sf_grid_t::find_ul_alloc(uint32_t L, prb_interval* alloc) const { *alloc = {}; - for (uint32_t n = 0; n < ul_mask.size() && alloc->L < L; n++) { - if (not ul_mask.test(n) && alloc->L == 0) { - alloc->RB_start = n; + for (uint32_t n = 0; n < ul_mask.size() && alloc->length() < L; n++) { + if (not ul_mask.test(n) && alloc->length() == 0) { + alloc->shift_to(n); } if (not ul_mask.test(n)) { - alloc->L++; - } else if (alloc->L > 0) { + alloc->stop++; + } else if (alloc->length() > 0) { // avoid edges if (n < 3) { - alloc->RB_start = 0; - alloc->L = 0; + alloc->start = 0; + alloc->stop = 0; } else { break; } } } - if (alloc->L == 0) { + if (alloc->length() == 0) { return false; } // Make sure L is allowed by SC-FDMA modulation - while (!srslte_dft_precoding_valid_prb(alloc->L)) { - alloc->L--; + while (!srslte_dft_precoding_valid_prb(alloc->length())) { + alloc->stop--; } - return alloc->L == L; + return alloc->length() == L; } /******************************************************* @@ -757,8 +757,8 @@ alloc_outcome_t sf_sched::alloc_dl_user(sched_ue* user, const rbgmask_t& user_ma const dl_harq_proc& h = user->get_dl_harq(pid, ue_cc_idx); if (h.is_empty()) { // It is newTx - rbg_range_t r = user->get_required_dl_rbgs(ue_cc_idx); - if (r.rbg_min > user_mask.count()) { + rbg_interval r = user->get_required_dl_rbgs(ue_cc_idx); + if (r.start > user_mask.count()) { log_h->warning("The number of RBGs allocated to rnti=0x%x will force segmentation\n", user->get_rnti()); return alloc_outcome_t::NOF_RB_INVALID; } @@ -771,10 +771,10 @@ alloc_outcome_t sf_sched::alloc_dl_user(sched_ue* user, const rbgmask_t& user_ma bool has_pusch_grant = is_ul_alloc(user) or cc_results->is_ul_alloc(user->get_rnti()); if (not has_pusch_grant) { // Try to allocate small PUSCH grant, if there are no allocated PUSCH grants for this TTI yet - ul_harq_proc::ul_alloc_t alloc = {}; - uint32_t L = user->get_required_prb_ul(ue_cc_idx, srslte::ceil_div(SRSLTE_UCI_CQI_CODED_PUCCH_B + 2, 8)); + prb_interval alloc = {}; + uint32_t L = user->get_required_prb_ul(ue_cc_idx, srslte::ceil_div(SRSLTE_UCI_CQI_CODED_PUCCH_B + 2, 8)); tti_alloc.find_ul_alloc(L, &alloc); - if (ue_cc_idx != 0 and (alloc.L == 0 or not alloc_ul_user(user, alloc))) { + if (ue_cc_idx != 0 and (alloc.length() == 0 or not alloc_ul_user(user, alloc))) { // For SCells, if we can't allocate small PUSCH grant, abort DL allocation return alloc_outcome_t::PUCCH_COLLISION; } @@ -798,10 +798,7 @@ alloc_outcome_t sf_sched::alloc_dl_user(sched_ue* user, const rbgmask_t& user_ma return alloc_outcome_t::SUCCESS; } -alloc_outcome_t sf_sched::alloc_ul(sched_ue* user, - ul_harq_proc::ul_alloc_t alloc, - sf_sched::ul_alloc_t::type_t alloc_type, - uint32_t mcs) +alloc_outcome_t sf_sched::alloc_ul(sched_ue* user, prb_interval alloc, ul_alloc_t::type_t alloc_type, uint32_t mcs) { // Check whether user was already allocated if (is_ul_alloc(user)) { @@ -827,15 +824,15 @@ alloc_outcome_t sf_sched::alloc_ul(sched_ue* user, return alloc_outcome_t::SUCCESS; } -alloc_outcome_t sf_sched::alloc_ul_user(sched_ue* user, ul_harq_proc::ul_alloc_t alloc) +alloc_outcome_t sf_sched::alloc_ul_user(sched_ue* user, prb_interval alloc) { // check whether adaptive/non-adaptive retx/newtx - sf_sched::ul_alloc_t::type_t alloc_type; - ul_harq_proc* h = user->get_ul_harq(get_tti_tx_ul(), user->get_cell_index(cc_cfg->enb_cc_idx).second); - bool has_retx = h->has_pending_retx(); + ul_alloc_t::type_t alloc_type; + ul_harq_proc* h = user->get_ul_harq(get_tti_tx_ul(), user->get_cell_index(cc_cfg->enb_cc_idx).second); + bool has_retx = h->has_pending_retx(); if (has_retx) { - ul_harq_proc::ul_alloc_t prev_alloc = h->get_alloc(); - if (prev_alloc.L == alloc.L and prev_alloc.RB_start == alloc.RB_start) { + prb_interval prev_alloc = h->get_alloc(); + if (prev_alloc == alloc) { alloc_type = ul_alloc_t::NOADAPT_RETX; } else { alloc_type = ul_alloc_t::ADAPT_RETX; @@ -885,17 +882,16 @@ void sf_sched::set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul bc->dci.location = dci_result[bc_alloc.dci_idx]->dci_pos; /* Generate DCI format1A */ - prb_range_t prb_range = prb_range_t::rbgs_to_prbs(bc_alloc.rbg_range, cc_cfg->P); - int tbs = generate_format1a( - prb_range.prb_min, prb_range.nof_prbs(), bc_alloc.req_bytes, bc_alloc.rv, bc_alloc.rnti, &bc->dci); + prb_interval prb_range = prb_interval::rbgs_to_prbs(bc_alloc.rbg_range, cc_cfg->P); + int tbs = generate_format1a(prb_range, bc_alloc.req_bytes, bc_alloc.rv, bc_alloc.rnti, &bc->dci); // Setup BC/Paging processes if (bc_alloc.alloc_type == alloc_type_t::DL_BC) { if (tbs <= (int)bc_alloc.req_bytes) { log_h->warning("SCHED: Error SIB%d, rbgs=(%d,%d), dci=(%d,%d), len=%d\n", bc_alloc.sib_idx + 1, - bc_alloc.rbg_range.rbg_min, - bc_alloc.rbg_range.rbg_max, + bc_alloc.rbg_range.start, + bc_alloc.rbg_range.stop, bc->dci.location.L, bc->dci.location.ncce, bc_alloc.req_bytes); @@ -909,8 +905,8 @@ void sf_sched::set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul log_h->debug("SCHED: SIB%d, rbgs=(%d,%d), dci=(%d,%d), rv=%d, len=%d, period=%d, mcs=%d\n", bc_alloc.sib_idx + 1, - bc_alloc.rbg_range.rbg_min, - bc_alloc.rbg_range.rbg_max, + bc_alloc.rbg_range.start, + bc_alloc.rbg_range.stop, bc->dci.location.L, bc->dci.location.ncce, bc_alloc.rv, @@ -920,9 +916,8 @@ void sf_sched::set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul } else { // Paging if (tbs <= 0) { - log_h->warning("SCHED: Error Paging, rbgs=(%d,%d), dci=(%d,%d)\n", - bc_alloc.rbg_range.rbg_min, - bc_alloc.rbg_range.rbg_max, + log_h->warning("SCHED: Error Paging, rbgs=%s, dci=(%d,%d)\n", + bc_alloc.rbg_range.to_string().c_str(), bc->dci.location.L, bc->dci.location.ncce); continue; @@ -932,9 +927,8 @@ void sf_sched::set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul bc->type = sched_interface::dl_sched_bc_t::PCCH; bc->tbs = (uint32_t)tbs; - log_h->info("SCHED: PCH, rbgs=(%d,%d), dci=(%d,%d), tbs=%d, mcs=%d\n", - bc_alloc.rbg_range.rbg_min, - bc_alloc.rbg_range.rbg_max, + log_h->info("SCHED: PCH, rbgs=%s, dci=(%d,%d), tbs=%d, mcs=%d\n", + bc_alloc.rbg_range.to_string().c_str(), bc->dci.location.L, bc->dci.location.ncce, tbs, @@ -955,18 +949,12 @@ void sf_sched::set_rar_sched_result(const pdcch_grid_t::alloc_result_t& dci_resu rar->dci.location = dci_result[rar_alloc.alloc_data.dci_idx]->dci_pos; /* Generate DCI format1A */ - prb_range_t prb_range = prb_range_t::rbgs_to_prbs(rar_alloc.alloc_data.rbg_range, cc_cfg->P); - int tbs = generate_format1a(prb_range.prb_min, - prb_range.nof_prbs(), - rar_alloc.alloc_data.req_bytes, - 0, - rar_alloc.alloc_data.rnti, - &rar->dci); + prb_interval prb_range = prb_interval::rbgs_to_prbs(rar_alloc.alloc_data.rbg_range, cc_cfg->P); + int tbs = generate_format1a(prb_range, rar_alloc.alloc_data.req_bytes, 0, rar_alloc.alloc_data.rnti, &rar->dci); if (tbs <= 0) { - log_h->warning("SCHED: Error RAR, ra_rnti_idx=%d, rbgs=(%d,%d), dci=(%d,%d)\n", + log_h->warning("SCHED: Error RAR, ra_rnti_idx=%d, rbgs=%s, dci=(%d,%d)\n", rar_alloc.alloc_data.rnti, - rar_alloc.alloc_data.rbg_range.rbg_min, - rar_alloc.alloc_data.rbg_range.rbg_max, + rar_alloc.alloc_data.rbg_range.to_string().c_str(), rar->dci.location.L, rar->dci.location.ncce); continue; @@ -981,12 +969,11 @@ void sf_sched::set_rar_sched_result(const pdcch_grid_t::alloc_result_t& dci_resu for (uint32_t i = 0; i < rar->nof_grants; ++i) { const auto& msg3_grant = rar->msg3_grant[i]; uint16_t expected_rnti = msg3_grant.data.temp_crnti; - log_h->info("SCHED: RAR, temp_crnti=0x%x, ra-rnti=%d, rbgs=(%d,%d), dci=(%d,%d), rar_grant_rba=%d, " + log_h->info("SCHED: RAR, temp_crnti=0x%x, ra-rnti=%d, rbgs=%s, dci=(%d,%d), rar_grant_rba=%d, " "rar_grant_mcs=%d\n", expected_rnti, rar_alloc.alloc_data.rnti, - rar_alloc.alloc_data.rbg_range.rbg_min, - rar_alloc.alloc_data.rbg_range.rbg_max, + rar_alloc.alloc_data.rbg_range.to_string().c_str(), rar->dci.location.L, rar->dci.location.ncce, msg3_grant.grant.rba, @@ -1142,21 +1129,20 @@ void sf_sched::set_ul_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul ul_harq_proc* h = user->get_ul_harq(get_tti_tx_ul(), cell_index); if (tbs <= 0) { - log_h->warning("SCHED: Error %s %s rnti=0x%x, pid=%d, dci=(%d,%d), prb=(%d,%d), bsr=%d\n", + log_h->warning("SCHED: Error %s %s rnti=0x%x, pid=%d, dci=(%d,%d), prb=%s, bsr=%d\n", ul_alloc.type == ul_alloc_t::MSG3 ? "Msg3" : "UL", ul_alloc.is_retx() ? "retx" : "tx", user->get_rnti(), h->get_id(), pusch->dci.location.L, pusch->dci.location.ncce, - ul_alloc.alloc.RB_start, - ul_alloc.alloc.RB_start + ul_alloc.alloc.L, + ul_alloc.alloc.to_string().c_str(), user->get_pending_ul_new_data(get_tti_tx_ul())); continue; } // Print Resulting UL Allocation - log_h->info("SCHED: %s %s rnti=0x%x, cc=%d, pid=%d, dci=(%d,%d), prb=(%d,%d), n_rtx=%d, tbs=%d, bsr=%d (%d-%d)\n", + log_h->info("SCHED: %s %s rnti=0x%x, cc=%d, pid=%d, dci=(%d,%d), prb=%s, n_rtx=%d, tbs=%d, bsr=%d (%d-%d)\n", ul_alloc.is_msg3() ? "Msg3" : "UL", ul_alloc.is_retx() ? "retx" : "tx", user->get_rnti(), @@ -1164,8 +1150,7 @@ void sf_sched::set_ul_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul h->get_id(), pusch->dci.location.L, pusch->dci.location.ncce, - ul_alloc.alloc.RB_start, - ul_alloc.alloc.RB_start + ul_alloc.alloc.L, + ul_alloc.alloc.to_string().c_str(), h->nof_retx(0), tbs, user->get_pending_ul_new_data(get_tti_tx_ul()), @@ -1179,14 +1164,14 @@ void sf_sched::set_ul_sched_result(const pdcch_grid_t::alloc_result_t& dci_resul alloc_outcome_t sf_sched::alloc_msg3(sched_ue* user, const sched_interface::dl_sched_rar_grant_t& rargrant) { // Derive PRBs from allocated RAR grants - ul_harq_proc::ul_alloc_t msg3_alloc = {}; - srslte_ra_type2_from_riv( - rargrant.grant.rba, &msg3_alloc.L, &msg3_alloc.RB_start, cc_cfg->nof_prb(), cc_cfg->nof_prb()); + prb_interval msg3_alloc = {}; + uint32_t L; + srslte_ra_type2_from_riv(rargrant.grant.rba, &L, &msg3_alloc.start, cc_cfg->nof_prb(), cc_cfg->nof_prb()); + msg3_alloc.set_length(L); alloc_outcome_t ret = alloc_ul(user, msg3_alloc, sf_sched::ul_alloc_t::MSG3, rargrant.grant.trunc_mcs); if (not ret) { - log_h->warning( - "SCHED: Could not allocate msg3 within (%d,%d)\n", msg3_alloc.RB_start, msg3_alloc.RB_start + msg3_alloc.L); + log_h->warning("SCHED: Could not allocate msg3 within %s\n", msg3_alloc.to_string().c_str()); } return ret; } @@ -1223,8 +1208,7 @@ uint32_t sf_sched::get_nof_ctrl_symbols() const return tti_alloc.get_cfi() + ((cc_cfg->cfg.cell.nof_prb <= 10) ? 1 : 0); } -int sf_sched::generate_format1a(uint32_t rb_start, - uint32_t l_crb, +int sf_sched::generate_format1a(prb_interval prb_range, uint32_t tbs_bytes, uint32_t rv, uint16_t rnti, @@ -1262,7 +1246,7 @@ int sf_sched::generate_format1a(uint32_t rb_start, dci->alloc_type = SRSLTE_RA_ALLOC_TYPE2; dci->type2_alloc.mode = srslte_ra_type2_t::SRSLTE_RA_TYPE2_LOC; - dci->type2_alloc.riv = srslte_ra_type2_to_riv(l_crb, rb_start, cc_cfg->cfg.cell.nof_prb); + dci->type2_alloc.riv = srslte_ra_type2_to_riv(prb_range.length(), prb_range.start, cc_cfg->cfg.cell.nof_prb); dci->pid = 0; dci->tb[0].mcs_idx = mcs; dci->tb[0].rv = rv; diff --git a/srsenb/src/stack/mac/scheduler_harq.cc b/srsenb/src/stack/mac/scheduler_harq.cc index 031f91e1e..5de64c4a2 100644 --- a/srsenb/src/stack/mac/scheduler_harq.cc +++ b/srsenb/src/stack/mac/scheduler_harq.cc @@ -228,7 +228,7 @@ void dl_harq_proc::reset_pending_data() * UE::UL HARQ class * ******************************************************/ -ul_harq_proc::ul_alloc_t ul_harq_proc::get_alloc() const +prb_interval ul_harq_proc::get_alloc() const { return allocation; } @@ -243,7 +243,7 @@ bool ul_harq_proc::is_adaptive_retx() const return is_adaptive and has_pending_retx(); } -void ul_harq_proc::new_tx(uint32_t tti_, int mcs, int tbs, ul_harq_proc::ul_alloc_t alloc, uint32_t max_retx_) +void ul_harq_proc::new_tx(uint32_t tti_, int mcs, int tbs, prb_interval alloc, uint32_t max_retx_) { max_retx = (uint32_t)max_retx_; is_adaptive = false; @@ -253,9 +253,9 @@ void ul_harq_proc::new_tx(uint32_t tti_, int mcs, int tbs, ul_harq_proc::ul_allo pending_ack = NULL_ACK; } -void ul_harq_proc::new_retx(uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs, ul_harq_proc::ul_alloc_t alloc) +void ul_harq_proc::new_retx(uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs, prb_interval alloc) { - is_adaptive = alloc.L != allocation.L or alloc.RB_start != allocation.RB_start; + is_adaptive = alloc != allocation; allocation = alloc; new_retx_common(tb_idx, tti_point{tti_}, mcs, tbs); } diff --git a/srsenb/src/stack/mac/scheduler_metric.cc b/srsenb/src/stack/mac/scheduler_metric.cc index 4d581c83b..e492ea20e 100644 --- a/srsenb/src/stack/mac/scheduler_metric.cc +++ b/srsenb/src/stack/mac/scheduler_metric.cc @@ -131,10 +131,10 @@ dl_harq_proc* dl_metric_rr::allocate_user(sched_ue* user) h = user->get_empty_dl_harq(tti_dl, cell_idx); if (h != nullptr) { // Allocate resources based on pending data - rbg_range_t req_rbgs = user->get_required_dl_rbgs(cell_idx); - if (req_rbgs.rbg_min > 0) { + rbg_interval req_rbgs = user->get_required_dl_rbgs(cell_idx); + if (req_rbgs.start > 0) { rbgmask_t newtx_mask(tti_alloc->get_dl_mask().size()); - if (find_allocation(req_rbgs.rbg_min, req_rbgs.rbg_max, &newtx_mask)) { + if (find_allocation(req_rbgs.start, req_rbgs.stop, &newtx_mask)) { // some empty spaces were found code = tti_alloc->alloc_dl_user(user, newtx_mask, h->get_id()); if (code == alloc_outcome_t::SUCCESS) { @@ -203,35 +203,34 @@ void ul_metric_rr::sched_users(std::map& ue_db, ul_sf_sched_ * @param alloc Found allocation. It is guaranteed that 0 <= alloc->L <= L * @return true if the requested allocation of size L was strictly met */ -bool ul_metric_rr::find_allocation(uint32_t L, ul_harq_proc::ul_alloc_t* alloc) +bool ul_metric_rr::find_allocation(uint32_t L, prb_interval* alloc) { const prbmask_t* used_rb = &tti_alloc->get_ul_mask(); - bzero(alloc, sizeof(ul_harq_proc::ul_alloc_t)); - for (uint32_t n = 0; n < used_rb->size() && alloc->L < L; n++) { - if (not used_rb->test(n) && alloc->L == 0) { - alloc->RB_start = n; + *alloc = {}; + for (uint32_t n = 0; n < used_rb->size() && alloc->length() < L; n++) { + if (not used_rb->test(n) && alloc->length() == 0) { + alloc->shift_to(n); } if (not used_rb->test(n)) { - alloc->L++; - } else if (alloc->L > 0) { + alloc->stop++; + } else if (alloc->length() > 0) { // avoid edges if (n < 3) { - alloc->RB_start = 0; - alloc->L = 0; + *alloc = {}; } else { break; } } } - if (alloc->L == 0) { + if (alloc->length() == 0) { return false; } // Make sure L is allowed by SC-FDMA modulation - while (!srslte_dft_precoding_valid_prb(alloc->L)) { - alloc->L--; + while (!srslte_dft_precoding_valid_prb(alloc->length())) { + alloc->stop--; } - return alloc->L == L; + return alloc->length() == L; } ul_harq_proc* ul_metric_rr::allocate_user_retx_prbs(sched_ue* user) @@ -251,7 +250,7 @@ ul_harq_proc* ul_metric_rr::allocate_user_retx_prbs(sched_ue* user) // if there are procedures and we have space if (h->has_pending_retx()) { - ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); + prb_interval alloc = h->get_alloc(); // If can schedule the same mask, do it ret = tti_alloc->alloc_ul_user(user, alloc); @@ -263,7 +262,7 @@ ul_harq_proc* ul_metric_rr::allocate_user_retx_prbs(sched_ue* user) return nullptr; } - if (find_allocation(alloc.L, &alloc)) { + if (find_allocation(alloc.length(), &alloc)) { ret = tti_alloc->alloc_ul_user(user, alloc); if (ret == alloc_outcome_t::SUCCESS) { return h; @@ -293,11 +292,11 @@ ul_harq_proc* ul_metric_rr::allocate_user_newtx_prbs(sched_ue* user) // find an empty PID if (h->is_empty(0) and pending_data > 0) { - uint32_t pending_rb = user->get_required_prb_ul(cell_idx, pending_data); - ul_harq_proc::ul_alloc_t alloc{}; + uint32_t pending_rb = user->get_required_prb_ul(cell_idx, pending_data); + prb_interval alloc{}; find_allocation(pending_rb, &alloc); - if (alloc.L > 0) { // at least one PRB was scheduled + if (alloc.length() > 0) { // at least one PRB was scheduled alloc_outcome_t ret = tti_alloc->alloc_ul_user(user, alloc); if (ret == alloc_outcome_t::SUCCESS) { return h; diff --git a/srsenb/src/stack/mac/scheduler_ue.cc b/srsenb/src/stack/mac/scheduler_ue.cc index e828974e7..905c73c98 100644 --- a/srsenb/src/stack/mac/scheduler_ue.cc +++ b/srsenb/src/stack/mac/scheduler_ue.cc @@ -524,8 +524,8 @@ std::pair sched_ue::compute_mcs_and_tbs(uint32_t ue_cc_i uint32_t cfi, const srslte_dci_dl_t& dci) { - int mcs = 0, tbs_bytes = 0; - std::pair req_bytes = get_requested_dl_bytes(ue_cc_idx); + int mcs = 0, tbs_bytes = 0; + srslte::interval req_bytes = get_requested_dl_bytes(ue_cc_idx); // Calculate exact number of RE for this PRB allocation srslte_pdsch_grant_t grant = {}; @@ -539,7 +539,7 @@ std::pair sched_ue::compute_mcs_and_tbs(uint32_t ue_cc_i // Use a higher MCS for the Msg4 to fit in the 6 PRB case if (carriers[ue_cc_idx].fixed_mcs_dl < 0 or not carriers[ue_cc_idx].dl_cqi_rx) { // Dynamic MCS - tbs_bytes = carriers[ue_cc_idx].alloc_tbs_dl(nof_alloc_prbs, nof_re, req_bytes.second, &mcs); + tbs_bytes = carriers[ue_cc_idx].alloc_tbs_dl(nof_alloc_prbs, nof_re, req_bytes.stop, &mcs); } else { // Fixed MCS mcs = carriers[ue_cc_idx].fixed_mcs_dl; @@ -549,7 +549,7 @@ std::pair sched_ue::compute_mcs_and_tbs(uint32_t ue_cc_i // If the number of prbs is not sufficient to fit minimum required bytes, increase the mcs // NOTE: this may happen during ConRes CE tx when DL-CQI is still not available - while (tbs_bytes > 0 and (uint32_t) tbs_bytes < req_bytes.first and mcs < 28) { + while (tbs_bytes > 0 and (uint32_t) tbs_bytes < req_bytes.start and mcs < 28) { mcs++; tbs_bytes = sched_utils::get_tbs_bytes((uint32_t)mcs, nof_alloc_prbs, cfg.use_tbs_index_alt, false); } @@ -666,7 +666,7 @@ int sched_ue::generate_format2(uint32_t pid, int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, uint32_t tti, uint32_t cc_idx, - ul_harq_proc::ul_alloc_t alloc, + prb_interval alloc, bool needs_pdcch, srslte_dci_location_t dci_pos, int explicit_mcs, @@ -692,18 +692,18 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, nof_retx = (data->needs_pdcch) ? get_max_retx() : max_msg3retx; if (mcs >= 0) { - tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false, true), alloc.L) / 8; + tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false, true), alloc.length()) / 8; } else { // dynamic mcs uint32_t req_bytes = get_pending_ul_new_data_unlocked(tti); uint32_t N_srs = 0; - uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell.cp) - 1) - N_srs) * alloc.L * SRSLTE_NRE; - tbs = carriers[cc_idx].alloc_tbs_ul(alloc.L, nof_re, req_bytes, &mcs); + uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell.cp) - 1) - N_srs) * alloc.length() * SRSLTE_NRE; + tbs = carriers[cc_idx].alloc_tbs_ul(alloc.length(), nof_re, req_bytes, &mcs); if (carries_uci) { // Reduce MCS to fit UCI mcs -= std::min(main_cc_params->sched_cfg->uci_mcs_dec, mcs); - tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false, true), alloc.L) / 8; + tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false, true), alloc.length()) / 8; } } h->new_tx(tti, mcs, tbs, alloc, nof_retx); @@ -713,7 +713,7 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, } else { // retx h->new_retx(0, tti, &mcs, nullptr, alloc); - tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false, true), alloc.L) / 8; + tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false, true), alloc.length()) / 8; } data->tbs = tbs; @@ -722,7 +722,7 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, dci->rnti = rnti; dci->format = SRSLTE_DCI_FORMAT0; dci->ue_cc_idx = cc_idx; - dci->type2_alloc.riv = srslte_ra_type2_to_riv(alloc.L, alloc.RB_start, cell.nof_prb); + dci->type2_alloc.riv = srslte_ra_type2_to_riv(alloc.length(), alloc.start, cell.nof_prb); dci->tb.rv = sched_utils::get_rvidx(h->nof_retx(0)); if (!is_newtx && h->is_adaptive_retx()) { dci->tb.mcs_idx = 28 + dci->tb.rv; @@ -793,25 +793,25 @@ uint32_t sched_ue::get_pending_dl_new_data_total() * @param ue_cc_idx carrier of the UE * @return range of number of RBGs that a UE can allocate in a given subframe */ -rbg_range_t sched_ue::get_required_dl_rbgs(uint32_t ue_cc_idx) +rbg_interval sched_ue::get_required_dl_rbgs(uint32_t ue_cc_idx) { - std::pair req_bytes = get_requested_dl_bytes(ue_cc_idx); - if (req_bytes.first == 0 and req_bytes.second == 0) { + srslte::interval req_bytes = get_requested_dl_bytes(ue_cc_idx); + if (req_bytes == srslte::interval{0, 0}) { return {0, 0}; } const auto* cellparams = carriers[ue_cc_idx].get_cell_cfg(); int pending_prbs = - carriers[ue_cc_idx].get_required_prb_dl(req_bytes.first, cellparams->sched_cfg->max_nof_ctrl_symbols); + carriers[ue_cc_idx].get_required_prb_dl(req_bytes.start, cellparams->sched_cfg->max_nof_ctrl_symbols); if (pending_prbs < 0) { // 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, - req_bytes.first); + req_bytes.start); return {cellparams->nof_prb(), cellparams->nof_prb()}; } uint32_t min_pending_rbg = cellparams->prb_to_rbg(pending_prbs); - pending_prbs = carriers[ue_cc_idx].get_required_prb_dl(req_bytes.second, cellparams->sched_cfg->max_nof_ctrl_symbols); + pending_prbs = carriers[ue_cc_idx].get_required_prb_dl(req_bytes.stop, cellparams->sched_cfg->max_nof_ctrl_symbols); pending_prbs = (pending_prbs < 0) ? cellparams->nof_prb() : pending_prbs; uint32_t max_pending_rbg = cellparams->prb_to_rbg(pending_prbs); return {min_pending_rbg, max_pending_rbg}; @@ -832,7 +832,7 @@ rbg_range_t sched_ue::get_required_dl_rbgs(uint32_t ue_cc_idx) * @ue_cc_idx carrier where allocation is being made * @return */ -std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_idx) +srslte::interval sched_ue::get_requested_dl_bytes(uint32_t ue_cc_idx) { const uint32_t min_alloc_bytes = 5; // 2 for subheader, and 3 for RLC header // Convenience function to compute the number of bytes allocated for a given SDU @@ -849,10 +849,10 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id // SRB0 is a special case due to being RLC TM (no segmentation possible) if (not lch_handler.is_bearer_dl(0)) { log_h->error("SRB0 must always be activated for DL\n"); - return {0, 0}; + return {}; } if (not carriers[ue_cc_idx].is_active()) { - return {0, 0}; + return {}; } uint32_t max_data = 0, min_data = 0; @@ -866,7 +866,7 @@ std::pair sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id if (ue_cc_idx == 0) { if (srb0_data == 0 and not pending_ces.empty() and pending_ces.front() == srslte::dl_sch_lcid::CON_RES_ID) { // Wait for SRB0 data to be available for Msg4 before scheduling the ConRes CE - return {0, 0}; + return {}; } for (const ce_cmd& ce : pending_ces) { sum_ce_data += srslte::ce_total_size(ce); diff --git a/srsenb/test/mac/scheduler_test_common.cc b/srsenb/test/mac/scheduler_test_common.cc index b9c283be1..e427793ef 100644 --- a/srsenb/test/mac/scheduler_test_common.cc +++ b/srsenb/test/mac/scheduler_test_common.cc @@ -64,20 +64,16 @@ int output_sched_tester::test_pusch_collisions(const tti_params_t& ul_allocs.resize(nof_prb); ul_allocs.reset(); - auto try_ul_fill = [&](srsenb::ul_harq_proc::ul_alloc_t alloc, const char* ch_str, bool strict = true) { - CONDERROR((alloc.RB_start + alloc.L) > nof_prb, - "Allocated RBs (%d,%d) out-of-bounds\n", - alloc.RB_start, - alloc.RB_start + alloc.L); - CONDERROR(alloc.L == 0, "Allocations must have at least one PRB\n"); - if (strict and ul_allocs.any(alloc.RB_start, alloc.RB_start + alloc.L)) { - TESTERROR("Collision Detected of %s alloc=(%d,%d) and cumulative_mask=0x%s\n", + auto try_ul_fill = [&](prb_interval alloc, const char* ch_str, bool strict = true) { + CONDERROR(alloc.stop > nof_prb, "Allocated RBs %s out-of-bounds\n", alloc.to_string().c_str()); + CONDERROR(alloc.is_empty(), "Allocations must have at least one PRB\n"); + if (strict and ul_allocs.any(alloc.start, alloc.stop)) { + TESTERROR("Collision Detected of %s alloc=%s and cumulative_mask=0x%s\n", ch_str, - alloc.RB_start, - alloc.RB_start + alloc.L, + alloc.to_string().c_str(), ul_allocs.to_hex().c_str()); } - ul_allocs.fill(alloc.RB_start, alloc.RB_start + alloc.L, true); + ul_allocs.fill(alloc.start, alloc.stop, true); return SRSLTE_SUCCESS; }; @@ -85,21 +81,22 @@ int output_sched_tester::test_pusch_collisions(const tti_params_t& bool is_prach_tti_tx_ul = srslte_prach_tti_opportunity_config_fdd(cell_params.cfg.prach_config, tti_params.tti_tx_ul, -1); if (is_prach_tti_tx_ul) { - try_ul_fill({cell_params.cfg.prach_freq_offset, 6}, "PRACH"); + try_ul_fill({cell_params.cfg.prach_freq_offset, cell_params.cfg.prach_freq_offset + 6}, "PRACH"); } /* TEST: check collisions in PUCCH */ bool strict = nof_prb != 6 or (not is_prach_tti_tx_ul); // and not tti_data.ul_pending_msg3_present); try_ul_fill({0, (uint32_t)cell_params.cfg.nrb_pucch}, "PUCCH", strict); - try_ul_fill( - {cell_params.cfg.cell.nof_prb - cell_params.cfg.nrb_pucch, (uint32_t)cell_params.cfg.nrb_pucch}, "PUCCH", strict); + try_ul_fill({cell_params.cfg.cell.nof_prb - cell_params.cfg.nrb_pucch, (uint32_t)cell_params.cfg.cell.nof_prb}, + "PUCCH", + strict); /* TEST: check collisions in the UL PUSCH */ for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) { uint32_t L, RBstart; srslte_ra_type2_from_riv(ul_result.pusch[i].dci.type2_alloc.riv, &L, &RBstart, nof_prb, nof_prb); strict = ul_result.pusch[i].needs_pdcch or nof_prb != 6; // Msg3 may collide with PUCCH at PRB==6 - try_ul_fill({RBstart, L}, "PUSCH", strict); + try_ul_fill({RBstart, RBstart + L}, "PUSCH", strict); // ue_stats[ul_result.pusch[i].dci.rnti].nof_ul_rbs += L; }