From fc81a5c6ba04f2f95dfac79959ad633c3ccce905 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 24 Nov 2020 18:27:04 +0000 Subject: [PATCH] harq ack state can now only be NACK or ACK. The ul_harq pending phich flag is now reset after phich scheduling. Thus, the existence of a crc_info(...) signal from the PHY is not required. --- srsenb/hdr/stack/mac/sched_harq.h | 12 +++---- srsenb/src/stack/mac/sched_grid.cc | 6 ++-- srsenb/src/stack/mac/sched_harq.cc | 42 +++++++++++----------- srsenb/src/stack/mac/sched_ue.cc | 4 +-- srsenb/test/mac/sched_test_rand.cc | 25 +------------ srsenb/test/mac/sched_ue_ded_test_suite.cc | 14 ++++---- 6 files changed, 38 insertions(+), 65 deletions(-) diff --git a/srsenb/hdr/stack/mac/sched_harq.h b/srsenb/hdr/stack/mac/sched_harq.h index 07f98fe4e..ecc7dcd93 100644 --- a/srsenb/hdr/stack/mac/sched_harq.h +++ b/srsenb/hdr/stack/mac/sched_harq.h @@ -54,7 +54,7 @@ protected: enum ack_t { NULL_ACK, NACK, ACK }; - ack_t ack_state[SRSLTE_MAX_TB]; + bool ack_state[SRSLTE_MAX_TB]; bool active[SRSLTE_MAX_TB]; std::array ndi = {}; uint32_t id; @@ -95,8 +95,8 @@ private: class ul_harq_proc : public harq_proc { public: - 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); + void new_tx(srslte::tti_point tti, int mcs, int tbs, prb_interval alloc, uint32_t max_retx_); + void new_retx(srslte::tti_point tti_, int* mcs, int* tbs, prb_interval alloc); bool set_ack(uint32_t tb_idx, bool ack); prb_interval get_alloc() const; @@ -104,15 +104,15 @@ public: bool is_adaptive_retx() const; void reset_pending_data(); - bool has_pending_ack() const; - bool get_pending_ack() const; uint32_t get_pending_data() const; + bool has_pending_phich() const; + bool pop_pending_phich(); private: prb_interval allocation; int pending_data; bool is_adaptive; - ack_t pending_ack; + bool pending_phich = false; }; class harq_entity diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 83adcdd0c..ba12f4fd1 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -866,7 +866,7 @@ alloc_outcome_t sf_sched::alloc_ul_user(sched_ue* user, prb_interval alloc) bool has_retx = h->has_pending_retx(); if (has_retx) { prb_interval prev_alloc = h->get_alloc(); - if (prev_alloc == alloc and h->has_pending_ack()) { + if (prev_alloc == alloc and h->has_pending_phich()) { alloc_type = ul_alloc_t::NOADAPT_RETX; } else { alloc_type = ul_alloc_t::ADAPT_RETX; @@ -893,8 +893,8 @@ bool sf_sched::alloc_phich(sched_ue* user, sched_interface::ul_sched_res_t* ul_s ul_harq_proc* h = user->get_ul_harq(tti_params.tti_tx_ul, cell_index); /* Indicate PHICH acknowledgment if needed */ - if (h->has_pending_ack()) { - phich_list.phich = h->get_pending_ack() ? phich_t::ACK : phich_t::NACK; + if (h->has_pending_phich()) { + phich_list.phich = h->pop_pending_phich() ? phich_t::ACK : phich_t::NACK; phich_list.rnti = user->get_rnti(); log_h->debug("SCHED: Allocated PHICH for rnti=0x%x, value=%s\n", user->get_rnti(), diff --git a/srsenb/src/stack/mac/sched_harq.cc b/srsenb/src/stack/mac/sched_harq.cc index 94d0b3414..336162f7d 100644 --- a/srsenb/src/stack/mac/sched_harq.cc +++ b/srsenb/src/stack/mac/sched_harq.cc @@ -45,7 +45,7 @@ void harq_proc::init(uint32_t id_) void harq_proc::reset(uint32_t tb_idx) { - ack_state[tb_idx] = NULL_ACK; + ack_state[tb_idx] = false; active[tb_idx] = false; n_rtx[tb_idx] = 0; tti = tti_point{0}; @@ -76,7 +76,7 @@ bool harq_proc::is_empty(uint32_t tb_idx) const bool harq_proc::has_pending_retx_common(uint32_t tb_idx) const { - return !is_empty(tb_idx) && ack_state[tb_idx] == NACK; + return active[tb_idx] && not ack_state[tb_idx]; } tti_point harq_proc::get_tti() const @@ -90,7 +90,7 @@ int harq_proc::set_ack_common(uint32_t tb_idx, bool ack_) log_h->warning("Received ACK for inactive harq\n"); return SRSLTE_ERROR; } - ack_state[tb_idx] = ack_ ? ACK : NACK; + ack_state[tb_idx] = ack_; log_h->debug("ACK=%d received pid=%d, tb_idx=%d, n_rtx=%d, max_retx=%d\n", ack_, id, tb_idx, n_rtx[tb_idx], max_retx); if (!ack_ && (n_rtx[tb_idx] + 1 >= max_retx)) { Info("SCHED: discarding TB=%d pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", @@ -120,7 +120,7 @@ void harq_proc::new_tx_common(uint32_t tb_idx, tti_point tti_, int mcs, int tbs, void harq_proc::new_retx_common(uint32_t tb_idx, tti_point tti_, int* mcs, int* tbs) { - ack_state[tb_idx] = NACK; + ack_state[tb_idx] = false; tti = tti_; n_rtx[tb_idx]++; if (mcs) { @@ -212,8 +212,7 @@ rbgmask_t dl_harq_proc::get_rbgmask() const bool dl_harq_proc::has_pending_retx(uint32_t tb_idx, uint32_t tti_tx_dl) const { - return (tti_point{tti_tx_dl} >= tti + FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS) and - has_pending_retx_common(tb_idx); + return (tti_point{tti_tx_dl} >= to_tx_dl_ack(tti)) and has_pending_retx_common(tb_idx); } int dl_harq_proc::get_tbs(uint32_t tb_idx) const @@ -245,21 +244,22 @@ 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, 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_) { is_adaptive = false; allocation = alloc; new_tx_common(0, tti_point{tti_}, mcs, tbs, max_retx_); - pending_data = tbs; - pending_ack = NULL_ACK; + pending_data = tbs; + pending_phich = true; } -void ul_harq_proc::new_retx(uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs, prb_interval alloc) +void ul_harq_proc::new_retx(tti_point tti_, int* mcs, int* tbs, prb_interval alloc) { - // If PRBs changed, or there was no CRC (e.g. HARQ is being resumed) - is_adaptive = alloc != allocation or not has_pending_ack(); + // If PRBs changed, or there was no tx in last oportunity (e.g. HARQ is being resumed) + is_adaptive = alloc != allocation or tti_ != to_tx_ul(tti); allocation = alloc; - new_retx_common(tb_idx, tti_point{tti_}, mcs, tbs); + new_retx_common(0, tti_point{tti_}, mcs, tbs); + pending_phich = true; } bool ul_harq_proc::set_ack(uint32_t tb_idx, bool ack_) @@ -267,25 +267,25 @@ bool ul_harq_proc::set_ack(uint32_t tb_idx, bool ack_) if (is_empty()) { return false; } - pending_ack = ack_ ? ACK : NACK; set_ack_common(tb_idx, ack_); return true; } -bool ul_harq_proc::has_pending_ack() const +bool ul_harq_proc::has_pending_phich() const { - return pending_ack != NULL_ACK; + return pending_phich; } -bool ul_harq_proc::get_pending_ack() const +bool ul_harq_proc::pop_pending_phich() { - return pending_ack == ACK; + bool ret = ack_state[0]; + pending_phich = false; + return ret; } void ul_harq_proc::reset_pending_data() { reset_pending_data_common(); - pending_ack = NULL_ACK; if (is_empty(0)) { pending_data = 0; } @@ -301,9 +301,7 @@ uint32_t ul_harq_proc::get_pending_data() const *******************/ harq_entity::harq_entity(size_t nof_dl_harqs, size_t nof_ul_harqs) : - dl_harqs(nof_dl_harqs), - ul_harqs(nof_ul_harqs), - log_h(srslte::logmap::get("MAC ")) + dl_harqs(nof_dl_harqs), ul_harqs(nof_ul_harqs), log_h(srslte::logmap::get("MAC ")) { for (uint32_t i = 0; i < dl_harqs.size(); ++i) { dl_harqs[i].init(i); diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index f270db171..e0e53ecd6 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -785,14 +785,14 @@ 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, mcs, tbs, alloc, nof_retx); + h->new_tx(tti_point{tti}, mcs, tbs, alloc, nof_retx); // Un-trigger the SR if data is allocated if (tbs > 0) { unset_sr(); } } else { // retx - h->new_retx(0, tti, &mcs, nullptr, alloc); + h->new_retx(tti_point{tti}, &mcs, nullptr, alloc); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs, false, true), alloc.length()) / 8; } diff --git a/srsenb/test/mac/sched_test_rand.cc b/srsenb/test/mac/sched_test_rand.cc index 6d3a095bd..adda8ccb6 100644 --- a/srsenb/test/mac/sched_test_rand.cc +++ b/srsenb/test/mac/sched_test_rand.cc @@ -250,35 +250,12 @@ int sched_tester::test_harqs() CONDERROR(h.get_n_cce() != data.dci.location.ncce, "Harq DCI location does not match with result\n"); } - for (uint32_t i = 0; i < tti_info.ul_sched_result[CARRIER_IDX].nof_dci_elems; ++i) { - const auto& pusch = tti_info.ul_sched_result[CARRIER_IDX].pusch[i]; - uint16_t rnti = pusch.dci.rnti; - const auto& ue_data = tti_data.ue_data[rnti]; - const srsenb::ul_harq_proc* h = ue_db[rnti].get_ul_harq(tti_info.tti_params.tti_tx_ul, CARRIER_IDX); - CONDERROR(h == nullptr or h->is_empty(), "scheduled UL harq does not exist or is empty\n"); - CONDERROR(h->get_tti() != tti_point{tti_info.tti_params.tti_tx_ul}, - "The scheduled UL harq does not a valid tti=%u\n", - tti_info.tti_params.tti_tx_ul); - CONDERROR(h->has_pending_ack(), "At the end of the TTI, there shouldnt be any pending ACKs\n"); - - if (h->has_pending_retx()) { - // retx - CONDERROR(ue_data.ul_harq.is_empty(0), "reTx in an UL harq that was empty\n"); - CONDERROR(h->nof_retx(0) != ue_data.ul_harq.nof_retx(0) + 1, - "A retx UL harq was scheduled but with invalid number of retxs\n"); - CONDERROR(h->is_adaptive_retx() and not pusch.needs_pdcch, "Adaptive retxs need PDCCH alloc\n"); - } else { - CONDERROR(h->nof_retx(0) != 0, "A new harq was scheduled but with invalid number of retxs\n"); - CONDERROR(not ue_data.ul_harq.is_empty(0), "UL new tx in a UL harq that was not empty\n"); - } - } - /* Check PHICH allocations */ for (uint32_t i = 0; i < tti_info.ul_sched_result[CARRIER_IDX].nof_phich_elems; ++i) { const auto& phich = tti_info.ul_sched_result[CARRIER_IDX].phich[i]; const auto& hprev = tti_data.ue_data[phich.rnti].ul_harq; const auto* h = ue_db[phich.rnti].get_ul_harq(tti_info.tti_params.tti_tx_ul, CARRIER_IDX); - CONDERROR(not hprev.has_pending_ack(), "Alloc PHICH did not have any pending ack\n"); + CONDERROR(not hprev.has_pending_phich(), "Alloc PHICH did not have any pending ack\n"); bool maxretx_flag = hprev.nof_retx(0) + 1 >= hprev.max_nof_retx(); if (phich.phich == sched_interface::ul_sched_phich_t::ACK) { // The harq can be either ACKed or Resumed diff --git a/srsenb/test/mac/sched_ue_ded_test_suite.cc b/srsenb/test/mac/sched_ue_ded_test_suite.cc index 55f63d888..1b86f69c6 100644 --- a/srsenb/test/mac/sched_ue_ded_test_suite.cc +++ b/srsenb/test/mac/sched_ue_ded_test_suite.cc @@ -151,7 +151,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& continue; } - const auto& h = ue.cc_list[ue_cc_idx].ul_harqs[pid]; + const auto& h = ue.cc_list[ue_cc_idx].ul_harqs[pid]; bool phich_ack = phich_ptr != nullptr and phich_ptr->phich == phich_t::ACK; bool is_msg3 = h.first_tti_rx == ue.msg3_tti_rx and h.nof_txs == h.nof_retxs + 1; bool last_retx = h.nof_retxs + 1 >= (is_msg3 ? sf_out.cc_params[0].cfg.maxharq_msg3tx : ue.ue_cfg.maxharq_tx); @@ -165,7 +165,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& rnti, pid); - // TEST: absent PUSCH grants for active DL HARQs must be either ACKs, last retx, or interrupted HARQs + // TEST: absent PUSCH grants for active UL HARQs must be either ACKs, last retx, or interrupted HARQs if ((phich_ptr != nullptr) and (pusch_ptr == nullptr)) { CONDERROR(not h_inactive, "PHICH NACK received for rnti=0x%x but no PUSCH retx reallocated\n", rnti); } @@ -187,15 +187,13 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& // the HARQ is being resumed CONDERROR(not pusch_ptr->needs_pdcch, "Resumed UL HARQs need to be signalled in PDCCH\n"); } - if (pusch_ptr->needs_pdcch) { - // adaptive retx - CONDERROR(h.tbs != pusch_ptr->tbs, "TBS changed during HARQ retx\n"); - CONDERROR(sched_utils::get_rvidx(h.nof_retxs + 1) != (uint32_t)pusch_ptr->dci.tb.rv, - "Invalid rv index for retx\n"); - } else { + if (not pusch_ptr->needs_pdcch) { // non-adaptive retx CONDERROR(pusch_ptr->dci.type2_alloc.riv != h.riv, "Non-adaptive retx must keep the same riv\n"); } + CONDERROR(sched_utils::get_rvidx(h.nof_retxs + 1) != (uint32_t)pusch_ptr->dci.tb.rv, + "Invalid rv index for retx\n"); + CONDERROR(h.tbs != pusch_ptr->tbs, "TBS changed during HARQ retx\n"); CONDERROR(to_tx_ul(h.last_tti_rx) > sf_out.tti_rx, "UL harq pid=%d was reused too soon\n", h.pid); } }