added check for UCI collision during DL scheduling for CA

master
Francisco Paisana 5 years ago
parent 53b85691b5
commit d859c33035

@ -31,7 +31,7 @@ namespace srslte {
constexpr uint32_t ceil_div(uint32_t x, uint32_t y) constexpr uint32_t ceil_div(uint32_t x, uint32_t y)
{ {
return (x > 0) ? (x - 1) / y + 1 : 0; return (x + y - 1) / y;
} }
template <size_t N, bool reversed = false> template <size_t N, bool reversed = false>

@ -36,7 +36,7 @@ enum class alloc_type_t { DL_BC, DL_PCCH, DL_RAR, DL_DATA, UL_DATA };
//! Result of alloc attempt //! Result of alloc attempt
struct alloc_outcome_t { struct alloc_outcome_t {
enum result_enum { SUCCESS, DCI_COLLISION, RB_COLLISION, ERROR, NOF_RB_INVALID }; enum result_enum { SUCCESS, DCI_COLLISION, RB_COLLISION, ERROR, NOF_RB_INVALID, PUCCH_COLLISION };
result_enum result = ERROR; result_enum result = ERROR;
alloc_outcome_t() = default; alloc_outcome_t() = default;
alloc_outcome_t(result_enum e) : result(e) {} alloc_outcome_t(result_enum e) : result(e) {}
@ -68,6 +68,8 @@ struct sf_sched_result {
{ {
return enb_cc_idx < enb_cc_list.size() ? &enb_cc_list[enb_cc_idx] : nullptr; return enb_cc_idx < enb_cc_list.size() ? &enb_cc_list[enb_cc_idx] : nullptr;
} }
bool is_ul_alloc(uint16_t rnti) const;
bool is_dl_alloc(uint16_t rnti) const;
}; };
struct sched_result_list { struct sched_result_list {
@ -168,6 +170,7 @@ public:
bool reserve_dl_rbgs(uint32_t start_rbg, uint32_t end_rbg); 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); 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); bool reserve_ul_prbs(const prbmask_t& prbmask, bool strict);
bool find_ul_alloc(uint32_t L, ul_harq_proc::ul_alloc_t* alloc) const;
// getters // getters
const rbgmask_t& get_dl_mask() const { return dl_mask; } const rbgmask_t& get_dl_mask() const { return dl_mask; }

@ -40,6 +40,8 @@ const char* alloc_outcome_t::to_string() const
return "error"; return "error";
case NOF_RB_INVALID: case NOF_RB_INVALID:
return "invalid nof prbs"; return "invalid nof prbs";
case PUCCH_COLLISION:
return "pucch_collision";
} }
return "unknown error"; return "unknown error";
} }
@ -60,6 +62,29 @@ cc_sched_result* sf_sched_result::new_cc(uint32_t enb_cc_idx)
return &enb_cc_list[enb_cc_idx]; return &enb_cc_list[enb_cc_idx];
} }
bool sf_sched_result::is_ul_alloc(uint16_t rnti) const
{
for (uint32_t i = 0; i < enb_cc_list.size(); ++i) {
for (uint32_t j = 0; j < enb_cc_list[i].ul_sched_result.nof_dci_elems; ++j) {
if (enb_cc_list[i].ul_sched_result.pusch[j].dci.rnti == rnti) {
return true;
}
}
}
return false;
}
bool sf_sched_result::is_dl_alloc(uint16_t rnti) const
{
for (uint32_t i = 0; i < enb_cc_list.size(); ++i) {
for (uint32_t j = 0; j < enb_cc_list[i].dl_sched_result.nof_data_elems; ++j) {
if (enb_cc_list[i].dl_sched_result.data[j].dci.rnti == rnti) {
return true;
}
}
}
return false;
}
sf_sched_result* sched_result_list::new_tti(srslte::tti_point tti_rx) sf_sched_result* sched_result_list::new_tti(srslte::tti_point tti_rx)
{ {
sf_sched_result* res = &results[tti_rx.to_uint() % results.size()]; sf_sched_result* res = &results[tti_rx.to_uint() % results.size()];
@ -500,6 +525,42 @@ bool sf_grid_t::reserve_ul_prbs(const prbmask_t& prbmask, bool strict)
return ret; return ret;
} }
/**
* Finds a range of L contiguous PRBs that are empty
* @param L Size of the requested UL allocation in PRBs
* @param alloc Found allocation. It is guaranteed that 0 <= alloc->L <= L
* @return true if the requested allocation of size L was strictly met
*/
bool sf_grid_t::find_ul_alloc(uint32_t L, ul_harq_proc::ul_alloc_t* alloc) const
{
*alloc = {};
for (uint32_t n = 0; n < ul_mask.size() && alloc->L < L; n++) {
if (not ul_mask.test(n) && alloc->L == 0) {
alloc->RB_start = n;
}
if (not ul_mask.test(n)) {
alloc->L++;
} else if (alloc->L > 0) {
// avoid edges
if (n < 3) {
alloc->RB_start = 0;
alloc->L = 0;
} else {
break;
}
}
}
if (alloc->L == 0) {
return false;
}
// Make sure L is allowed by SC-FDMA modulation
while (!srslte_dft_precoding_valid_prb(alloc->L)) {
alloc->L--;
}
return alloc->L == L;
}
/******************************************************* /*******************************************************
* TTI resource Scheduling Methods * TTI resource Scheduling Methods
*******************************************************/ *******************************************************/
@ -691,6 +752,28 @@ alloc_outcome_t sf_sched::alloc_dl_user(sched_ue* user, const rbgmask_t& user_ma
} }
} }
// Check if there is space in the PUCCH for HARQ ACKs
const sched_interface::ue_cfg_t& ue_cfg = user->get_ue_cfg();
bool has_scells = ue_cfg.supported_cc_list.size() > 1;
const srslte_cqi_report_cfg_t& cqi_report = ue_cfg.dl_cfg.cqi_report;
if (has_scells and srslte_cqi_periodic_send(&cqi_report, get_tti_tx_ul(), SRSLTE_FDD)) {
bool has_pusch_grant = is_ul_alloc(user) or cc_results->is_ul_alloc(user->get_rnti());
bool has_dl_allocs = cc_results->is_dl_alloc(user->get_rnti());
if (not has_pusch_grant and has_dl_allocs) {
// Try to allocate small PUSCH grant, if there are no pending UL retxs
ul_harq_proc* hul = user->get_ul_harq(get_tti_tx_ul(), ue_cc_idx);
bool has_retx = hul->has_pending_retx();
if (not has_retx) {
ul_harq_proc::ul_alloc_t alloc = {};
uint32_t L = user->get_required_prb_ul(ue_cc_idx, srslte::ceil_div(SRSLTE_UCI_CQI_CODED_PUCCH_B + 2, 8));
tti_alloc.find_ul_alloc(L, &alloc);
if (alloc.L == 0 or not alloc_ul_user(user, alloc)) {
return alloc_outcome_t::PUCCH_COLLISION;
}
}
}
}
// Try to allocate RBGs and DCI // Try to allocate RBGs and DCI
alloc_outcome_t ret = tti_alloc.alloc_dl_data(user, user_mask); alloc_outcome_t ret = tti_alloc.alloc_dl_data(user, user_mask);
if (ret != alloc_outcome_t::SUCCESS) { if (ret != alloc_outcome_t::SUCCESS) {

Loading…
Cancel
Save