add measgap awareness to scheduler metric and sf_sched. Add measGap test to random sched test suite.

master
Francisco Paisana 4 years ago committed by Andre Puschmann
parent 2b05d5a67c
commit 49a48c0130

@ -36,7 +36,7 @@ enum class alloc_type_t { DL_BC, DL_PCCH, DL_RAR, DL_DATA, UL_DATA };
//! Result of alloc attempt
struct alloc_outcome_t {
enum result_enum { SUCCESS, DCI_COLLISION, RB_COLLISION, ERROR, NOF_RB_INVALID, PUCCH_COLLISION };
enum result_enum { SUCCESS, DCI_COLLISION, RB_COLLISION, ERROR, NOF_RB_INVALID, PUCCH_COLLISION, MEASGAP_COLLISION };
result_enum result = ERROR;
alloc_outcome_t() = default;
alloc_outcome_t(result_enum e) : result(e) {}

@ -44,6 +44,8 @@ const char* alloc_outcome_t::to_string() const
return "invalid nof prbs";
case PUCCH_COLLISION:
return "pucch_collision";
case MEASGAP_COLLISION:
return "measgap_collision";
}
return "unknown error";
}
@ -769,10 +771,17 @@ alloc_outcome_t sf_sched::alloc_dl_user(sched_ue* user, const rbgmask_t& user_ma
log_h->warning("SCHED: Attempt to assign multiple harq pids to the same user rnti=0x%x\n", user->get_rnti());
return alloc_outcome_t::ERROR;
}
auto* cc = user->find_ue_carrier(cc_cfg->enb_cc_idx);
if (cc == nullptr or cc->cc_state() != cc_st::active) {
return alloc_outcome_t::ERROR;
}
uint32_t ue_cc_idx = cc->get_ue_cc_idx();
if (not user->pdsch_enabled(srslte::tti_point{get_tti_rx()}, cc_cfg->enb_cc_idx)) {
return alloc_outcome_t::MEASGAP_COLLISION;
}
// Check if allocation would cause segmentation
uint32_t ue_cc_idx = user->enb_to_ue_cc_idx(cc_cfg->enb_cc_idx);
const dl_harq_proc& h = user->get_dl_harq(pid, ue_cc_idx);
const dl_harq_proc& h = user->get_dl_harq(pid, ue_cc_idx);
if (h.is_empty()) {
// It is newTx
rbg_interval r = user->get_required_dl_rbgs(ue_cc_idx);
@ -826,9 +835,14 @@ alloc_outcome_t sf_sched::alloc_ul(sched_ue* user, prb_interval alloc, ul_alloc_
return alloc_outcome_t::ERROR;
}
// Check if there is no collision with measGap
bool needs_pdcch = alloc_type == ul_alloc_t::ADAPT_RETX or alloc_type == ul_alloc_t::NEWTX;
if (not user->pusch_enabled(srslte::tti_point{get_tti_rx()}, cc_cfg->enb_cc_idx, needs_pdcch)) {
return alloc_outcome_t::MEASGAP_COLLISION;
}
// Allocate RBGs and DCI space
bool needs_pdcch = alloc_type == ul_alloc_t::ADAPT_RETX or alloc_type == ul_alloc_t::NEWTX;
alloc_outcome_t ret = tti_alloc.alloc_ul_data(user, alloc, needs_pdcch);
alloc_outcome_t ret = tti_alloc.alloc_ul_data(user, alloc, needs_pdcch);
if (ret != alloc_outcome_t::SUCCESS) {
return ret;
}

@ -94,6 +94,9 @@ dl_harq_proc* dl_metric_rr::allocate_user(sched_ue* user)
return nullptr;
}
uint32_t cell_idx = p.second;
if (not user->pdsch_enabled(srslte::tti_point(tti_alloc->get_tti_tx_dl() - TX_ENB_DELAY), cc_cfg->enb_cc_idx)) {
return nullptr;
}
alloc_outcome_t code;
uint32_t tti_dl = tti_alloc->get_tti_tx_dl();
@ -245,8 +248,9 @@ ul_harq_proc* ul_metric_rr::allocate_user_retx_prbs(sched_ue* user)
}
uint32_t cell_idx = p.second;
alloc_outcome_t ret;
ul_harq_proc* h = user->get_ul_harq(current_tti, cell_idx);
alloc_outcome_t ret;
ul_harq_proc* h = user->get_ul_harq(current_tti, cell_idx);
srslte::tti_point tti_rx{current_tti - (TX_ENB_DELAY + FDD_HARQ_DELAY_DL_MS)};
// if there are procedures and we have space
if (h->has_pending_retx()) {
@ -287,6 +291,12 @@ ul_harq_proc* ul_metric_rr::allocate_user_newtx_prbs(sched_ue* user)
}
uint32_t cell_idx = p.second;
// Avoid measGaps
if (not user->pusch_enabled(
srslte::tti_point{current_tti - (TX_ENB_DELAY + FDD_HARQ_DELAY_DL_MS)}, cc_cfg->enb_cc_idx, true)) {
return nullptr;
}
uint32_t pending_data = user->get_pending_ul_new_data(current_tti, cell_idx);
ul_harq_proc* h = user->get_ul_harq(current_tti, cell_idx);

