mirror of https://github.com/PentHertz/srsLTE.git
created new separate ue class in sched tester to handle acks and harq tests
This commit is contained in:
parent
2ea78c8feb
commit
500a7f6357
|
@ -119,6 +119,13 @@ inline uint32_t get_rvidx(uint32_t retx_idx)
|
|||
return rv_idx[retx_idx % 4];
|
||||
}
|
||||
|
||||
//! Obtain nof retxs from rvidx.
|
||||
inline uint32_t get_nof_retx(uint32_t rv_idx)
|
||||
{
|
||||
const static uint32_t nof_retxs[4] = {0, 3, 1, 2};
|
||||
return nof_retxs[rv_idx % 4];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate possible CCE locations a user can use to allocate DCIs
|
||||
* @param regs Regs data for the given cell configuration
|
||||
|
|
|
@ -50,7 +50,7 @@ protected:
|
|||
void new_tx_common(uint32_t tb_idx, srslte::tti_point tti, int mcs, int tbs);
|
||||
void new_retx_common(uint32_t tb_idx, srslte::tti_point tti, int* mcs, int* tbs);
|
||||
bool has_pending_retx_common(uint32_t tb_idx) const;
|
||||
void set_ack_common(uint32_t tb_idx, bool ack);
|
||||
int set_ack_common(uint32_t tb_idx, bool ack);
|
||||
void reset_pending_data_common();
|
||||
|
||||
enum ack_t { NULL_ACK, NACK, ACK };
|
||||
|
@ -75,7 +75,7 @@ public:
|
|||
dl_harq_proc();
|
||||
void new_tx(const rbgmask_t& new_mask, uint32_t tb_idx, uint32_t tti, int mcs, int tbs, uint32_t n_cce_);
|
||||
void new_retx(const rbgmask_t& new_mask, uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs, uint32_t n_cce_);
|
||||
void set_ack(uint32_t tb_idx, bool ack);
|
||||
int set_ack(uint32_t tb_idx, bool ack);
|
||||
rbgmask_t get_rbgmask() const;
|
||||
bool has_pending_retx(uint32_t tb_idx, uint32_t tti) const;
|
||||
int get_tbs(uint32_t tb_idx) const;
|
||||
|
|
|
@ -89,8 +89,12 @@ tti_point harq_proc::get_tti() const
|
|||
return tti;
|
||||
}
|
||||
|
||||
void harq_proc::set_ack_common(uint32_t tb_idx, bool ack_)
|
||||
int harq_proc::set_ack_common(uint32_t tb_idx, bool ack_)
|
||||
{
|
||||
if (is_empty(tb_idx)) {
|
||||
log_h->warning("Received ACK for inactive harq\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
ack_state[tb_idx] = ack_ ? ACK : NACK;
|
||||
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)) {
|
||||
|
@ -103,6 +107,7 @@ void harq_proc::set_ack_common(uint32_t tb_idx, bool ack_)
|
|||
} else if (ack_) {
|
||||
active[tb_idx] = false;
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void harq_proc::new_tx_common(uint32_t tb_idx, tti_point tti_, int mcs, int tbs)
|
||||
|
@ -188,9 +193,9 @@ void dl_harq_proc::new_retx(const rbgmask_t& new_mask,
|
|||
new_retx_common(tb_idx, tti_point{tti_}, mcs, tbs);
|
||||
}
|
||||
|
||||
void dl_harq_proc::set_ack(uint32_t tb_idx, bool ack)
|
||||
int dl_harq_proc::set_ack(uint32_t tb_idx, bool ack)
|
||||
{
|
||||
set_ack_common(tb_idx, ack);
|
||||
return set_ack_common(tb_idx, ack);
|
||||
}
|
||||
|
||||
uint32_t dl_harq_proc::get_n_cce() const
|
||||
|
@ -354,9 +359,11 @@ std::pair<uint32_t, int> harq_entity::set_ack_info(uint32_t tti_rx, uint32_t tb_
|
|||
{
|
||||
for (auto& h : dl_harqs) {
|
||||
if (h.get_tti() + FDD_HARQ_DELAY_DL_MS == tti_point{tti_rx}) {
|
||||
h.set_ack(tb_idx, ack);
|
||||
if (h.set_ack(tb_idx, ack) == SRSLTE_SUCCESS) {
|
||||
return {h.get_id(), h.get_tbs(tb_idx)};
|
||||
}
|
||||
return {h.get_id(), -1};
|
||||
}
|
||||
}
|
||||
return {dl_harqs.size(), -1};
|
||||
}
|
||||
|
|
|
@ -258,12 +258,12 @@ bool sched_ue::pucch_sr_collision(uint32_t current_tti, uint32_t n_cce)
|
|||
|
||||
int sched_ue::set_ack_info(uint32_t tti_rx, uint32_t enb_cc_idx, uint32_t tb_idx, bool ack)
|
||||
{
|
||||
int ret = -1;
|
||||
int tbs_acked = -1;
|
||||
auto p = get_cell_index(enb_cc_idx);
|
||||
if (p.first) {
|
||||
std::pair<uint32_t, int> p2 = carriers[p.second].harq_ent.set_ack_info(tti_rx, tb_idx, ack);
|
||||
ret = p2.second;
|
||||
if (ret > 0) {
|
||||
tbs_acked = p2.second;
|
||||
if (tbs_acked > 0) {
|
||||
Debug("SCHED: Set ACK=%d for rnti=0x%x, pid=%d, tb=%d, tti=%d\n", ack, rnti, p2.first, tb_idx, tti_rx);
|
||||
} else {
|
||||
Warning("SCHED: Received ACK info for unknown TTI=%d\n", tti_rx);
|
||||
|
@ -271,7 +271,7 @@ int sched_ue::set_ack_info(uint32_t tti_rx, uint32_t enb_cc_idx, uint32_t tb_idx
|
|||
} else {
|
||||
log_h->warning("Received DL ACK for invalid cell index %d\n", enb_cc_idx);
|
||||
}
|
||||
return ret;
|
||||
return tbs_acked;
|
||||
}
|
||||
|
||||
void sched_ue::ul_recv_len(uint32_t lcid, uint32_t len)
|
||||
|
@ -909,7 +909,7 @@ std::pair<uint32_t, uint32_t> sched_ue::get_requested_dl_bytes(uint32_t ue_cc_id
|
|||
|
||||
/* Set Minimum boundary */
|
||||
min_data = srb0_data;
|
||||
if (pending_ces.front() == ce_cmd::CON_RES_ID) {
|
||||
if (not pending_ces.empty() and pending_ces.front() == ce_cmd::CON_RES_ID) {
|
||||
min_data += srslte::ce_total_size(pending_ces.front());
|
||||
}
|
||||
if (min_data == 0) {
|
||||
|
|
|
@ -298,6 +298,180 @@ int output_sched_tester::test_all(const tti_params_t& tti_par
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************
|
||||
* User State Tester
|
||||
***********************/
|
||||
|
||||
ue_state::ue_state(uint16_t rnti_, const sched::ue_cfg_t& ue_cfg_) : rnti(rnti_)
|
||||
{
|
||||
set_cfg(ue_cfg_);
|
||||
}
|
||||
|
||||
int ue_state::set_cfg(const sched::ue_cfg_t& ue_cfg_)
|
||||
{
|
||||
for (uint32_t ue_cc_idx = 0; ue_cc_idx < ue_cfg_.supported_cc_list.size(); ++ue_cc_idx) {
|
||||
const auto& cc = ue_cfg_.supported_cc_list[ue_cc_idx];
|
||||
if (ue_cc_idx >= active_ccs.size()) {
|
||||
// new cell
|
||||
active_ccs.emplace_back();
|
||||
active_ccs.back().ue_cc_idx = active_ccs.size() - 1;
|
||||
active_ccs.back().enb_cc_idx = cc.enb_cc_idx;
|
||||
for (size_t i = 0; i < active_ccs.back().dl_harqs.size(); ++i) {
|
||||
active_ccs.back().dl_harqs[i].pid = i;
|
||||
}
|
||||
} else {
|
||||
CONDERROR(cc.enb_cc_idx != active_ccs[ue_cc_idx].enb_cc_idx, "changing ccs not supported\n");
|
||||
}
|
||||
}
|
||||
|
||||
user_cfg = ue_cfg_;
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
ue_state::cc_state_t* ue_state::get_cc_state(uint32_t enb_cc_idx)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
active_ccs.begin(), active_ccs.end(), [enb_cc_idx](const cc_state_t& c) { return c.enb_cc_idx == enb_cc_idx; });
|
||||
return it == active_ccs.end() ? nullptr : &(*it);
|
||||
}
|
||||
|
||||
int ue_state::new_tti(sched* sched_ptr, srslte::tti_point tti_rx)
|
||||
{
|
||||
current_tti_rx = tti_rx;
|
||||
|
||||
TESTASSERT(fwd_pending_acks(sched_ptr) == SRSLTE_SUCCESS);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int ue_state::fwd_pending_acks(sched* sched_ptr)
|
||||
{
|
||||
/* Ack DL HARQs */
|
||||
// Checks:
|
||||
// - Pending DL ACK {cc_idx,rnti,tb} exist in scheduler
|
||||
while (not pending_dl_acks.empty()) {
|
||||
auto& p = pending_dl_acks.top();
|
||||
if (p.tti_ack > current_tti_rx) {
|
||||
break;
|
||||
}
|
||||
auto& h = active_ccs[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(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);
|
||||
|
||||
if (p.ack) {
|
||||
h.active = false;
|
||||
log_h->info("DL ACK tti=%u rnti=0x%x pid=%d\n", current_tti_rx.to_uint(), rnti, p.pid);
|
||||
}
|
||||
pending_dl_acks.pop();
|
||||
}
|
||||
|
||||
/* Ack UL HARQs */
|
||||
auto& p2 = pending_ul_acks[current_tti_rx.to_uint() % pending_ul_acks.size()];
|
||||
if (p2.tti_ack == current_tti_rx) {
|
||||
TESTASSERT(sched_ptr->ul_crc_info(current_tti_rx.to_uint(), rnti, p2.cc_idx, p2.ack) == SRSLTE_SUCCESS);
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int ue_state::process_sched_result(uint32_t enb_cc_idx,
|
||||
const sched::dl_sched_res_t& dl_result,
|
||||
const sched::ul_sched_res_t& ul_result)
|
||||
{
|
||||
cc_result result{enb_cc_idx, &dl_result, &ul_result};
|
||||
TESTASSERT(test_harqs(result) == SRSLTE_SUCCESS);
|
||||
TESTASSERT(schedule_acks(result) == SRSLTE_SUCCESS);
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanity checks of the DCI values in the scheduling result for a given user. Current checks:
|
||||
* - invalid ue_cc_idx<->enb_cc_idx matching in dl_result
|
||||
* - invalid pid value
|
||||
* - invalid rv value (nof retxs is incorrect) and ndi value
|
||||
*/
|
||||
int ue_state::test_harqs(cc_result result)
|
||||
{
|
||||
cc_state_t* cc = get_cc_state(result.enb_cc_idx);
|
||||
if (cc == nullptr) {
|
||||
// unsupported carrier
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
CONDERROR(data.dci.ue_cc_idx != cc->ue_cc_idx, "invalid ue_cc_idx=%d in sched result\n", data.dci.ue_cc_idx);
|
||||
CONDERROR(data.dci.pid >= cc->dl_harqs.size(), "invalid pid\n");
|
||||
auto& h = cc->dl_harqs[data.dci.pid];
|
||||
uint32_t nof_retx = sched_utils::get_nof_retx(data.dci.tb[0].rv); // 0..3
|
||||
|
||||
if (h.nof_txs == 0 or h.ndi != data.dci.tb[0].ndi) {
|
||||
// It is newtx
|
||||
CONDERROR(nof_retx != 0, "Invalid rv index for new tx\n");
|
||||
|
||||
h.active = true;
|
||||
h.nof_retxs = 0;
|
||||
h.ndi = data.dci.tb[0].ndi;
|
||||
h.tti_tx = srslte::to_tx_dl(current_tti_rx);
|
||||
} else {
|
||||
// it is retx
|
||||
CONDERROR(sched_utils::get_rvidx(h.nof_retxs + 1) != (uint32_t)data.dci.tb[0].rv, "Invalid rv index for retx\n");
|
||||
CONDERROR(h.ndi != data.dci.tb[0].ndi, "Invalid ndi for retx\n");
|
||||
CONDERROR(not h.active, "retx for inactive dl harq pid=%d\n", h.pid);
|
||||
CONDERROR(h.tti_tx + FDD_HARQ_DELAY_UL_MS > current_tti_rx, "harq pid=%d reused too soon\n", h.pid);
|
||||
|
||||
h.nof_retxs++;
|
||||
h.tti_tx = srslte::to_tx_dl(current_tti_rx);
|
||||
}
|
||||
h.nof_txs++;
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int ue_state::schedule_acks(cc_result result)
|
||||
{
|
||||
// schedule future 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 = srslte::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 = sched_utils::get_nof_retx(data.dci.tb[0].rv); // 0..3
|
||||
ack_data.ack = randf() < prob_dl_ack_mask[nof_retx % prob_dl_ack_mask.size()];
|
||||
|
||||
pending_dl_acks.push(ack_data);
|
||||
}
|
||||
|
||||
// /* Schedule UL ACKs */
|
||||
// for (uint32_t i = 0; i < tti_info.ul_sched_result[ccidx].nof_dci_elems; ++i) {
|
||||
// const auto& pusch = tti_info.ul_sched_result[ccidx].pusch[i];
|
||||
// ul_ack_info_t ack_data;
|
||||
// ack_data.rnti = pusch.dci.rnti;
|
||||
// ack_data.enb_cc_idx = ccidx;
|
||||
// ack_data.ue_cc_idx = ue_db[ack_data.rnti].get_cell_index(ccidx).second;
|
||||
// ack_data.ul_harq = *ue_db[ack_data.rnti].get_ul_harq(tti_info.tti_params.tti_tx_ul, ack_data.ue_cc_idx);
|
||||
// ack_data.tti_tx_ul = tti_info.tti_params.tti_tx_ul;
|
||||
// ack_data.tti_ack = tti_info.tti_params.tti_tx_ul + FDD_HARQ_DELAY_UL_MS;
|
||||
// if (ack_data.ul_harq.nof_retx(0) == 0) {
|
||||
// ack_data.ack = randf() > sim_args0.P_retx;
|
||||
// } else {
|
||||
// ack_data.ack = ack_data.ul_harq.nof_retx(0) == 2;
|
||||
// }
|
||||
// to_ul_ack.insert(std::make_pair(ack_data.tti_tx_ul, ack_data));
|
||||
// }
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int srsenb::extract_dl_prbmask(const srslte_cell_t& cell,
|
||||
const srslte_dci_dl_t& dci,
|
||||
srslte::bounded_bitset<100, true>* alloc_mask)
|
||||
|
@ -318,9 +492,12 @@ int srsenb::extract_dl_prbmask(const srslte_cell_t& cell,
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void user_state_sched_tester::new_tti(uint32_t tti_rx)
|
||||
void user_state_sched_tester::new_tti(sched* sched_ptr, uint32_t tti_rx)
|
||||
{
|
||||
tic++;
|
||||
for (auto& u : users) {
|
||||
u.second.new_tti(sched_ptr, srslte::tti_point{tti_rx});
|
||||
}
|
||||
}
|
||||
|
||||
int user_state_sched_tester::add_user(uint16_t rnti,
|
||||
|
@ -331,8 +508,7 @@ int user_state_sched_tester::add_user(uint16_t r
|
|||
cell_params[ue_cfg.supported_cc_list[0].enb_cc_idx].prach_config, tic.tti_rx(), -1),
|
||||
"New user added in a non-PRACH TTI\n");
|
||||
TESTASSERT(users.count(rnti) == 0);
|
||||
ue_state ue;
|
||||
ue.user_cfg = ue_cfg;
|
||||
ue_state ue{rnti, ue_cfg};
|
||||
ue.prach_tic = tic;
|
||||
ue.preamble_idx = preamble_idx;
|
||||
users.insert(std::make_pair(rnti, ue));
|
||||
|
@ -342,7 +518,7 @@ int user_state_sched_tester::add_user(uint16_t r
|
|||
int user_state_sched_tester::user_reconf(uint16_t rnti, const srsenb::sched_interface::ue_cfg_t& ue_cfg)
|
||||
{
|
||||
TESTASSERT(users.count(rnti) > 0);
|
||||
users[rnti].user_cfg = ue_cfg;
|
||||
users.at(rnti).set_cfg(ue_cfg);
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -353,10 +529,10 @@ int user_state_sched_tester::bearer_cfg(uint16_t
|
|||
auto it = users.find(rnti);
|
||||
TESTASSERT(it != users.end());
|
||||
it->second.user_cfg.ue_bearers[lcid] = bearer_cfg;
|
||||
users[rnti].drb_cfg_flag = false;
|
||||
users.at(rnti).drb_cfg_flag = false;
|
||||
for (uint32_t i = 2; i < it->second.user_cfg.ue_bearers.size(); ++i) {
|
||||
if (it->second.user_cfg.ue_bearers[i].direction != sched_interface::ue_bearer_cfg_t::IDLE) {
|
||||
users[rnti].drb_cfg_flag = true;
|
||||
users.at(rnti).drb_cfg_flag = true;
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
|
@ -488,7 +664,7 @@ int user_state_sched_tester::test_ra(uint32_t enb_
|
|||
auto& pusch_alloc = ul_result.pusch[i];
|
||||
if (not pusch_alloc.needs_pdcch) {
|
||||
// can be adaptive retx or msg3
|
||||
auto& ue = users[pusch_alloc.dci.rnti];
|
||||
auto& ue = users.at(pusch_alloc.dci.rnti);
|
||||
if (tic.tic_tx_ul() == ue.msg3_tic) {
|
||||
msg3_count--;
|
||||
}
|
||||
|
@ -593,6 +769,11 @@ int user_state_sched_tester::test_all(uint32_t enb
|
|||
TESTASSERT(test_ra(enb_cc_idx, dl_result, ul_result) == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_ctrl_info(enb_cc_idx, dl_result, ul_result) == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_scell_activation(enb_cc_idx, dl_result, ul_result) == SRSLTE_SUCCESS);
|
||||
|
||||
for (auto& u : users) {
|
||||
TESTASSERT(u.second.process_sched_result(enb_cc_idx, dl_result, ul_result) == SRSLTE_SUCCESS);
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -700,8 +881,6 @@ void common_sched_tester::new_test_tti()
|
|||
tti_info.ul_sched_result.resize(sched_cell_params.size());
|
||||
|
||||
tester_log->step(tti_info.tti_params.tti_rx);
|
||||
|
||||
ue_tester->new_tti(tti_info.tti_params.tti_rx);
|
||||
}
|
||||
|
||||
int common_sched_tester::process_ack_txs()
|
||||
|
@ -712,38 +891,6 @@ int common_sched_tester::process_ack_txs()
|
|||
erase_if(to_ul_ack,
|
||||
[this](std::pair<const uint32_t, ul_ack_info_t>& elem) { return this->ue_db.count(elem.second.rnti) == 0; });
|
||||
|
||||
/* Ack DL HARQs */
|
||||
for (const auto& ack_it : to_ack) {
|
||||
if (ack_it.second.tti != tti_info.tti_params.tti_rx) {
|
||||
continue;
|
||||
}
|
||||
const ack_info_t& dl_ack = ack_it.second;
|
||||
|
||||
const srsenb::dl_harq_proc& h = ue_db[dl_ack.rnti].get_dl_harq(ack_it.second.dl_harq.get_id(), dl_ack.ue_cc_idx);
|
||||
const srsenb::dl_harq_proc& hack = dl_ack.dl_harq;
|
||||
CONDERROR(hack.is_empty(), "The acked DL harq was not active\n");
|
||||
|
||||
bool ret = false;
|
||||
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; ++tb) {
|
||||
if (dl_ack.dl_harq.is_empty(tb)) {
|
||||
continue;
|
||||
}
|
||||
ret |= dl_ack_info(tti_info.tti_params.tti_rx, dl_ack.rnti, dl_ack.enb_cc_idx, tb, dl_ack.ack) > 0;
|
||||
}
|
||||
CONDERROR(not ret, "The dl harq proc that was ACKed does not exist\n");
|
||||
|
||||
if (dl_ack.ack) {
|
||||
CONDERROR(!h.is_empty(), "ACKed dl harq was not emptied\n");
|
||||
CONDERROR(h.has_pending_retx(0, tti_info.tti_params.tti_tx_dl), "ACKed dl harq still has pending retx\n");
|
||||
tester_log->info(
|
||||
"DL ACK tti=%u rnti=0x%x pid=%d\n", tti_info.tti_params.tti_rx, dl_ack.rnti, dl_ack.dl_harq.get_id());
|
||||
} else {
|
||||
tester_log->info(
|
||||
"DL NACK tti=%u rnti=0x%x pid=%d\n", tti_info.tti_params.tti_rx, dl_ack.rnti, dl_ack.dl_harq.get_id());
|
||||
CONDERROR(h.is_empty() and hack.nof_retx(0) + 1 < hack.max_nof_retx(), "NACKed DL harq got emptied\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Ack UL HARQs */
|
||||
for (const auto& ack_it : to_ul_ack) {
|
||||
if (ack_it.first != tti_info.tti_params.tti_rx) {
|
||||
|
@ -784,40 +931,6 @@ int common_sched_tester::process_ack_txs()
|
|||
int common_sched_tester::schedule_acks()
|
||||
{
|
||||
for (uint32_t ccidx = 0; ccidx < sched_cell_params.size(); ++ccidx) {
|
||||
// schedule future acks
|
||||
for (uint32_t i = 0; i < tti_info.dl_sched_result[ccidx].nof_data_elems; ++i) {
|
||||
ack_info_t ack_data;
|
||||
ack_data.rnti = tti_info.dl_sched_result[ccidx].data[i].dci.rnti;
|
||||
ack_data.tti = FDD_HARQ_DELAY_DL_MS + tti_info.tti_params.tti_tx_dl;
|
||||
ack_data.enb_cc_idx = ccidx;
|
||||
ack_data.ue_cc_idx = ue_db[ack_data.rnti].get_cell_index(ccidx).second;
|
||||
const srsenb::dl_harq_proc& dl_h =
|
||||
ue_db[ack_data.rnti].get_dl_harq(tti_info.dl_sched_result[ccidx].data[i].dci.pid, ack_data.ue_cc_idx);
|
||||
ack_data.dl_harq = dl_h;
|
||||
if (ack_data.dl_harq.nof_retx(0) == 0) {
|
||||
ack_data.ack = randf() > sim_args0.P_retx;
|
||||
} else { // always ack after three retxs
|
||||
ack_data.ack = ack_data.dl_harq.nof_retx(0) == 3;
|
||||
}
|
||||
|
||||
// Remove harq from the ack list if there was a harq rewrite
|
||||
auto it = to_ack.begin();
|
||||
while (it != to_ack.end() and it->first < ack_data.tti) {
|
||||
if (it->second.rnti == ack_data.rnti and it->second.dl_harq.get_id() == ack_data.dl_harq.get_id() and
|
||||
it->second.ue_cc_idx == ack_data.ue_cc_idx) {
|
||||
CONDERROR(it->second.tti + FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS > ack_data.tti,
|
||||
"The retx dl harq id=%d was transmitted too soon\n",
|
||||
ack_data.dl_harq.get_id());
|
||||
auto toerase_it = it++;
|
||||
to_ack.erase(toerase_it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
// add new ack to the list
|
||||
to_ack.insert(std::make_pair(ack_data.tti, ack_data));
|
||||
}
|
||||
|
||||
/* Schedule UL ACKs */
|
||||
for (uint32_t i = 0; i < tti_info.ul_sched_result[ccidx].nof_dci_elems; ++i) {
|
||||
const auto& pusch = tti_info.ul_sched_result[ccidx].pusch[i];
|
||||
|
@ -932,6 +1045,7 @@ int common_sched_tester::run_tti(const tti_ev& tti_events)
|
|||
new_test_tti();
|
||||
tester_log->info("---- tti=%u | nof_ues=%zd ----\n", tic.tti_rx(), ue_db.size());
|
||||
|
||||
ue_tester->new_tti(this, tti_info.tti_params.tti_rx);
|
||||
process_tti_events(tti_events);
|
||||
process_ack_txs();
|
||||
before_sched();
|
||||
|
|
|
@ -80,24 +80,80 @@ private:
|
|||
const sched_cell_params_t& cell_params;
|
||||
};
|
||||
|
||||
class user_state_sched_tester
|
||||
{
|
||||
public:
|
||||
using dl_sched_res_list = std::vector<sched_interface::dl_sched_res_t>;
|
||||
using ul_sched_res_list = std::vector<sched_interface::ul_sched_res_t>;
|
||||
|
||||
struct ue_state {
|
||||
// args
|
||||
srslte::log_ref log_h{"TEST"};
|
||||
uint32_t cqi_Npd = 10, cqi_Noffset = std::uniform_int_distribution<uint32_t>{0, 10}(get_rand_gen()); // CQI reporting
|
||||
std::vector<float> prob_dl_ack_mask{0.5, 0.5, 1}, prob_ul_ack_mask{0.5, 0.5, 1};
|
||||
|
||||
// state
|
||||
uint16_t rnti;
|
||||
srslte::tti_point current_tti_rx;
|
||||
|
||||
struct cc_state_t {
|
||||
uint32_t ue_cc_idx = 0;
|
||||
uint32_t enb_cc_idx = 0;
|
||||
// Harq State
|
||||
struct harq_state_t {
|
||||
uint32_t pid = 0;
|
||||
srslte::tti_point tti_tx;
|
||||
bool active = false;
|
||||
bool ndi = false;
|
||||
uint32_t nof_retxs = 0;
|
||||
uint32_t nof_txs = 0;
|
||||
};
|
||||
std::array<harq_state_t, sched_ue_carrier::SCHED_MAX_HARQ_PROC> dl_harqs = {};
|
||||
};
|
||||
std::vector<cc_state_t> active_ccs;
|
||||
|
||||
tti_counter prach_tic, rar_tic, msg3_tic, msg4_tic;
|
||||
bool drb_cfg_flag = false;
|
||||
srsenb::sched_interface::ue_cfg_t user_cfg;
|
||||
uint32_t preamble_idx = 0;
|
||||
uint32_t msg3_riv = 0;
|
||||
bool is_msg3_rx(const tti_counter& tti_rx) const { return msg3_tic.is_valid() and msg3_tic <= tti_rx; }
|
||||
|
||||
ue_state(uint16_t rnti_, const sched::ue_cfg_t& ue_cfg_);
|
||||
int set_cfg(const sched::ue_cfg_t& ue_cfg_);
|
||||
cc_state_t* get_cc_state(uint32_t enb_cc_idx);
|
||||
|
||||
int new_tti(sched* sched_ptr, srslte::tti_point tti_rx);
|
||||
int process_sched_result(uint32_t enb_cc_idx,
|
||||
const sched::dl_sched_res_t& dl_result,
|
||||
const sched::ul_sched_res_t& ul_result);
|
||||
|
||||
private:
|
||||
int fwd_pending_acks(sched* sched_ptr);
|
||||
|
||||
struct cc_result {
|
||||
uint32_t enb_cc_idx;
|
||||
const sched::dl_sched_res_t* dl_result;
|
||||
const sched::ul_sched_res_t* ul_result;
|
||||
};
|
||||
int test_harqs(cc_result result);
|
||||
int schedule_acks(cc_result result);
|
||||
|
||||
struct pending_ack_t {
|
||||
srslte::tti_point tti_ack;
|
||||
uint32_t cc_idx, ue_cc_idx, tb, pid;
|
||||
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;
|
||||
std::array<pending_ack_t, sched_ue_carrier::SCHED_MAX_HARQ_PROC> 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_)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void new_tti(uint32_t tti_rx);
|
||||
void new_tti(sched* sched_ptr, uint32_t tti_rx);
|
||||
bool user_exists(uint16_t rnti) const { return users.find(rnti) != users.end(); }
|
||||
const ue_state* get_user_state(uint16_t rnti) const
|
||||
{
|
||||
|
@ -141,8 +197,7 @@ class sched_result_stats
|
|||
public:
|
||||
explicit sched_result_stats(std::vector<srsenb::sched::cell_cfg_t> cell_params_) :
|
||||
cell_params(std::move(cell_params_))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void process_results(const tti_params_t& tti_params,
|
||||
const std::vector<sched_interface::dl_sched_res_t>& dl_result,
|
||||
|
|
Loading…
Reference in New Issue