diff --git a/srsenb/src/stack/mac/sched_ue.cc b/srsenb/src/stack/mac/sched_ue.cc index 27fcace8d..994599c03 100644 --- a/srsenb/src/stack/mac/sched_ue.cc +++ b/srsenb/src/stack/mac/sched_ue.cc @@ -89,6 +89,65 @@ bool operator==(const sched_interface::ue_cfg_t::cc_cfg_t& lhs, const sched_inte return lhs.enb_cc_idx == rhs.enb_cc_idx and lhs.active == rhs.active; } +template +std::tuple false_position_method(int x1, int x2, YType y0, const Callable& f) +{ + return false_position_method(x1, x2, y0, f, []() { return false; }); +} +template +std::tuple +false_position_method(int x1, int x2, YType y0, const Callable& f, const ErrorDetect& is_error) +{ + static_assert(std::is_same::value, + "The type of the final result and callable return do not match\n"); + YType y1 = f(x1); + if (is_error(y1) or y1 >= y0) { + return {x1, y1, x1, y1}; + } + YType y2 = f(x2); + if (is_error(y2) or y2 <= y0) { + return {x2, y2, x2, y2}; + } + YType y3; + while (x2 > x1 + 1) { + int x3 = round(x1 - ((x2 - x1) * (y1 - y0) / (float)(y2 - y1))); + if (x3 == x2) { + y3 = y2; + // check if in frontier + YType y3_1 = f(x3 - 1); + if (not is_error(y3_1) and y3_1 < y0) { + return {x3 - 1, y3_1, x3, y3}; + } else { + x3--; + y3 = y3_1; + } + } else if (x3 == x1) { + y3 = y1; + // check if in frontier + YType y3_1 = f(x3 + 1); + if (not is_error(y3_1) and y3_1 >= y0) { + return {x3, y3, x3 + 1, y3_1}; + } else { + x3++; + y3 = y3_1; + } + } else { + y3 = f(x3); + if (is_error(y3) or y3 == y0) { + return {x3, y3, x3, y3}; + } + } + if (y3 < y0) { + x1 = x3; + y1 = y3; + } else { + x2 = x3; + y2 = y3; + } + } + return {x1, y1, x2, y2}; +} + /******************************************************* * * Initialization and configuration functions @@ -1425,68 +1484,46 @@ int cc_sched_ue::alloc_tbs_ul(uint32_t nof_prb, uint32_t nof_re, uint32_t req_by int cc_sched_ue::get_required_prb_dl(uint32_t req_bytes, uint32_t nof_ctrl_symbols) { - int mcs = 0; - uint32_t nof_re = 0; - int tbs = 0; - - uint32_t nbytes = 0; - uint32_t n; - for (n = 0; n < cell_params->nof_prb() and nbytes < req_bytes; ++n) { - nof_re = srslte_ra_dl_approx_nof_re(&cell_params->cfg.cell, n + 1, nof_ctrl_symbols); + auto compute_tbs_approx = [this, nof_ctrl_symbols](uint32_t nof_prb) { + uint32_t nof_re = srslte_ra_dl_approx_nof_re(&cell_params->cfg.cell, nof_prb, nof_ctrl_symbols); + int mcs, tbs; if (fixed_mcs_dl < 0 or not dl_cqi_rx) { - tbs = alloc_tbs_dl(n + 1, nof_re, 0, &mcs); - } else { - tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl, cfg->use_tbs_index_alt, false), n + 1) / 8; + return alloc_tbs_dl(nof_prb, nof_re, 0, &mcs); } - if (tbs > 0) { - nbytes = tbs; - } else if (tbs < 0) { - return 0; - } - } + return srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl, cfg->use_tbs_index_alt, false), nof_prb) / 8; + }; - return (nbytes >= req_bytes) ? n : -1; + std::tuple ret = false_position_method( + 1u, cell_params->nof_prb(), (int)req_bytes, compute_tbs_approx, [](int y) { return y == SRSLTE_ERROR; }); + int upper_tbs = std::get<3>(ret); + uint32_t upper_nprb = std::get<2>(ret); + return (upper_tbs < 0) ? 0 : ((upper_tbs < (int)req_bytes) ? -1 : upper_nprb); } uint32_t cc_sched_ue::get_required_prb_ul(uint32_t req_bytes) { - int mcs = 0; - uint32_t nbytes = 0; - uint32_t N_srs = 0; - - uint32_t n = 0; if (req_bytes == 0) { return 0; } - - uint32_t last_valid_n = 0; - for (n = 1; n < cell_params->nof_prb() && nbytes < req_bytes + 4; n++) { - uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell_params->cfg.cell.cp) - 1) - N_srs) * n * SRSLTE_NRE; - int tbs = 0; + auto compute_tbs_approx = [this](uint32_t nof_prb) { + const uint32_t N_srs = 0; + uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell_params->cfg.cell.cp) - 1) - N_srs) * nof_prb * SRSLTE_NRE; + int mcs, tbs; if (fixed_mcs_ul < 0) { - tbs = alloc_tbs_ul(n, nof_re, 0, &mcs); - } else { - tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul, false, true), n) / 8; - } - if (tbs > 0) { - nbytes = tbs; - last_valid_n = n; + return alloc_tbs_ul(nof_prb, nof_re, 0, &mcs); } - } - - if (last_valid_n > 0) { - if (n != last_valid_n) { - n = last_valid_n; - } - while (!srslte_dft_precoding_valid_prb(n) && n <= cell_params->nof_prb()) { - n++; - } - return n; - } else { - // This should never happen. Just in case, return 0 PRB and handle it later - log_h->error("SCHED: Could not obtain any valid number of PRB for an uplink allocation\n"); - return 0; - } + return srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_ul, false, true), nof_prb) / 8; + }; + + // find nof prbs that lead to a tbs just above req_bytes + int target_tbs = req_bytes + 4; + std::tuple ret = false_position_method( + 1u, cell_params->nof_prb(), target_tbs, compute_tbs_approx, [](int y) { return y == SRSLTE_ERROR; }); + uint32_t req_prbs = std::get<2>(ret); + while (!srslte_dft_precoding_valid_prb(req_prbs) && req_prbs < cell_params->nof_prb()) { + req_prbs++; + } + return req_prbs; } void cc_sched_ue::set_dl_cqi(uint32_t tti_tx_dl, uint32_t dl_cqi_)