diff --git a/srsgnb/hdr/stack/mac/sched_nr_ue.h b/srsgnb/hdr/stack/mac/sched_nr_ue.h index 59389d2a0..6cc35630d 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_ue.h +++ b/srsgnb/hdr/stack/mac/sched_nr_ue.h @@ -65,10 +65,12 @@ public: uint32_t cc = SRSRAN_MAX_CARRIERS; ue_buffer_manager* parent = nullptr; }; +}; -private: - /// Update of buffers is mutexed when carrier aggreg. is in place - std::mutex mutex; +/// Class containing context of UE that is common to all carriers +struct ue_context_common { + uint32_t pending_dl_bytes = 0; + uint32_t pending_ul_bytes = 0; }; class slot_ue; @@ -79,6 +81,7 @@ public: ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const cell_params_t& cell_params_, + const ue_context_common& ctxt, const ue_buffer_manager::pdu_builder& pdu_builder_); void set_cfg(const ue_cfg_t& ue_cfg); @@ -102,6 +105,9 @@ public: // metrics mac_ue_metrics_t metrics = {}; + // common context + const ue_context_common& common_ctxt; + private: friend class slot_ue; @@ -127,7 +133,7 @@ public: /// UE state feedback void ul_bsr(uint32_t lcg, uint32_t bsr_val) { buffers.ul_bsr(lcg, bsr_val); } - void ul_sr_info() { last_sr_slot = last_pdcch_slot - TX_ENB_DELAY; } + void ul_sr_info() { last_sr_slot = last_tx_slot - TX_ENB_DELAY; } bool has_ca() const { @@ -146,9 +152,9 @@ private: ue_cfg_t ue_cfg; - slot_point last_pdcch_slot; - slot_point last_sr_slot; - int ul_pending_bytes = 0, dl_pending_bytes = 0; + slot_point last_tx_slot; + slot_point last_sr_slot; + ue_context_common common_ctxt; ue_buffer_manager buffers; }; @@ -157,25 +163,29 @@ class slot_ue { public: slot_ue() = default; - explicit slot_ue(ue_carrier& ue, slot_point slot_tx_, uint32_t dl_pending_bytes, uint32_t ul_pending_bytes); + explicit slot_ue(ue_carrier& ue, slot_point slot_tx_); slot_ue(slot_ue&&) noexcept = default; slot_ue& operator=(slot_ue&&) noexcept = default; bool empty() const { return ue == nullptr; } void release() { ue = nullptr; } const ue_carrier_params_t& cfg() const { return ue->bwp_cfg; } - const ue_carrier_params_t& operator*() const { return ue->bwp_cfg; } const ue_carrier_params_t* operator->() const { return &ue->bwp_cfg; } - // mutable interface to ue_carrier state + /// Find available HARQs dl_harq_proc* find_empty_dl_harq() { return ue->harq_ent.find_empty_dl_harq(); } ul_harq_proc* find_empty_ul_harq() { return ue->harq_ent.find_empty_ul_harq(); } + /// Build PDU with MAC CEs and MAC SDUs void build_pdu(uint32_t rem_bytes, sched_nr_interface::dl_pdu_t& pdu) { ue->pdu_builder.alloc_subpdus(rem_bytes, pdu); } + /// Channel Information Getters + uint32_t dl_cqi() const { return ue->dl_cqi; } + uint32_t ul_cqi() const { return ue->ul_cqi; } + // UE parameters common to all sectors uint32_t dl_bytes = 0, ul_bytes = 0; diff --git a/srsgnb/src/stack/mac/sched_nr_helpers.cc b/srsgnb/src/stack/mac/sched_nr_helpers.cc index cf17981c3..c63d7a1bc 100644 --- a/srsgnb/src/stack/mac/sched_nr_helpers.cc +++ b/srsgnb/src/stack/mac/sched_nr_helpers.cc @@ -34,7 +34,14 @@ void log_sched_slot_ues(srslog::basic_logger& logger, slot_point pdcch_slot, uin for (const auto& ue_pair : slot_ues) { auto& ue = ue_pair->second; - fmt::format_to(fmtbuf, "{}{{rnti=0x{:x}, dl_bs={}, ul_bs={}}}", use_comma, ue->rnti, ue.dl_bytes, ue.ul_bytes); + fmt::format_to(fmtbuf, "{}{{rnti=0x{:x}", use_comma, ue->rnti); + if (ue.dl_active) { + fmt::format_to(fmtbuf, ", dl_bs={}", ue.dl_bytes); + } + if (ue.ul_active) { + fmt::format_to(fmtbuf, ", ul_bs={}", ue.ul_bytes); + } + fmt::format_to(fmtbuf, "}}"); use_comma = ", "; } diff --git a/srsgnb/src/stack/mac/sched_nr_sch.cc b/srsgnb/src/stack/mac/sched_nr_sch.cc index ebe7bcb2c..e378e364d 100644 --- a/srsgnb/src/stack/mac/sched_nr_sch.cc +++ b/srsgnb/src/stack/mac/sched_nr_sch.cc @@ -121,9 +121,9 @@ alloc_result pdsch_allocator::is_ue_grant_valid(const ue_carrier_params_t& ue, log_alloc_failure(bwp_cfg.logger.error, "rnti=0x%x,SearchSpaceId={} has not been configured.", ue.rnti, ss_id); return alloc_result::invalid_grant_params; } - alloc_result alloc_result = is_grant_valid_common(ss->type, dci_fmt, ss->coreset_id, grant); - if (alloc_result != alloc_result::success) { - return alloc_result; + alloc_result ret = is_grant_valid_common(ss->type, dci_fmt, ss->coreset_id, grant); + if (ret != alloc_result::success) { + return ret; } // TS 38.214, 5.1.2.2 - "the UE shall use the downlink frequency resource allocation type as defined by the higher diff --git a/srsgnb/src/stack/mac/sched_nr_ue.cc b/srsgnb/src/stack/mac/sched_nr_ue.cc index 869c7d615..d0c4cebf8 100644 --- a/srsgnb/src/stack/mac/sched_nr_ue.cc +++ b/srsgnb/src/stack/mac/sched_nr_ue.cc @@ -53,8 +53,7 @@ void ue_buffer_manager::pdu_builder::alloc_subpdus(uint32_t rem_bytes, sched_nr_ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -slot_ue::slot_ue(ue_carrier& ue_, slot_point slot_tx_, uint32_t dl_pending_bytes, uint32_t ul_pending_bytes) : - ue(&ue_), pdcch_slot(slot_tx_) +slot_ue::slot_ue(ue_carrier& ue_, slot_point slot_tx_) : ue(&ue_), pdcch_slot(slot_tx_) { const uint32_t k0 = 0; pdsch_slot = pdcch_slot + k0; @@ -65,17 +64,17 @@ slot_ue::slot_ue(ue_carrier& ue_, slot_point slot_tx_, uint32_t dl_pending_bytes const srsran_duplex_config_nr_t& tdd_cfg = ue->cell_params.cfg.duplex; - dl_active = srsran_duplex_nr_is_dl(&tdd_cfg, 0, pdsch_slot.slot_idx()); + dl_active = ue->cell_params.bwps[0].slots[pdsch_slot.slot_idx()].is_dl; if (dl_active) { - dl_bytes = dl_pending_bytes; + dl_bytes = ue->common_ctxt.pending_dl_bytes; h_dl = ue->harq_ent.find_pending_dl_retx(); if (h_dl == nullptr) { h_dl = ue->harq_ent.find_empty_dl_harq(); } } - ul_active = srsran_duplex_nr_is_ul(&tdd_cfg, 0, pusch_slot.slot_idx()); + ul_active = ue->cell_params.bwps[0].slots[pusch_slot.slot_idx()].is_ul; if (ul_active) { - ul_bytes = ul_pending_bytes; + ul_bytes = ue->common_ctxt.pending_ul_bytes; h_ul = ue->harq_ent.find_pending_ul_retx(); if (h_ul == nullptr) { h_ul = ue->harq_ent.find_empty_ul_harq(); @@ -88,6 +87,7 @@ slot_ue::slot_ue(ue_carrier& ue_, slot_point slot_tx_, uint32_t dl_pending_bytes ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const cell_params_t& cell_params_, + const ue_context_common& ctxt, const ue_buffer_manager::pdu_builder& pdu_builder_) : rnti(rnti_), cc(cell_params_.cc), @@ -95,6 +95,7 @@ ue_carrier::ue_carrier(uint16_t rnti_, bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_), cell_params(cell_params_), pdu_builder(pdu_builder_), + common_ctxt(ctxt), harq_ent(rnti_, cell_params_.nof_prb(), SCHED_NR_MAX_HARQ, cell_params_.bwps[0].logger) {} @@ -142,8 +143,11 @@ void ue::set_cfg(const ue_cfg_t& cfg) for (auto& ue_cc_cfg : cfg.carriers) { if (ue_cc_cfg.active) { if (carriers[ue_cc_cfg.cc] == nullptr) { - carriers[ue_cc_cfg.cc].reset(new ue_carrier( - rnti, ue_cfg, sched_cfg.cells[ue_cc_cfg.cc], ue_buffer_manager::pdu_builder{ue_cc_cfg.cc, buffers})); + carriers[ue_cc_cfg.cc].reset(new ue_carrier(rnti, + ue_cfg, + sched_cfg.cells[ue_cc_cfg.cc], + common_ctxt, + ue_buffer_manager::pdu_builder{ue_cc_cfg.cc, buffers})); } else { carriers[ue_cc_cfg.cc]->set_cfg(ue_cfg); } @@ -175,7 +179,7 @@ void ue::rlc_buffer_state(uint32_t lcid, uint32_t newtx, uint32_t priotx) void ue::new_slot(slot_point pdcch_slot) { - last_pdcch_slot = pdcch_slot; + last_tx_slot = pdcch_slot; for (std::unique_ptr& cc : carriers) { if (cc != nullptr) { @@ -185,18 +189,18 @@ void ue::new_slot(slot_point pdcch_slot) // Compute pending DL/UL bytes for {rnti, pdcch_slot} if (sched_cfg.sched_cfg.auto_refill_buffer) { - dl_pending_bytes = 1000000; - ul_pending_bytes = 1000000; + common_ctxt.pending_dl_bytes = 1000000; + common_ctxt.pending_ul_bytes = 1000000; } else { - dl_pending_bytes = buffers.get_dl_tx_total(); - ul_pending_bytes = buffers.get_bsr(); + common_ctxt.pending_dl_bytes = buffers.get_dl_tx_total(); + common_ctxt.pending_ul_bytes = buffers.get_bsr(); for (auto& ue_cc_cfg : ue_cfg.carriers) { auto& cc = carriers[ue_cc_cfg.cc]; if (cc != nullptr) { // Discount UL HARQ pending bytes to BSR for (uint32_t pid = 0; pid < cc->harq_ent.nof_ul_harqs(); ++pid) { if (not cc->harq_ent.ul_harq(pid).empty()) { - ul_pending_bytes -= cc->harq_ent.ul_harq(pid).tbs(); + common_ctxt.pending_ul_bytes -= std::min(cc->harq_ent.ul_harq(pid).tbs(), common_ctxt.pending_ul_bytes); if (last_sr_slot.valid() and cc->harq_ent.ul_harq(pid).harq_slot_tx() > last_sr_slot) { last_sr_slot.clear(); } @@ -204,10 +208,9 @@ void ue::new_slot(slot_point pdcch_slot) } } } - ul_pending_bytes = std::max(0, ul_pending_bytes); - if (ul_pending_bytes == 0 and last_sr_slot.valid()) { + if (common_ctxt.pending_ul_bytes == 0 and last_sr_slot.valid()) { // If unanswered SR is pending - ul_pending_bytes = 512; + common_ctxt.pending_ul_bytes = 512; } } } @@ -215,7 +218,7 @@ void ue::new_slot(slot_point pdcch_slot) slot_ue ue::make_slot_ue(slot_point pdcch_slot, uint32_t cc) { srsran_assert(carriers[cc] != nullptr, "make_slot_ue() called for inexistent rnti=0x%x,cc=%d", rnti, cc); - return slot_ue(*carriers[cc], pdcch_slot, dl_pending_bytes, ul_pending_bytes); + return slot_ue(*carriers[cc], pdcch_slot); } } // namespace sched_nr_impl diff --git a/srsgnb/src/stack/mac/test/CMakeLists.txt b/srsgnb/src/stack/mac/test/CMakeLists.txt index 8edb0ccd4..782c0879b 100644 --- a/srsgnb/src/stack/mac/test/CMakeLists.txt +++ b/srsgnb/src/stack/mac/test/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +set_directory_properties(PROPERTIES LABELS "sched;nr") + add_library(sched_nr_test_suite sched_nr_common_test.cc sched_nr_ue_ded_test_suite.cc sched_nr_sim_ue.cc) target_link_libraries(sched_nr_test_suite srsgnb_mac srsran_common) diff --git a/srsgnb/src/stack/mac/test/sched_nr_test.cc b/srsgnb/src/stack/mac/test/sched_nr_test.cc index 6a41ece98..7c6dd6f36 100644 --- a/srsgnb/src/stack/mac/test/sched_nr_test.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_test.cc @@ -130,7 +130,7 @@ void test_sched_nr_data() { uint32_t max_nof_ttis = 1000, nof_sectors = 1; uint16_t rnti = 0x4601; - uint32_t nof_dl_bytes_to_tx = 1e6; + uint32_t nof_dl_bytes_to_tx = 2e6; sched_nr_interface::sched_args_t cfg; cfg.auto_refill_buffer = false;