diff --git a/srsenb/test/mac/sched_ca_test.cc b/srsenb/test/mac/sched_ca_test.cc index ae22964f3..49fb28ae5 100644 --- a/srsenb/test/mac/sched_ca_test.cc +++ b/srsenb/test/mac/sched_ca_test.cc @@ -251,4 +251,4 @@ int main() } return 0; -} \ No newline at end of file +} diff --git a/srsenb/test/mac/sched_sim_ue.cc b/srsenb/test/mac/sched_sim_ue.cc index 17c38e8ef..0ba774b65 100644 --- a/srsenb/test/mac/sched_sim_ue.cc +++ b/srsenb/test/mac/sched_sim_ue.cc @@ -36,14 +36,17 @@ bool sim_ue_ctxt_t::is_last_dl_retx(uint32_t ue_cc_idx, uint32_t pid) const return h.nof_retxs + 1 >= ue_cfg.maxharq_tx; } -ue_sim::ue_sim(uint16_t rnti_, - const sched_interface::ue_cfg_t& ue_cfg_, - srslte::tti_point prach_tti_rx_, - uint32_t preamble_idx) +ue_sim::ue_sim(uint16_t rnti_, + const std::vector& cell_params_, + const sched_interface::ue_cfg_t& ue_cfg_, + srslte::tti_point prach_tti_rx_, + uint32_t preamble_idx) : + cell_params(&cell_params_) { ctxt.rnti = rnti_; ctxt.prach_tti_rx = prach_tti_rx_; ctxt.preamble_idx = preamble_idx; + pending_feedback.cc_list.resize(cell_params->size()); set_cfg(ue_cfg_); } @@ -59,37 +62,57 @@ void ue_sim::set_cfg(const sched_interface::ue_cfg_t& ue_cfg_) } } -bool ue_sim::enqueue_pending_acks(srslte::tti_point tti_rx, - pucch_feedback& feedback_list, - std::bitset ack_val) +ue_sim::sync_tti_events ue_sim::get_pending_events(srslte::tti_point tti_rx, sched_interface* sched) { - bool ack_added = false; - for (uint32_t ue_cc_idx = 0; ue_cc_idx < ctxt.cc_list.size(); ++ue_cc_idx) { - uint32_t enb_cc_idx = ctxt.ue_cfg.supported_cc_list[ue_cc_idx].enb_cc_idx; - auto& ue_cc = ctxt.cc_list[ue_cc_idx]; + pending_feedback.tti_rx = tti_rx; + for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_feedback.cc_list.size(); ++enb_cc_idx) { + auto& cc_feedback = pending_feedback.cc_list[enb_cc_idx]; + cc_feedback = {}; + if (ctxt.enb_to_ue_cc_idx(enb_cc_idx) < 0) { + continue; + } + cc_feedback.configured = true; + cc_feedback.ue_cc_idx = ctxt.enb_to_ue_cc_idx(enb_cc_idx); for (uint32_t pid = 0; pid < SRSLTE_FDD_NOF_HARQ; ++pid) { - auto& h = ue_cc.dl_harqs[pid]; + auto& h = ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[pid]; if (h.active and to_tx_dl_ack(h.last_tti_rx) == tti_rx) { - if (feedback_list.cc_list.size() <= ue_cc_idx) { - feedback_list.cc_list.resize(ue_cc_idx + 1); - } - auto& result = feedback_list.cc_list[ue_cc_idx]; - result.enb_cc_idx = enb_cc_idx; - result.ack = ack_val[ue_cc_idx]; - result.pid = pid; + cc_feedback.dl_pid = pid; + cc_feedback.dl_ack = false; // default is NACK + } + } + } + return {this, sched}; +} - if (result.pid >= 0 and (result.ack or h.nof_retxs + 1 >= ctxt.ue_cfg.maxharq_tx)) { - h.active = false; - } +void ue_sim::push_feedback(sched_interface* sched) +{ + for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_feedback.cc_list.size(); ++enb_cc_idx) { + const auto& cc_feedback = pending_feedback.cc_list[enb_cc_idx]; + if (not cc_feedback.configured) { + continue; + } + + if (cc_feedback.dl_pid >= 0) { + auto& h = ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid]; - ack_added = true; + if (cc_feedback.dl_ack) { + log_h->info( + "DL ACK rnti=0x%x tti_dl_tx=%u pid=%d\n", ctxt.rnti, to_tx_dl(h.last_tti_rx).to_uint(), cc_feedback.dl_pid); + } + // update scheduler + if (sched->dl_ack_info( + pending_feedback.tti_rx.to_uint(), ctxt.rnti, enb_cc_idx, cc_feedback.tb, cc_feedback.dl_ack) < 0) { + log_h->error("The ACKed DL Harq pid=%d does not exist.\n", cc_feedback.dl_pid); + } + + // set UE sim context + if (cc_feedback.dl_ack or ctxt.is_last_dl_retx(cc_feedback.ue_cc_idx, cc_feedback.dl_pid)) { + h.active = false; } } } - - return ack_added; } int ue_sim::update(const sf_output_res_t& sf_out) @@ -248,7 +271,7 @@ void ue_db_sim::add_user(uint16_t rnti, srslte::tti_point prach_tti_rx_, uint32_t preamble_idx) { - ue_db.insert(std::make_pair(rnti, ue_sim(rnti, ue_cfg_, prach_tti_rx_, preamble_idx))); + ue_db.insert(std::make_pair(rnti, ue_sim(rnti, *cell_params, ue_cfg_, prach_tti_rx_, preamble_idx))); } void ue_db_sim::ue_recfg(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_) diff --git a/srsenb/test/mac/sched_sim_ue.h b/srsenb/test/mac/sched_sim_ue.h index d277b5964..870734259 100644 --- a/srsenb/test/mac/sched_sim_ue.h +++ b/srsenb/test/mac/sched_sim_ue.h @@ -53,46 +53,69 @@ struct sim_enb_ctxt_t { const std::vector* cell_params; std::map ue_db; }; -struct pucch_feedback { +struct ue_tti_events { struct cc_data { - uint32_t enb_cc_idx = 0; - int cqi = -1; - int pid = -1; - bool ack = false; + bool configured = false; + uint32_t ue_cc_idx = 0; + int dl_cqi = -1; + int dl_pid = -1; + bool dl_ack = false; + int tb = 0; }; + srslte::tti_point tti_rx; std::vector cc_list; }; class ue_sim { public: - ue_sim(uint16_t rnti_, - const sched_interface::ue_cfg_t& ue_cfg_, - srslte::tti_point prach_tti_rx, - uint32_t preamble_idx); + ue_sim(uint16_t rnti_, + const std::vector& cell_params_, + const sched_interface::ue_cfg_t& ue_cfg_, + srslte::tti_point prach_tti_rx, + uint32_t preamble_idx); void set_cfg(const sched_interface::ue_cfg_t& ue_cfg_); int update(const sf_output_res_t& sf_out); - bool enqueue_pending_acks(srslte::tti_point tti_rx, - pucch_feedback& feedback_list, - std::bitset ack_val); - const sim_ue_ctxt_t& get_ctxt() const { return ctxt; } sim_ue_ctxt_t& get_ctxt() { return ctxt; } + class sync_tti_events + { + public: + sync_tti_events(ue_sim* ue_, sched_interface* sched_) : ue(ue_), sched(sched_) {} + sync_tti_events(const sync_tti_events&) = delete; + sync_tti_events(sync_tti_events&&) = default; + sync_tti_events& operator=(const sync_tti_events&) = delete; + sync_tti_events& operator=(sync_tti_events&&) = default; + ~sync_tti_events() { ue->push_feedback(sched); } + ue_tti_events* operator->() { return &ue->pending_feedback; } + ue_tti_events* operator*() { return &ue->pending_feedback; } + + private: + ue_sim* ue; + sched_interface* sched; + }; + sync_tti_events get_pending_events(srslte::tti_point tti_rx, sched_interface* sched); + private: void update_conn_state(const sf_output_res_t& sf_out); void update_dl_harqs(const sf_output_res_t& sf_out); void update_ul_harqs(const sf_output_res_t& sf_out); + void push_feedback(sched_interface* sched); - sim_ue_ctxt_t ctxt; + srslte::log_ref log_h{"MAC"}; + const std::vector* cell_params; + sim_ue_ctxt_t ctxt; + ue_tti_events pending_feedback; }; class ue_db_sim { public: + ue_db_sim(const std::vector& cell_params_) : cell_params(&cell_params_) {} void add_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_, srslte::tti_point prach_tti_rx_, @@ -106,7 +129,8 @@ public: const ue_sim& at(uint16_t rnti) const { return ue_db.at(rnti); } private: - std::map ue_db; + const std::vector* cell_params; + std::map ue_db; }; } // namespace srsenb diff --git a/srsenb/test/mac/sched_test_common.cc b/srsenb/test/mac/sched_test_common.cc index 8bdd58d3e..13b790dd3 100644 --- a/srsenb/test/mac/sched_test_common.cc +++ b/srsenb/test/mac/sched_test_common.cc @@ -102,29 +102,19 @@ int ue_ctxt_test::new_tti(sched* sched_ptr, srslte::tti_point tti_rx) int ue_ctxt_test::fwd_pending_acks(sched* sched_ptr) { - /* Ack DL HARQs */ - // Checks: - // - Pending DL ACK {cc_idx,rnti,tb} exist in scheduler harqs - // - Pending DL ACK tti_ack correspond to the expected based on tti_tx_dl - while (not pending_dl_acks.empty()) { - auto& p = pending_dl_acks.top(); - if (p.tti_ack > current_tti_rx) { - break; - } - auto& h = ue_ctxt->get_ctxt().cc_list[p.ue_cc_idx].dl_harqs[p.pid]; - CONDERROR(not h.active, "The ACKed DL Harq pid=%d is not active\n", h.pid); - CONDERROR(to_tx_dl(h.last_tti_rx) + FDD_HARQ_DELAY_DL_MS != p.tti_ack, "dl ack hasn't arrived when expected\n"); - CONDERROR(sched_ptr->dl_ack_info(current_tti_rx.to_uint(), rnti, p.cc_idx, p.tb, p.ack) <= 0, - "The ACKed DL Harq pid=%d does not exist.\n", - p.pid); + auto pending_feedback = ue_ctxt->get_pending_events(current_tti_rx, sched_ptr); - if (p.ack) { - log_h->info("DL ACK tti=%u rnti=0x%x pid=%d\n", current_tti_rx.to_uint(), rnti, p.pid); + for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_feedback->cc_list.size(); ++enb_cc_idx) { + auto& cc_feedback = pending_feedback->cc_list[enb_cc_idx]; + if (not cc_feedback.configured) { + continue; } - if (p.ack or ue_ctxt->get_ctxt().is_last_dl_retx(p.ue_cc_idx, p.pid)) { - h.active = false; + + // ACK DL HARQs + if (cc_feedback.dl_pid >= 0) { + auto& h = ue_ctxt->get_ctxt().cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid]; + cc_feedback.dl_ack = randf() < sim_cfg.prob_dl_ack_mask[h.nof_retxs % sim_cfg.prob_dl_ack_mask.size()]; } - pending_dl_acks.pop(); } /* Ack UL HARQs */ @@ -200,23 +190,6 @@ int ue_ctxt_test::schedule_acks(cc_result result) if (cc == nullptr) { return SRSLTE_SUCCESS; } - /* Schedule DL ACKs */ - for (uint32_t i = 0; i < result.dl_result->nof_data_elems; ++i) { - const auto& data = result.dl_result->data[i]; - if (data.dci.rnti != rnti) { - continue; - } - pending_ack_t ack_data; - ack_data.tti_ack = to_tx_dl_ack(current_tti_rx); - ack_data.cc_idx = result.enb_cc_idx; - ack_data.tb = 0; - ack_data.pid = data.dci.pid; - ack_data.ue_cc_idx = data.dci.ue_cc_idx; - uint32_t nof_retx = srsenb::get_nof_retx(data.dci.tb[0].rv); // 0..3 - ack_data.ack = randf() < sim_cfg.prob_dl_ack_mask[nof_retx % sim_cfg.prob_dl_ack_mask.size()]; - - pending_dl_acks.push(ack_data); - } /* Schedule UL ACKs */ for (uint32_t i = 0; i < result.ul_result->nof_dci_elems; ++i) { diff --git a/srsenb/test/mac/sched_test_common.h b/srsenb/test/mac/sched_test_common.h index b1a4fdc89..a08a6d91e 100644 --- a/srsenb/test/mac/sched_test_common.h +++ b/srsenb/test/mac/sched_test_common.h @@ -84,14 +84,14 @@ private: bool ack; bool operator<(const pending_ack_t& other) const { return tti_ack > other.tti_ack; } }; - std::priority_queue pending_dl_acks, pending_ul_acks; + std::priority_queue pending_ul_acks; }; class user_state_sched_tester { public: explicit user_state_sched_tester(const std::vector& cell_params_) : - cell_params(cell_params_) + cell_params(cell_params_), sim_users(cell_params_) {} void new_tti(sched* sched_ptr, tti_point tti_rx);