diff --git a/srsenb/hdr/stack/mac/sched_common.h b/srsenb/hdr/stack/mac/sched_common.h index 2732b3830..905f5257f 100644 --- a/srsenb/hdr/stack/mac/sched_common.h +++ b/srsenb/hdr/stack/mac/sched_common.h @@ -59,9 +59,10 @@ public: uint32_t get_dl_lb_nof_re(tti_point tti_tx_dl, uint32_t nof_prbs_alloc) const; uint32_t get_dl_nof_res(srslte::tti_point tti_tx_dl, const srslte_dci_dl_t& dci, uint32_t cfi) const; - uint32_t enb_cc_idx = 0; - sched_interface::cell_cfg_t cfg = {}; - const sched_interface::sched_args_t* sched_cfg = nullptr; + uint32_t enb_cc_idx = 0; + sched_interface::cell_cfg_t cfg = {}; + srslte_pucch_cfg_t pucch_cfg_common = {}; + const sched_interface::sched_args_t* sched_cfg = nullptr; std::unique_ptr regs; cce_sf_position_table common_locations = {}; cce_frame_position_table rar_locations = {}; diff --git a/srsenb/hdr/stack/mac/sched_grid.h b/srsenb/hdr/stack/mac/sched_grid.h index e8962d213..47c801d15 100644 --- a/srsenb/hdr/stack/mac/sched_grid.h +++ b/srsenb/hdr/stack/mac/sched_grid.h @@ -105,7 +105,8 @@ public: 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, prb_interval alloc, bool needs_pdcch); - bool reserve_ul_prbs(const prbmask_t& prbmask, bool strict); + alloc_outcome_t reserve_ul_prbs(const prbmask_t& prbmask, bool strict); + alloc_outcome_t reserve_ul_prbs(prb_interval alloc, bool strict); bool find_ul_alloc(uint32_t L, prb_interval* alloc) const; // getters @@ -113,6 +114,7 @@ public: const prbmask_t& get_ul_mask() const { return ul_mask; } uint32_t get_cfi() const { return pdcch_alloc.get_cfi(); } const sf_cch_allocator& get_pdcch_grid() const { return pdcch_alloc; } + uint32_t get_pucch_width() const { return pucch_nrb; } private: alloc_outcome_t alloc_dl(uint32_t aggr_lvl, alloc_type_t alloc_type, rbgmask_t alloc_mask, sched_ue* user = nullptr); @@ -122,6 +124,8 @@ private: srslog::basic_logger& logger; uint32_t nof_rbgs = 0; uint32_t si_n_rbg = 0, rar_n_rbg = 0; + uint32_t pucch_nrb = 0; + prbmask_t pucch_mask; // derived sf_cch_allocator pdcch_alloc = {}; @@ -166,7 +170,7 @@ public: uint32_t pid; }; struct ul_alloc_t { - enum type_t { NEWTX, NOADAPT_RETX, ADAPT_RETX, MSG3 }; + enum type_t { NEWTX, NOADAPT_RETX, ADAPT_RETX, MSG3, MSG3_RETX }; size_t dci_idx; type_t type; uint16_t rnti; @@ -243,7 +247,6 @@ private: const sched_cell_params_t* cc_cfg = nullptr; srslog::basic_logger& logger; sf_sched_result* cc_results; ///< Results of other CCs for the same Subframe - prbmask_t pucch_mask; // internal state sf_grid_t tti_alloc; diff --git a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h index 2435b69e8..c2147410f 100644 --- a/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h +++ b/srsenb/hdr/stack/mac/sched_ue_ctrl/sched_harq.h @@ -85,13 +85,14 @@ private: class ul_harq_proc : public harq_proc { public: - void new_tx(srslte::tti_point tti, int mcs, int tbs, prb_interval alloc, uint32_t max_retx_); + void new_tx(srslte::tti_point tti, int mcs, int tbs, prb_interval alloc, uint32_t max_retx_, bool is_msg3); void new_retx(srslte::tti_point tti_, int* mcs, int* tbs, prb_interval alloc); bool set_ack(uint32_t tb_idx, bool ack); bool retx_requires_pdcch(srslte::tti_point tti_, prb_interval alloc) const; prb_interval get_alloc() const; bool has_pending_retx() const; + bool is_msg3() const { return is_msg3_; } void reset_pending_data(); uint32_t get_pending_data() const; @@ -102,6 +103,7 @@ private: prb_interval allocation; int pending_data; bool pending_phich = false; + bool is_msg3_ = false; }; class harq_entity diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 0a55c1b10..e04863d75 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -131,6 +131,14 @@ void sf_grid_t::init(const sched_cell_params_t& cell_params_) ul_mask.resize(cc_cfg->nof_prb()); pdcch_alloc.init(*cc_cfg); + + // Compute reserved PRBs for CQI, SR and HARQ-ACK, and store it in a bitmask + pucch_mask.resize(cc_cfg->nof_prb()); + pucch_nrb = (cc_cfg->cfg.nrb_pucch > 0) ? (uint32_t)cc_cfg->cfg.nrb_pucch : 0; + if (pucch_nrb > 0) { + pucch_mask.fill(0, pucch_nrb); + pucch_mask.fill(cc_cfg->nof_prb() - pucch_nrb, cc_cfg->nof_prb()); + } } void sf_grid_t::new_tti(tti_point tti_rx_) @@ -141,6 +149,19 @@ void sf_grid_t::new_tti(tti_point tti_rx_) ul_mask.reset(); avail_rbg = nof_rbgs; + // Reserve PRBs for PUCCH + ul_mask |= pucch_mask; + + // Reserve PRBs for PRACH + if (srslte_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, to_tx_ul(tti_rx).to_uint(), -1)) { + prbmask_t prach_mask{cc_cfg->nof_prb()}; + prach_mask.fill(cc_cfg->cfg.prach_freq_offset, cc_cfg->cfg.prach_freq_offset + 6); + reserve_ul_prbs(prach_mask, cc_cfg->nof_prb() != 6); + logger.debug("SCHED: Allocated PRACH RBs for tti_tx_ul=%d. Mask: 0x%s", + to_tx_ul(tti_rx).to_uint(), + prach_mask.to_hex().c_str()); + } + // internal state pdcch_alloc.new_tti(tti_rx); } @@ -242,14 +263,25 @@ bool sf_grid_t::reserve_dl_rbgs(uint32_t start_rbg, uint32_t end_rbg) return true; } -bool sf_grid_t::reserve_ul_prbs(const prbmask_t& prbmask, bool strict) +alloc_outcome_t sf_grid_t::reserve_ul_prbs(prb_interval alloc, bool strict) { - bool ret = true; + if (alloc.stop() > ul_mask.size()) { + return alloc_outcome_t::ERROR; + } + + prbmask_t newmask(ul_mask.size()); + newmask.fill(alloc.start(), alloc.stop()); + return reserve_ul_prbs(newmask, strict); +} + +alloc_outcome_t sf_grid_t::reserve_ul_prbs(const prbmask_t& prbmask, bool strict) +{ + alloc_outcome_t ret = alloc_outcome_t::SUCCESS; if (strict and (ul_mask & prbmask).any()) { logger.error("There was a collision in UL channel. current mask=0x%s, new alloc mask=0x%s", ul_mask.to_hex().c_str(), prbmask.to_hex().c_str()); - ret = false; + ret = alloc_outcome_t::ERROR; } ul_mask |= prbmask; return ret; @@ -300,13 +332,7 @@ void sf_sched::init(const sched_cell_params_t& cell_params_) { cc_cfg = &cell_params_; tti_alloc.init(*cc_cfg); - max_msg3_prb = std::max(6u, cc_cfg->cfg.cell.nof_prb - (uint32_t)cc_cfg->cfg.nrb_pucch); - - pucch_mask.resize(cc_cfg->nof_prb()); - if (cc_cfg->cfg.nrb_pucch > 0) { - pucch_mask.fill(0, (uint32_t)cc_cfg->cfg.nrb_pucch); - pucch_mask.fill(cc_cfg->nof_prb() - cc_cfg->cfg.nrb_pucch, cc_cfg->nof_prb()); - } + max_msg3_prb = std::max(6u, cc_cfg->cfg.cell.nof_prb - tti_alloc.get_pucch_width()); } void sf_sched::new_tti(tti_point tti_rx_, sf_sched_result* cc_results_) @@ -321,21 +347,8 @@ void sf_sched::new_tti(tti_point tti_rx_, sf_sched_result* cc_results_) tti_alloc.new_tti(tti_rx_); cc_results = cc_results_; - // Reserve PRBs for PUCCH - reserve_ul_prbs(pucch_mask, true); - - // Reserve PRBs for PRACH - if (srslte_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, to_tx_ul(tti_rx).to_uint(), -1)) { - prbmask_t prach_mask{cc_cfg->nof_prb()}; - prach_mask.fill(cc_cfg->cfg.prach_freq_offset, cc_cfg->cfg.prach_freq_offset + 6); - reserve_ul_prbs(prach_mask, cc_cfg->nof_prb() != 6); - logger.debug("SCHED: Allocated PRACH RBs for tti_tx_ul=%d. Mask: 0x%s", - to_tx_ul(tti_rx).to_uint(), - prach_mask.to_hex().c_str()); - } - // setup first prb to be used for msg3 alloc. Account for potential PRACH alloc - last_msg3_prb = cc_cfg->cfg.nrb_pucch; + last_msg3_prb = tti_alloc.get_pucch_width(); tti_point tti_msg3_alloc = to_tx_ul(tti_rx) + MSG3_DELAY_MS; if (srslte_prach_tti_opportunity_config_fdd(cc_cfg->cfg.prach_config, tti_msg3_alloc.to_uint(), -1)) { last_msg3_prb = std::max(last_msg3_prb, cc_cfg->cfg.prach_freq_offset + 6); @@ -595,7 +608,13 @@ alloc_outcome_t sf_sched::alloc_ul(sched_ue* user, prb_interval alloc, ul_alloc_ } // Allocate RBGs and DCI space - alloc_outcome_t ret = tti_alloc.alloc_ul_data(user, alloc, needs_pdcch); + alloc_outcome_t ret; + if (alloc_type != ul_alloc_t::MSG3 and alloc_type != ul_alloc_t::MSG3_RETX) { + ret = tti_alloc.alloc_ul_data(user, alloc, needs_pdcch); + } else { + // allow collisions between Msg3 and PUCCH for 6 PRBs + ret = tti_alloc.reserve_ul_prbs(alloc, cc_cfg->nof_prb() != 6); + } if (ret != alloc_outcome_t::SUCCESS) { return ret; } @@ -617,14 +636,14 @@ alloc_outcome_t sf_sched::alloc_ul_user(sched_ue* user, prb_interval alloc) ul_alloc_t::type_t alloc_type; ul_harq_proc* h = user->get_ul_harq(get_tti_tx_ul(), cc_cfg->enb_cc_idx); bool has_retx = h->has_pending_retx(); - if (has_retx) { - if (h->retx_requires_pdcch(tti_point{get_tti_tx_ul()}, alloc)) { - alloc_type = ul_alloc_t::ADAPT_RETX; - } else { - alloc_type = ul_alloc_t::NOADAPT_RETX; - } - } else { + if (not has_retx) { alloc_type = ul_alloc_t::NEWTX; + } else if (h->is_msg3()) { + alloc_type = ul_alloc_t::MSG3_RETX; + } else if (h->retx_requires_pdcch(tti_point{get_tti_tx_ul()}, alloc)) { + alloc_type = ul_alloc_t::ADAPT_RETX; + } else { + alloc_type = ul_alloc_t::NOADAPT_RETX; } return alloc_ul(user, alloc, alloc_type); diff --git a/srsenb/src/stack/mac/sched_helpers.cc b/srsenb/src/stack/mac/sched_helpers.cc index a5891425d..c77838fde 100644 --- a/srsenb/src/stack/mac/sched_helpers.cc +++ b/srsenb/src/stack/mac/sched_helpers.cc @@ -221,11 +221,14 @@ sched_cell_params_t::dl_lb_nof_re_table get_lb_nof_re_x_prb(const sched_cell_par srslte::bounded_vector re_prb_vec(table.size()); for (uint32_t p = 0; p < table.size(); ++p) { for (uint32_t s = 0; s < SRSLTE_NOF_SLOTS_PER_SF; ++s) { + // assume max CFI to compute lower bound re_prb_vec[p] += table[p][sf_idx][s][SRSLTE_NOF_CFI - 1]; } } + srslte::bounded_vector re_prb_vec2(re_prb_vec.size()); std::copy(re_prb_vec.begin(), re_prb_vec.end(), re_prb_vec2.begin()); + // pick intervals of PRBs with the lowest sum of REs ret[sf_idx][0] = *std::min_element(re_prb_vec2.begin(), re_prb_vec2.end()); for (uint32_t p = 1; p < table.size(); ++p) { std::transform(re_prb_vec2.begin(), @@ -323,6 +326,13 @@ bool sched_cell_params_t::set_cfg(uint32_t enb_cc_id nof_cce_table[cfix] = (uint32_t)ret; } + // PUCCH config struct for PUCCH position derivation + pucch_cfg_common.format = SRSLTE_PUCCH_FORMAT_1; + pucch_cfg_common.delta_pucch_shift = cfg.delta_pucch_shift; + pucch_cfg_common.n_rb_2 = cfg.nrb_cqi; + pucch_cfg_common.N_cs = cfg.ncs_an; + pucch_cfg_common.N_pucch_1 = cfg.n1pucch_an; + P = srslte_ra_type0_P(cfg.cell.nof_prb); nof_rbgs = srslte::ceil_div(cfg.cell.nof_prb, P); diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index 5c13f2aa3..d5bb2232e 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -616,11 +616,6 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, bool is_newtx = h->is_empty(0); if (is_newtx) { - uint32_t nof_retx; - - // If Msg3 set different nof retx - nof_retx = (data->needs_pdcch) ? get_max_retx() : max_msg3retx; - if (tbinfo.mcs >= 0) { tbinfo.tbs_bytes = get_tbs_bytes(tbinfo.mcs, alloc.length(), false, true); } else { @@ -653,7 +648,9 @@ int sched_ue::generate_format0(sched_interface::ul_sched_data_t* data, // NOTE: if (nof_re < nof_uci_re) we should set TBS=0 } } - h->new_tx(tti_tx_ul, tbinfo.mcs, tbinfo.tbs_bytes, alloc, nof_retx); + // If Msg3 set different nof retx + uint32_t nof_retx = (data->needs_pdcch) ? get_max_retx() : max_msg3retx; + h->new_tx(tti_tx_ul, tbinfo.mcs, tbinfo.tbs_bytes, alloc, nof_retx, not data->needs_pdcch); // Un-trigger the SR if data is allocated if (tbinfo.tbs_bytes > 0) { unset_sr(); diff --git a/srsenb/src/stack/mac/sched_ue_ctrl/sched_harq.cc b/srsenb/src/stack/mac/sched_ue_ctrl/sched_harq.cc index f628c92e0..5ced31492 100644 --- a/srsenb/src/stack/mac/sched_ue_ctrl/sched_harq.cc +++ b/srsenb/src/stack/mac/sched_ue_ctrl/sched_harq.cc @@ -235,12 +235,13 @@ bool ul_harq_proc::has_pending_retx() const return has_pending_retx_common(0); } -void ul_harq_proc::new_tx(tti_point tti_, int mcs, int tbs, prb_interval alloc, uint32_t max_retx_) +void ul_harq_proc::new_tx(tti_point tti_, int mcs, int tbs, prb_interval alloc, uint32_t max_retx_, bool is_msg3) { allocation = alloc; new_tx_common(0, tti_point{tti_}, mcs, tbs, max_retx_); pending_data = tbs; pending_phich = true; + is_msg3_ = is_msg3; } void ul_harq_proc::new_retx(tti_point tti_, int* mcs, int* tbs, prb_interval alloc)