@ -301,7 +301,8 @@ bool sched_ue::pucch_sr_collision(uint32_t tti, uint32_t n_cce)
tti_point prev_meas_gap_start(tti_point tti, uint32_t period, uint32_t offset)
{
return tti_point{static_cast<uint32_t>(floor(static_cast<float>((tti - offset).to_uint()) / period))};
return tti_point{static_cast<uint32_t>(floor(static_cast<float>((tti - offset).to_uint()) / period)) * period +
offset};
}
tti_point next_meas_gap_start(tti_point tti, uint32_t period, uint32_t offset)
@ -311,7 +312,8 @@ tti_point next_meas_gap_start(tti_point tti, uint32_t period, uint32_t offset)
tti_point nearest_meas_gap(tti_point tti, uint32_t period, uint32_t offset)
{
return tti_point{static_cast<uint32_t>(round(static_cast<float>((tti - offset).to_uint()) / period))};
return tti_point{static_cast<uint32_t>(round(static_cast<float>((tti - offset).to_uint()) / period)) * period +
offset};
}
bool sched_ue::pdsch_enabled(srslte::tti_point tti_rx, uint32_t enb_cc_idx) const
@ -342,17 +344,16 @@ bool sched_ue::pusch_enabled(srslte::tti_point tti_rx, uint32_t enb_cc_idx, bool
// Check measGap collision
if (cfg.measgap_period > 0) {
tti_point tti_tx_ul = to_tx_ul(tti_rx), tti_tx_ul_ack = to_tx_ul_ack(tti_rx);
tti_point tti_tx_dl = to_tx_dl(tti_rx);
tti_point tti_tx_ul = to_tx_ul(tti_rx);
tti_point mgap_tti = nearest_meas_gap(tti_tx_ul, cfg.measgap_period, cfg.measgap_offset);
tti_interval meas_gap{mgap_tti, mgap_tti + 6};
// disable TTIs that leads to PUSCH tx or PHICH rx falling in measGap
if (meas_gap.contains(tti_tx_ul) or meas_gap.contains(tti_tx_ul_ack)) {
if (meas_gap.contains(tti_tx_ul) or meas_gap.contains(to_tx_ul_ack(tti_rx))) {
return false;
}
// disable TTIs which respective PDCCH falls in measGap (in case PDCCH is needed)
if (needs_pdcch and meas_gap.contains(tti_tx_dl)) {
if (needs_pdcch and meas_gap.contains(to_tx_dl(tti_rx))) {
return false;
}
}

@ -27,6 +27,7 @@ namespace srsenb {
using phich_t = sched_interface::ul_sched_phich_t;
using pusch_t = sched_interface::ul_sched_data_t;
using pdsch_t = sched_interface::dl_sched_data_t;
const sched_interface::ue_cfg_t::cc_cfg_t* sim_ue_ctxt_t::get_cc_cfg(uint32_t enb_cc_idx) const
{
@ -47,6 +48,22 @@ int sim_ue_ctxt_t::enb_to_ue_cc_idx(uint32_t enb_cc_idx) const
return it == ue_cfg.supported_cc_list.end() ? -1 : std::distance(ue_cfg.supported_cc_list.begin(), it);
}
const pusch_t* find_pusch_grant(uint16_t rnti, const sched_interface::ul_sched_res_t& ul_cc_res)
{
const pusch_t* ptr = std::find_if(&ul_cc_res.pusch[0],
&ul_cc_res.pusch[ul_cc_res.nof_dci_elems],
[rnti](const pusch_t& pusch) { return pusch.dci.rnti == rnti; });
return ptr == &ul_cc_res.pusch[ul_cc_res.nof_dci_elems] ? nullptr : ptr;
}
const pdsch_t* find_pdsch_grant(uint16_t rnti, const sched_interface::dl_sched_res_t& dl_cc_res)
{
const pdsch_t* ptr = std::find_if(&dl_cc_res.data[0],
&dl_cc_res.data[dl_cc_res.nof_data_elems],
[rnti](const pdsch_t& pdsch) { return pdsch.dci.rnti == rnti; });
return ptr == &dl_cc_res.data[dl_cc_res.nof_data_elems] ? nullptr : ptr;
}
int test_pdsch_grant(const sim_ue_ctxt_t& ue_ctxt,
srslte::tti_point tti_rx,
uint32_t enb_cc_idx,
@ -124,10 +141,8 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t&
const phich_t* phich_ptr =
std::find_if(phich_begin, phich_end, [rnti](const phich_t& phich) { return phich.rnti == rnti; });
phich_ptr = phich_ptr == phich_end ? nullptr : phich_ptr;
const pusch_t* pusch_ptr =
std::find_if(pusch_begin, pusch_end, [rnti](const pusch_t& pusch) { return pusch.dci.rnti == rnti; });
pusch_ptr = pusch_ptr == pusch_end ? nullptr : pusch_ptr;
phich_ptr = phich_ptr == phich_end ? nullptr : phich_ptr;
const pusch_t* pusch_ptr = find_pusch_grant(rnti, sf_out.ul_cc_result[cc]);
// TEST: Check that idle CCs do not receive PUSCH grants or PHICH
if (ue_cc_idx < 0 or not ue.ue_cfg.supported_cc_list[ue_cc_idx].active) {
@ -136,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);
@ -319,6 +334,43 @@ int test_ra(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
return SRSLTE_SUCCESS;
}
bool is_in_measgap(srslte::tti_point tti, uint32_t period, uint32_t offset)
{
uint32_t T = period / 10;
return (tti.sfn() % T == offset / 10) and (tti.sf_idx() == offset % 10);
}
int test_meas_gaps(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
{
for (uint32_t cc = 0; cc < enb_ctxt.cell_params->size(); ++cc) {
const auto& dl_cc_res = sf_out.dl_cc_result[cc];
const auto& ul_cc_res = sf_out.ul_cc_result[cc];
for (const auto& ue_pair : enb_ctxt.ue_db) {
const auto& ue = *ue_pair.second;
uint16_t rnti = ue.rnti;
uint32_t ue_cc_idx = ue.enb_to_ue_cc_idx(cc);
srslte::tti_point tti_tx_ul = to_tx_ul(sf_out.tti_rx), tti_tx_dl = to_tx_dl(sf_out.tti_rx),
tti_tx_dl_ack = to_tx_dl_ack(sf_out.tti_rx), tti_tx_phich = to_tx_ul_ack(sf_out.tti_rx);
if (ue_cc_idx != 0 or ue.ue_cfg.measgap_period == 0) {
continue;
}
if (is_in_measgap(tti_tx_ul, ue.ue_cfg.measgap_period, ue.ue_cfg.measgap_offset) or
is_in_measgap(tti_tx_phich, ue.ue_cfg.measgap_period, ue.ue_cfg.measgap_offset)) {
const pusch_t* pusch_ptr = find_pusch_grant(rnti, ul_cc_res);
CONDERROR(pusch_ptr != nullptr, "PUSCH grants and PHICH cannot fall in UE measGap\n");
}
if (is_in_measgap(tti_tx_dl, ue.ue_cfg.measgap_period, ue.ue_cfg.measgap_offset) or
is_in_measgap(tti_tx_dl_ack, ue.ue_cfg.measgap_period, ue.ue_cfg.measgap_offset)) {
const pdsch_t* pdsch_ptr = find_pdsch_grant(rnti, dl_cc_res);
CONDERROR(pdsch_ptr != nullptr, "PDSCH grants and respective ACKs cannot fall in UE measGap\n");
}
}
}
return SRSLTE_SUCCESS;
}
int test_all_ues(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
{
TESTASSERT(test_dl_sched_result(enb_ctxt, sf_out) == SRSLTE_SUCCESS);
@ -327,6 +379,8 @@ int test_all_ues(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
TESTASSERT(test_ra(enb_ctxt, sf_out) == SRSLTE_SUCCESS);
TESTASSERT(test_meas_gaps(enb_ctxt, sf_out) == SRSLTE_SUCCESS);
return SRSLTE_SUCCESS;
}

@ -64,6 +64,8 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t&
*/
int test_ra(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out);
int test_meas_gaps(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out);
/**
* Call all tests that depend on the UE internal state for all registered UEs in the eNB
* @param enb_ctxt current eNB state, including list of UEs

@ -264,7 +264,7 @@ int user_state_sched_tester::add_user(uint16_t rnti, uint32_t preamble_idx, cons
cell_params[cfg_.ue_cfg.supported_cc_list[0].enb_cc_idx].prach_config, tic.to_uint(), -1),
"New user added in a non-PRACH TTI\n");
TESTASSERT(users.count(rnti) == 0);
sim_users.add_user(rnti, cfg_.ue_cfg, tic, preamble_idx);
sim_users.add_user(rnti, generate_rach_ue_cfg(cfg_.ue_cfg), tic, preamble_idx);
ue_ctxt_test ue{rnti, tic, cfg_, sim_users.at(rnti)};
users.insert(std::make_pair(rnti, ue));

@ -335,6 +335,12 @@ void test_scheduler_rand(sched_sim_events sim)
tester.test_next_ttis(sim.tti_events);
}
template <typename T>
T pick_random_uniform(std::initializer_list<T> v)
{
return *(v.begin() + std::uniform_int_distribution<size_t>{0, v.size()}(srsenb::get_rand_gen()));
}
sched_sim_events rand_sim_params(uint32_t nof_ttis)
{
auto boolean_dist = []() { return std::uniform_int_distribution<>{0, 1}(srsenb::get_rand_gen()); };
@ -356,8 +362,11 @@ sched_sim_events rand_sim_params(uint32_t nof_ttis)
sim_gen.sim_args.default_ue_sim_cfg.ue_cfg = generate_default_ue_cfg();
sim_gen.sim_args.default_ue_sim_cfg.periodic_cqi = true;
sim_gen.sim_args.default_ue_sim_cfg.ue_cfg.maxharq_tx = std::uniform_int_distribution<>{1, 5}(srsenb::get_rand_gen());
sim_gen.sim_args.start_tti = 0;
sim_gen.sim_args.sim_log = log_global.get();
sim_gen.sim_args.default_ue_sim_cfg.ue_cfg.measgap_period = pick_random_uniform({0, 40, 80});
sim_gen.sim_args.default_ue_sim_cfg.ue_cfg.measgap_offset = std::uniform_int_distribution<uint32_t>{
0, sim_gen.sim_args.default_ue_sim_cfg.ue_cfg.measgap_period}(srsenb::get_rand_gen());
sim_gen.sim_args.start_tti = 0;
sim_gen.sim_args.sim_log = log_global.get();
sim_gen.sim_args.sched_args.pdsch_mcs =
boolean_dist() ? -1 : std::uniform_int_distribution<>{0, 24}(srsenb::get_rand_gen());
sim_gen.sim_args.sched_args.pusch_mcs =

Loading…
Cancel
Save