simplification of scheduling of DL acks in sched tester

master
Francisco 4 years ago committed by Andre Puschmann
parent b86d2ab7d0
commit 86eb315102

@ -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<sched_interface::cell_cfg_t>& 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<SRSLTE_MAX_CARRIERS> 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_)

@ -53,46 +53,69 @@ struct sim_enb_ctxt_t {
const std::vector<sched_interface::cell_cfg_t>* cell_params;
std::map<uint16_t, const sim_ue_ctxt_t*> 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_data> 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<sched_interface::cell_cfg_t>& 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<SRSLTE_MAX_CARRIERS> 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<sched_interface::cell_cfg_t>* cell_params;
sim_ue_ctxt_t ctxt;
ue_tti_events pending_feedback;
};
class ue_db_sim
{
public:
ue_db_sim(const std::vector<sched_interface::cell_cfg_t>& 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<uint16_t, ue_sim> ue_db;
const std::vector<sched_interface::cell_cfg_t>* cell_params;
std::map<uint16_t, ue_sim> ue_db;
};
} // namespace srsenb

@ -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) {

@ -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_ack_t> pending_dl_acks, pending_ul_acks;
std::priority_queue<pending_ack_t> pending_ul_acks;
};
class user_state_sched_tester
{
public:
explicit user_state_sched_tester(const std::vector<srsenb::sched::cell_cfg_t>& cell_params_) :
cell_params(cell_params_)
cell_params(cell_params_), sim_users(cell_params_)
{}
void new_tti(sched* sched_ptr, tti_point tti_rx);

Loading…
Cancel
Save