|
|
|
@ -41,7 +41,7 @@ void dl_metric_rr::set_params(const sched_params_t& sched_params_)
|
|
|
|
|
log_h = sched_params_.log_h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void dl_metric_rr::sched_users(std::map<uint16_t, sched_ue>& ue_db, dl_tti_sched_t* tti_sched, uint32_t cc_idx)
|
|
|
|
|
void dl_metric_rr::sched_users(std::map<uint16_t, sched_ue>& ue_db, dl_tti_sched_t* tti_sched, uint32_t enb_cc_idx)
|
|
|
|
|
{
|
|
|
|
|
tti_alloc = tti_sched;
|
|
|
|
|
|
|
|
|
@ -58,7 +58,7 @@ void dl_metric_rr::sched_users(std::map<uint16_t, sched_ue>& ue_db, dl_tti_sched
|
|
|
|
|
iter = ue_db.begin(); // wrap around
|
|
|
|
|
}
|
|
|
|
|
sched_ue* user = &iter->second;
|
|
|
|
|
allocate_user(user, cc_idx);
|
|
|
|
|
allocate_user(user, enb_cc_idx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -77,20 +77,26 @@ bool dl_metric_rr::find_allocation(uint32_t nof_rbg, rbgmask_t* rbgmask)
|
|
|
|
|
return nof_rbg == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dl_harq_proc* dl_metric_rr::allocate_user(sched_ue* user, uint32_t cc_idx)
|
|
|
|
|
dl_harq_proc* dl_metric_rr::allocate_user(sched_ue* user, uint32_t enb_cc_idx)
|
|
|
|
|
{
|
|
|
|
|
if (tti_alloc->is_dl_alloc(user)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
auto p = user->get_cell_index(enb_cc_idx);
|
|
|
|
|
if (not p.first) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
uint32_t cell_idx = p.second;
|
|
|
|
|
|
|
|
|
|
// FIXME: First do reTxs for all users. Only then do the rest.
|
|
|
|
|
alloc_outcome_t code;
|
|
|
|
|
uint32_t tti_dl = tti_alloc->get_tti_tx_dl();
|
|
|
|
|
dl_harq_proc* h = user->get_pending_dl_harq(tti_dl, cc_idx);
|
|
|
|
|
dl_harq_proc* h = user->get_pending_dl_harq(tti_dl, cell_idx);
|
|
|
|
|
uint32_t req_bytes = user->get_pending_dl_new_data_total();
|
|
|
|
|
|
|
|
|
|
// Schedule retx if we have space
|
|
|
|
|
#if ASYNC_DL_SCHED
|
|
|
|
|
if (h) {
|
|
|
|
|
if (h != nullptr) {
|
|
|
|
|
#else
|
|
|
|
|
if (h && !h->is_empty()) {
|
|
|
|
|
#endif
|
|
|
|
@ -111,7 +117,8 @@ dl_harq_proc* dl_metric_rr::allocate_user(sched_ue* user, uint32_t cc_idx)
|
|
|
|
|
code = tti_alloc->alloc_dl_user(user, retx_mask, h->get_id());
|
|
|
|
|
if (code == alloc_outcome_t::SUCCESS) {
|
|
|
|
|
return h;
|
|
|
|
|
} else if (code == alloc_outcome_t::DCI_COLLISION) {
|
|
|
|
|
}
|
|
|
|
|
if (code == alloc_outcome_t::DCI_COLLISION) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -119,15 +126,15 @@ dl_harq_proc* dl_metric_rr::allocate_user(sched_ue* user, uint32_t cc_idx)
|
|
|
|
|
|
|
|
|
|
// If could not schedule the reTx, or there wasn't any pending retx, find an empty PID
|
|
|
|
|
#if ASYNC_DL_SCHED
|
|
|
|
|
h = user->get_empty_dl_harq(cc_idx);
|
|
|
|
|
if (h) {
|
|
|
|
|
h = user->get_empty_dl_harq(cell_idx);
|
|
|
|
|
if (h != nullptr) {
|
|
|
|
|
#else
|
|
|
|
|
if (h && h->is_empty()) {
|
|
|
|
|
#endif
|
|
|
|
|
// Allocate resources based on pending data
|
|
|
|
|
if (req_bytes) {
|
|
|
|
|
if (req_bytes > 0) {
|
|
|
|
|
uint32_t pending_rbg =
|
|
|
|
|
user->prb_to_rbg(user->get_required_prb_dl(cc_idx, req_bytes, tti_alloc->get_nof_ctrl_symbols()));
|
|
|
|
|
user->prb_to_rbg(user->get_required_prb_dl(cell_idx, req_bytes, tti_alloc->get_nof_ctrl_symbols()));
|
|
|
|
|
rbgmask_t newtx_mask(tti_alloc->get_dl_mask().size());
|
|
|
|
|
find_allocation(pending_rbg, &newtx_mask);
|
|
|
|
|
if (newtx_mask.any()) { // some empty spaces were found
|
|
|
|
@ -153,7 +160,7 @@ void ul_metric_rr::set_params(const sched_params_t& sched_params_)
|
|
|
|
|
log_h = sched_params_.log_h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ul_metric_rr::sched_users(std::map<uint16_t, sched_ue>& ue_db, ul_tti_sched_t* tti_sched, uint32_t cc_idx)
|
|
|
|
|
void ul_metric_rr::sched_users(std::map<uint16_t, sched_ue>& ue_db, ul_tti_sched_t* tti_sched, uint32_t enb_cc_idx)
|
|
|
|
|
{
|
|
|
|
|
tti_alloc = tti_sched;
|
|
|
|
|
current_tti = tti_alloc->get_tti_tx_ul();
|
|
|
|
@ -174,7 +181,7 @@ void ul_metric_rr::sched_users(std::map<uint16_t, sched_ue>& ue_db, ul_tti_sched
|
|
|
|
|
iter = ue_db.begin(); // wrap around
|
|
|
|
|
}
|
|
|
|
|
sched_ue* user = &iter->second;
|
|
|
|
|
allocate_user_retx_prbs(user, cc_idx);
|
|
|
|
|
allocate_user_retx_prbs(user, enb_cc_idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// give priority in a time-domain RR basis
|
|
|
|
@ -185,7 +192,7 @@ void ul_metric_rr::sched_users(std::map<uint16_t, sched_ue>& ue_db, ul_tti_sched
|
|
|
|
|
iter = ue_db.begin(); // wrap around
|
|
|
|
|
}
|
|
|
|
|
sched_ue* user = &iter->second;
|
|
|
|
|
allocate_user_newtx_prbs(user, cc_idx);
|
|
|
|
|
allocate_user_newtx_prbs(user, enb_cc_idx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -226,13 +233,20 @@ bool ul_metric_rr::find_allocation(uint32_t L, ul_harq_proc::ul_alloc_t* alloc)
|
|
|
|
|
return alloc->L == L;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ul_harq_proc* ul_metric_rr::allocate_user_retx_prbs(sched_ue* user, uint32_t cc_idx)
|
|
|
|
|
ul_harq_proc* ul_metric_rr::allocate_user_retx_prbs(sched_ue* user, uint32_t enb_cc_idx)
|
|
|
|
|
{
|
|
|
|
|
if (tti_alloc->is_ul_alloc(user)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
auto p = user->get_cell_index(enb_cc_idx);
|
|
|
|
|
if (not p.first) {
|
|
|
|
|
// this cc is not activated for this user
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
uint32_t cell_idx = p.second;
|
|
|
|
|
|
|
|
|
|
alloc_outcome_t ret;
|
|
|
|
|
ul_harq_proc* h = user->get_ul_harq(current_tti, cc_idx);
|
|
|
|
|
ul_harq_proc* h = user->get_ul_harq(current_tti, cell_idx);
|
|
|
|
|
|
|
|
|
|
// if there are procedures and we have space
|
|
|
|
|
if (h->has_pending_retx()) {
|
|
|
|
@ -261,18 +275,25 @@ ul_harq_proc* ul_metric_rr::allocate_user_retx_prbs(sched_ue* user, uint32_t cc_
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ul_harq_proc* ul_metric_rr::allocate_user_newtx_prbs(sched_ue* user, uint32_t cc_idx)
|
|
|
|
|
ul_harq_proc* ul_metric_rr::allocate_user_newtx_prbs(sched_ue* user, uint32_t enb_cc_idx)
|
|
|
|
|
{
|
|
|
|
|
if (tti_alloc->is_ul_alloc(user)) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
auto p = user->get_cell_index(enb_cc_idx);
|
|
|
|
|
if (not p.first) {
|
|
|
|
|
// this cc is not activated for this user
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
uint32_t cell_idx = p.second;
|
|
|
|
|
|
|
|
|
|
uint32_t pending_data = user->get_pending_ul_new_data(current_tti);
|
|
|
|
|
ul_harq_proc* h = user->get_ul_harq(current_tti, cc_idx);
|
|
|
|
|
ul_harq_proc* h = user->get_ul_harq(current_tti, cell_idx);
|
|
|
|
|
|
|
|
|
|
// find an empty PID
|
|
|
|
|
if (h->is_empty(0) and pending_data > 0) {
|
|
|
|
|
uint32_t pending_rb = user->get_required_prb_ul(cc_idx, pending_data);
|
|
|
|
|
ul_harq_proc::ul_alloc_t alloc;
|
|
|
|
|
uint32_t pending_rb = user->get_required_prb_ul(cell_idx, pending_data);
|
|
|
|
|
ul_harq_proc::ul_alloc_t alloc{};
|
|
|
|
|
|
|
|
|
|
find_allocation(pending_rb, &alloc);
|
|
|
|
|
if (alloc.L > 0) { // at least one PRB was scheduled
|
|
|
|
|