diff --git a/srsenb/hdr/stack/mac/scheduler_carrier.h b/srsenb/hdr/stack/mac/scheduler_carrier.h index 8cd3f0bc9..12b78e23c 100644 --- a/srsenb/hdr/stack/mac/scheduler_carrier.h +++ b/srsenb/hdr/stack/mac/scheduler_carrier.h @@ -98,7 +98,6 @@ private: std::array pending_sibs; // TTI specific - uint32_t current_sfn = 0, current_sf_idx = 0; uint32_t current_tti = 0; uint32_t bc_aggr_level = 2; }; diff --git a/srsenb/hdr/stack/mac/scheduler_grid.h b/srsenb/hdr/stack/mac/scheduler_grid.h index f7babc564..93e2eea11 100644 --- a/srsenb/hdr/stack/mac/scheduler_grid.h +++ b/srsenb/hdr/stack/mac/scheduler_grid.h @@ -69,6 +69,7 @@ public: void init(const sched_cell_params_t& cell_params_); void new_tti(const tti_params_t& tti_params_, uint32_t start_cfi); + void reset(); bool alloc_dci(alloc_type_t alloc_type, uint32_t aggr_idx, sched_ue* user = nullptr); bool set_cfi(uint32_t cfi); @@ -84,7 +85,6 @@ private: const static uint32_t nof_cfis = 3; using tree_node_t = std::pair; ///< First represents the parent node idx, and second the alloc tree node - void reset(); const sched_dci_cce_t* get_cce_loc_table(alloc_type_t alloc_type, sched_ue* user) const; void update_alloc_tree(int node_idx, uint32_t aggr_idx, @@ -104,7 +104,7 @@ private: size_t nof_dci_allocs = 0; }; -//! manages a full TTI grid resources, namely CCE and DL/UL RB allocations +//! manages a subframe grid resources, namely CCE and DL/UL RB allocations class sf_grid_t { public: @@ -113,16 +113,17 @@ public: rbg_range_t rbg_range; }; - void init(const sched_cell_params_t& cell_params_, uint32_t enb_cc_idx_); + void init(const sched_cell_params_t& cell_params_); void new_tti(const tti_params_t& tti_params_, uint32_t start_cfi); + void reset(); 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); + bool reserve_ul_prbs(const prbmask_t& prbmask, bool strict); // getters - rbgmask_t& get_dl_mask() { return dl_mask; } const rbgmask_t& get_dl_mask() const { return dl_mask; } - prbmask_t& get_ul_mask() { return ul_mask; } const prbmask_t& get_ul_mask() const { return ul_mask; } uint32_t get_cfi() const { return pdcch_alloc.get_cfi(); } const pdcch_grid_t& get_pdcch_grid() const { return pdcch_alloc; } @@ -168,8 +169,8 @@ public: virtual bool is_ul_alloc(sched_ue* user) const = 0; }; -/** Description: Stores the RAR, broadcast, paging, DL data, UL data allocations for the given TTI - * Converts the stored allocations' metadata to the scheduler UL/DL result +/** Description: Stores the RAR, broadcast, paging, DL data, UL data allocations for the given subframe + * Converts the stored allocations' metadata to the scheduler DL/UL result * Handles the generation of DCI formats */ class sf_sched : public dl_sf_sched_itf, public ul_sf_sched_itf @@ -219,32 +220,36 @@ public: uint32_t mcs = 0; }; struct pending_rar_t { - uint16_t ra_rnti = 0; - uint32_t prach_tti = 0; - uint32_t nof_grants = 0; - sched_interface::dl_sched_rar_info_t msg3_grant[sched_interface::MAX_RAR_LIST]; + uint16_t ra_rnti = 0; + uint32_t prach_tti = 0; + uint32_t nof_grants = 0; + sched_interface::dl_sched_rar_info_t msg3_grant[sched_interface::MAX_RAR_LIST] = {}; }; typedef std::pair ctrl_code_t; // TTI scheduler result - pdcch_mask_t pdcch_mask; sched_interface::dl_sched_res_t dl_sched_result; sched_interface::ul_sched_res_t ul_sched_result; + // Control/Configuration Methods void init(const sched_cell_params_t& cell_params_); void new_tti(uint32_t tti_rx_, uint32_t start_cfi); + void reset(); - // DL alloc + // DL alloc methods alloc_outcome_t alloc_bc(uint32_t aggr_lvl, uint32_t sib_idx, uint32_t sib_ntx); alloc_outcome_t alloc_paging(uint32_t aggr_lvl, uint32_t paging_payload); std::pair alloc_rar(uint32_t aggr_lvl, const pending_rar_t& rar_grant); + bool reserve_dl_rbgs(uint32_t rbg_start, uint32_t rbg_end) { return tti_alloc.reserve_dl_rbgs(rbg_start, rbg_end); } - // UL alloc + // UL alloc methods alloc_outcome_t alloc_msg3(const pending_msg3_t& msg3); 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_ul(sched_ue* user, ul_harq_proc::ul_alloc_t alloc, sf_sched::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); } - void generate_dcis(); + // compute DCIs and generate dl_sched_result/ul_sched_result for a given TTI + void generate_sched_results(); // dl_tti_sched itf alloc_outcome_t alloc_dl_user(sched_ue* user, const rbgmask_t& user_mask, uint32_t pid) final; @@ -257,18 +262,13 @@ public: uint32_t get_tti_tx_ul() const final { return tti_params.tti_tx_ul; } // getters - const pdcch_mask_t& get_pdcch_mask() const { return pdcch_mask; } - rbgmask_t& get_dl_mask() { return tti_alloc.get_dl_mask(); } - prbmask_t& get_ul_mask() { return tti_alloc.get_ul_mask(); } - const std::vector& get_ul_allocs() const { return ul_data_allocs; } - uint32_t get_cfi() const { return tti_alloc.get_cfi(); } uint32_t get_tti_rx() const { return tti_params.tti_rx; } - uint32_t get_sfn() const { return tti_params.sfn; } - uint32_t get_sf_idx() const { return tti_params.sf_idx; } const tti_params_t& get_tti_params() const { return tti_params; } std::deque& get_pending_msg3() { return pending_msg3s; } const std::deque& get_pending_msg3() const { return pending_msg3s; } + const std::tuple last_sched_result_masks() const; + private: bool is_dl_alloc(sched_ue* user) const final; bool is_ul_alloc(sched_ue* user) const final; @@ -297,6 +297,11 @@ private: std::vector ul_data_allocs; std::deque pending_msg3s; uint32_t last_msg3_prb = 0, max_msg3_prb = 0; + + // Store last decisions + rbgmask_t last_dl_mask; + prbmask_t last_ul_mask; + pdcch_mask_t last_pdcch_mask; }; } // namespace srsenb diff --git a/srsenb/src/stack/mac/scheduler_carrier.cc b/srsenb/src/stack/mac/scheduler_carrier.cc index 2a60747c0..2aed9db5a 100644 --- a/srsenb/src/stack/mac/scheduler_carrier.cc +++ b/srsenb/src/stack/mac/scheduler_carrier.cc @@ -38,10 +38,8 @@ bc_sched::bc_sched(const sched_cell_params_t& cfg_, srsenb::rrc_interface_mac* r void bc_sched::dl_sched(sf_sched* tti_sched) { - current_sf_idx = tti_sched->get_sf_idx(); - current_sfn = tti_sched->get_sfn(); - current_tti = tti_sched->get_tti_tx_dl(); - bc_aggr_level = 2; + current_tti = tti_sched->get_tti_tx_dl(); + bc_aggr_level = 2; /* Activate/deactivate SI windows */ update_si_windows(tti_sched); @@ -56,7 +54,9 @@ void bc_sched::dl_sched(sf_sched* tti_sched) void bc_sched::update_si_windows(sf_sched* tti_sched) { - uint32_t tti_tx_dl = tti_sched->get_tti_tx_dl(); + uint32_t tti_tx_dl = tti_sched->get_tti_tx_dl(); + uint32_t current_sf_idx = tti_sched->get_tti_params().sf_idx; + uint32_t current_sfn = tti_sched->get_tti_params().sfn; for (uint32_t i = 0; i < pending_sibs.size(); ++i) { // There is SIB data @@ -94,6 +94,9 @@ void bc_sched::update_si_windows(sf_sched* tti_sched) void bc_sched::alloc_sibs(sf_sched* tti_sched) { + uint32_t current_sf_idx = tti_sched->get_tti_params().sf_idx; + uint32_t current_sfn = tti_sched->get_tti_params().sfn; + for (uint32_t i = 0; i < pending_sibs.size(); i++) { if (cc_cfg->cfg.sibs[i].len > 0 and pending_sibs[i].is_in_window and pending_sibs[i].n_tx < 4) { uint32_t nof_tx = (i > 0) ? SRSLTE_MIN(srslte::ceil_div(cc_cfg->cfg.si_window_ms, 10), 4) : 4; @@ -371,7 +374,7 @@ sf_sched* sched::carrier_sched::generate_tti_result(uint32_t tti_rx) } /* Select the winner DCI allocation combination */ - tti_sched->generate_dcis(); + tti_sched->generate_sched_results(); /* Enqueue Msg3s derived from allocated RARs */ if (dl_active) { @@ -430,7 +433,7 @@ void sched::carrier_sched::alloc_dl_users(sf_sched* tti_result) if (cc_cfg->nof_prb() == 6) { uint32_t tti_rx_ack = TTI_RX_ACK(tti_result->get_tti_rx()); if (srslte_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, tti_rx_ack, -1)) { - tti_result->get_dl_mask().fill(0, tti_result->get_dl_mask().size()); + tti_result->reserve_dl_rbgs(0, cc_cfg->nof_rbgs); } } @@ -440,12 +443,11 @@ void sched::carrier_sched::alloc_dl_users(sf_sched* tti_result) int sched::carrier_sched::alloc_ul_users(sf_sched* tti_sched) { - uint32_t tti_tx_ul = tti_sched->get_tti_tx_ul(); - prbmask_t& ul_mask = tti_sched->get_ul_mask(); + uint32_t tti_tx_ul = tti_sched->get_tti_tx_ul(); /* reserve PRBs for PRACH */ if (srslte_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, tti_tx_ul, -1)) { - ul_mask = prach_mask; + tti_sched->reserve_ul_prbs(prach_mask, false); log_h->debug("SCHED: Allocated PRACH RBs. Mask: 0x%s\n", prach_mask.to_hex().c_str()); } @@ -453,12 +455,7 @@ int sched::carrier_sched::alloc_ul_users(sf_sched* tti_sched) ra_sched_ptr->ul_sched(tti_sched); /* reserve PRBs for PUCCH */ - if (cc_cfg->nof_prb() != 6 and (ul_mask & pucch_mask).any()) { - log_h->error("There was a collision with the PUCCH. current mask=0x%s, pucch_mask=0x%s\n", - ul_mask.to_hex().c_str(), - pucch_mask.to_hex().c_str()); - } - ul_mask |= pucch_mask; + tti_sched->reserve_ul_prbs(pucch_mask, true); /* Call scheduler for UL data */ ul_metric->sched_users(*ue_db, tti_sched); diff --git a/srsenb/src/stack/mac/scheduler_grid.cc b/srsenb/src/stack/mac/scheduler_grid.cc index 088e20c91..58131a632 100644 --- a/srsenb/src/stack/mac/scheduler_grid.cc +++ b/srsenb/src/stack/mac/scheduler_grid.cc @@ -70,7 +70,6 @@ void pdcch_grid_t::new_tti(const tti_params_t& tti_params_, uint32_t start_cfi) { tti_params = &tti_params_; current_cfix = start_cfi - 1; - reset(); } const sched_dci_cce_t* pdcch_grid_t::get_cce_loc_table(alloc_type_t alloc_type, sched_ue* user) const @@ -208,6 +207,7 @@ void pdcch_grid_t::get_allocs(alloc_result_t* vec, pdcch_mask_t* tot_mask, size_ vec->clear(); } if (tot_mask != nullptr) { + tot_mask->resize(nof_cces()); tot_mask->reset(); } return; @@ -265,7 +265,7 @@ std::string pdcch_grid_t::result_to_string(bool verbose) const * TTI resource Scheduling Methods *******************************************************/ -void sf_grid_t::init(const sched_cell_params_t& cell_params_, uint32_t enb_cc_idx_) +void sf_grid_t::init(const sched_cell_params_t& cell_params_) { cc_cfg = &cell_params_; log_h = srslte::logmap::get("MAC "); @@ -274,6 +274,7 @@ void sf_grid_t::init(const sched_cell_params_t& cell_params_, uint32_t enb_cc_id rar_n_rbg = srslte::ceil_div(3, cc_cfg->P); pdcch_alloc.init(*cc_cfg); + reset(); } void sf_grid_t::new_tti(const tti_params_t& tti_params_, uint32_t start_cfi) @@ -282,13 +283,18 @@ void sf_grid_t::new_tti(const tti_params_t& tti_params_, uint32_t start_cfi) // internal state avail_rbg = nof_rbgs; - dl_mask.reset(); dl_mask.resize(nof_rbgs); - ul_mask.reset(); ul_mask.resize(cc_cfg->nof_prb()); pdcch_alloc.new_tti(*tti_params, start_cfi); } +void sf_grid_t::reset() +{ + dl_mask.reset(); + ul_mask.reset(); + pdcch_alloc.reset(); +} + //! Allocates CCEs and RBs for the given mask and allocation type (e.g. data, BC, RAR, paging) alloc_outcome_t sf_grid_t::alloc_dl(uint32_t aggr_lvl, alloc_type_t alloc_type, rbgmask_t alloc_mask, sched_ue* user) { @@ -381,6 +387,25 @@ alloc_outcome_t sf_grid_t::alloc_ul_data(sched_ue* user, ul_harq_proc::ul_alloc_ return alloc_outcome_t::SUCCESS; } +bool sf_grid_t::reserve_dl_rbgs(uint32_t start_rbg, uint32_t end_rbg) +{ + dl_mask.fill(start_rbg, end_rbg); + return true; +} + +bool sf_grid_t::reserve_ul_prbs(const prbmask_t& prbmask, bool strict) +{ + bool ret = true; + if (strict and (ul_mask & prbmask).any()) { + log_h->error("There was a collision in UL channel. current mask=0x%s, new alloc mask=0x%s\n", + ul_mask.to_hex().c_str(), + prbmask.to_hex().c_str()); + ret = false; + } + ul_mask |= prbmask; + return ret; +} + /******************************************************* * TTI resource Scheduling Methods *******************************************************/ @@ -389,8 +414,9 @@ void sf_sched::init(const sched_cell_params_t& cell_params_) { cc_cfg = &cell_params_; log_h = srslte::logmap::get("MAC "); - tti_alloc.init(*cc_cfg, 0); + tti_alloc.init(*cc_cfg); max_msg3_prb = std::max(6u, cc_cfg->cfg.cell.nof_prb - (uint32_t)cc_cfg->cfg.nrb_pucch); + reset(); } void sf_sched::new_tti(uint32_t tti_rx_, uint32_t start_cfi) @@ -399,17 +425,9 @@ void sf_sched::new_tti(uint32_t tti_rx_, uint32_t start_cfi) tti_alloc.new_tti(tti_params, start_cfi); // reset sf result - pdcch_mask.reset(); - pdcch_mask.resize(tti_alloc.get_pdcch_grid().nof_cces()); dl_sched_result = {}; ul_sched_result = {}; - // reset internal state - bc_allocs.clear(); - rar_allocs.clear(); - data_allocs.clear(); - ul_data_allocs.clear(); - // setup first prb to be used for msg3 alloc last_msg3_prb = cc_cfg->cfg.nrb_pucch; uint32_t tti_msg3_alloc = TTI_ADD(tti_params.tti_tx_ul, MSG3_DELAY_MS); @@ -418,6 +436,17 @@ void sf_sched::new_tti(uint32_t tti_rx_, uint32_t start_cfi) } } +void sf_sched::reset() +{ + // reset internal state + bc_allocs.clear(); + rar_allocs.clear(); + data_allocs.clear(); + ul_data_allocs.clear(); + + tti_alloc.reset(); +} + bool sf_sched::is_dl_alloc(sched_ue* user) const { for (const auto& a : data_allocs) { @@ -630,6 +659,11 @@ alloc_outcome_t sf_sched::alloc_ul_user(sched_ue* user, ul_harq_proc::ul_alloc_t return alloc_ul(user, alloc, alloc_type); } +const std::tuple sf_sched::last_sched_result_masks() const +{ + return {last_pdcch_mask, last_dl_mask, last_ul_mask}; +} + void sf_sched::set_bc_sched_result(const pdcch_grid_t::alloc_result_t& dci_result) { for (const auto& bc_alloc : bc_allocs) { @@ -769,13 +803,13 @@ void sf_sched::set_dl_data_sched_result(const pdcch_grid_t::alloc_result_t& dci_ int tbs = 0; switch (dci_format) { case SRSLTE_DCI_FORMAT1: - tbs = user->generate_format1(h, data, get_tti_tx_dl(), cell_index, get_cfi(), data_alloc.user_mask); + tbs = user->generate_format1(h, data, get_tti_tx_dl(), cell_index, tti_alloc.get_cfi(), data_alloc.user_mask); break; case SRSLTE_DCI_FORMAT2: - tbs = user->generate_format2(h, data, get_tti_tx_dl(), cell_index, get_cfi(), data_alloc.user_mask); + tbs = user->generate_format2(h, data, get_tti_tx_dl(), cell_index, tti_alloc.get_cfi(), data_alloc.user_mask); break; case SRSLTE_DCI_FORMAT2A: - tbs = user->generate_format2a(h, data, get_tti_tx_dl(), cell_index, get_cfi(), data_alloc.user_mask); + tbs = user->generate_format2a(h, data, get_tti_tx_dl(), cell_index, tti_alloc.get_cfi(), data_alloc.user_mask); break; default: Error("DCI format (%d) not implemented\n", dci_format); @@ -874,12 +908,12 @@ alloc_outcome_t sf_sched::alloc_msg3(const pending_msg3_t& msg3) return alloc_outcome_t::SUCCESS; } -void sf_sched::generate_dcis() +void sf_sched::generate_sched_results() { /* Pick one of the possible DCI masks */ pdcch_grid_t::alloc_result_t dci_result; // tti_alloc.get_pdcch_grid().result_to_string(); - tti_alloc.get_pdcch_grid().get_allocs(&dci_result, &pdcch_mask); + tti_alloc.get_pdcch_grid().get_allocs(&dci_result, &last_pdcch_mask); /* Register final CFI */ dl_sched_result.cfi = tti_alloc.get_pdcch_grid().get_cfi(); @@ -892,6 +926,13 @@ void sf_sched::generate_dcis() set_dl_data_sched_result(dci_result); set_ul_sched_result(dci_result); + + /* Store last results */ + last_dl_mask = tti_alloc.get_dl_mask(); + last_ul_mask = tti_alloc.get_ul_mask(); + + /* Reset all resources */ + reset(); } uint32_t sf_sched::get_nof_ctrl_symbols() const diff --git a/srsenb/test/mac/scheduler_test_rand.cc b/srsenb/test/mac/scheduler_test_rand.cc index eaa5c525f..4c991ed8f 100644 --- a/srsenb/test/mac/scheduler_test_rand.cc +++ b/srsenb/test/mac/scheduler_test_rand.cc @@ -252,9 +252,10 @@ int sched_tester::test_pdcch_collisions() tti_info.dl_sched_result[CARRIER_IDX], tti_info.ul_sched_result[CARRIER_IDX]) == SRSLTE_SUCCESS); /* verify if sched_result "used_cce" coincide with sched "used_cce" */ - auto* tti_alloc = carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx); - if (used_cce != tti_alloc->get_pdcch_mask()) { - std::string mask_str = tti_alloc->get_pdcch_mask().to_string(); + auto* tti_alloc = carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx); + srsenb::pdcch_mask_t mask = std::get<0>(tti_alloc->last_sched_result_masks()); + if (used_cce != mask) { + std::string mask_str = mask.to_string(); TESTERROR("The used_cce do not match: (%s!=%s)\n", mask_str.c_str(), used_cce.to_string().c_str()); } @@ -375,15 +376,17 @@ int sched_tester::test_harqs() int sched_tester::test_sch_collisions() { - const srsenb::sf_sched* tti_sched = carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx); - srsenb::prbmask_t ul_allocs(sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb); + const srsenb::sf_sched* tti_sched = carrier_schedulers[CARRIER_IDX]->get_sf_sched_ptr(tti_info.tti_params.tti_rx); + const auto& combined_sched_result = tti_sched->last_sched_result_masks(); + + srsenb::prbmask_t ul_allocs(sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb); /* TEST: any collision in PUCCH and PUSCH */ TESTASSERT(output_tester[CARRIER_IDX].test_pusch_collisions( tti_info.tti_params, tti_info.ul_sched_result[CARRIER_IDX], ul_allocs) == SRSLTE_SUCCESS); /* TEST: check whether cumulative UL PRB masks coincide */ - if (ul_allocs != tti_sched->get_ul_mask()) { + if (ul_allocs != std::get<2>(combined_sched_result)) { TESTERROR("The UL PRB mask and the scheduler result UL mask are not consistent\n"); } @@ -413,14 +416,10 @@ int sched_tester::test_sch_collisions() } // TEST: check if resulting DL mask is equal to scheduler internal DL mask - if (rbgmask != carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx)->get_dl_mask()) { - TESTERROR("The UL PRB mask and the scheduler result UL mask are not consistent (%s!=%s)\n", + if (rbgmask != std::get<1>(combined_sched_result)) { + TESTERROR("The DL PRB mask and the scheduler result DL mask are not consistent (%s!=%s)\n", rbgmask.to_string().c_str(), - carrier_schedulers[CARRIER_IDX] - ->get_sf_sched_ptr(tti_info.tti_params.tti_rx) - ->get_dl_mask() - .to_string() - .c_str()); + std::get<1>(combined_sched_result).to_string().c_str()); } return SRSLTE_SUCCESS; }