mirror of https://github.com/PentHertz/srsLTE.git
re-designed algorithm to compute lowest mcs that meets cqi,req_bytes,nof_prbs requirements in the scheduler
This commit is contained in:
parent
3dd7877199
commit
ed8ab3871c
|
@ -22,6 +22,11 @@ struct tbs_info {
|
||||||
int mcs = 0;
|
int mcs = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute MCS, TBS based on CQI, N_prb
|
||||||
|
* \remark See TS 36.213 - Table 7.1.7.1-1/1A
|
||||||
|
* @return resulting TBS (in bytes) and mcs. TBS=-1 if no valid solution was found.
|
||||||
|
*/
|
||||||
tbs_info compute_mcs_and_tbs(uint32_t nof_prb,
|
tbs_info compute_mcs_and_tbs(uint32_t nof_prb,
|
||||||
uint32_t nof_re,
|
uint32_t nof_re,
|
||||||
uint32_t cqi,
|
uint32_t cqi,
|
||||||
|
@ -30,6 +35,20 @@ tbs_info compute_mcs_and_tbs(uint32_t nof_prb,
|
||||||
bool ulqam64_enabled,
|
bool ulqam64_enabled,
|
||||||
bool use_tbs_index_alt);
|
bool use_tbs_index_alt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute lowest MCS, TBS based on CQI, N_prb that satisfies TBS >= req_bytes
|
||||||
|
* \remark See TS 36.213 - Table 7.1.7.1-1/1A
|
||||||
|
* @return resulting TBS (in bytes) and mcs. TBS=-1 if no valid solution was found.
|
||||||
|
*/
|
||||||
|
tbs_info compute_min_mcs_and_tbs_from_required_bytes(uint32_t nof_prb,
|
||||||
|
uint32_t nof_re,
|
||||||
|
uint32_t cqi,
|
||||||
|
uint32_t max_mcs,
|
||||||
|
uint32_t req_bytes,
|
||||||
|
bool is_ul,
|
||||||
|
bool ulqam64_enabled,
|
||||||
|
bool use_tbs_index_alt);
|
||||||
|
|
||||||
} // namespace srsenb
|
} // namespace srsenb
|
||||||
|
|
||||||
#endif // SRSLTE_SCHED_DCI_H
|
#endif // SRSLTE_SCHED_DCI_H
|
||||||
|
|
|
@ -89,12 +89,9 @@ private:
|
||||||
* TBS/MCS derivation
|
* TBS/MCS derivation
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
/// Compute TBS and MCS based on cell state and grant
|
tbs_info alloc_tbs_dl(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, int req_bytes = -1);
|
||||||
tbs_info cqi_to_tbs(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, bool is_ul);
|
|
||||||
|
|
||||||
tbs_info alloc_tbs_dl(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes);
|
|
||||||
tbs_info
|
tbs_info
|
||||||
alloc_tbs_ul(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int explicit_mcs = -1);
|
alloc_tbs_ul(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, int req_bytes = -1, int explicit_mcs = -1);
|
||||||
|
|
||||||
int get_required_prb_dl(const sched_ue_cell& cell, tti_point tti_tx_dl, uint32_t req_bytes);
|
int get_required_prb_dl(const sched_ue_cell& cell, tti_point tti_tx_dl, uint32_t req_bytes);
|
||||||
uint32_t get_required_prb_ul(const sched_ue_cell& cell, uint32_t req_bytes);
|
uint32_t get_required_prb_ul(const sched_ue_cell& cell, uint32_t req_bytes);
|
||||||
|
|
|
@ -23,47 +23,41 @@ int coderate_to_tbs(float max_coderate, uint32_t nof_re)
|
||||||
return floorf(nof_re * max_coderate - 24);
|
return floorf(nof_re * max_coderate - 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
tbs_info compute_mcs_and_tbs_recursive(uint32_t nof_prb,
|
/// Compute {mcs, tbs_idx} based on {max_tbs, nof_prb}
|
||||||
uint32_t nof_re,
|
int compute_mcs_from_max_tbs(uint32_t nof_prb,
|
||||||
uint32_t max_mcs,
|
uint32_t max_tbs,
|
||||||
bool is_ul,
|
uint32_t max_mcs,
|
||||||
bool use_tbs_index_alt,
|
bool is_ul,
|
||||||
float max_coderate)
|
bool use_tbs_index_alt,
|
||||||
|
int& mcs,
|
||||||
|
int& tbs_idx)
|
||||||
{
|
{
|
||||||
// compute max MCS based on max coderate
|
constexpr static std::array<int, 6> forbidden_tbs_idx_alt{1, 3, 5, 7, 9, 26};
|
||||||
int max_tbs = coderate_to_tbs(max_coderate, nof_re);
|
|
||||||
if (max_tbs <= 0) {
|
// Compute I_TBS based on max TBS
|
||||||
return tbs_info{};
|
tbs_idx = srslte_ra_tbs_to_table_idx(max_tbs, nof_prb);
|
||||||
}
|
|
||||||
int tbs_idx = srslte_ra_tbs_to_table_idx(max_tbs, nof_prb);
|
|
||||||
if (tbs_idx <= 0) {
|
if (tbs_idx <= 0) {
|
||||||
return tbs_info{};
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
tbs_idx -= 1; // get TBS index lower bound
|
--tbs_idx; // get TBS index lower bound
|
||||||
uint32_t mcs = srslte_ra_mcs_from_tbs_idx(tbs_idx, use_tbs_index_alt, is_ul);
|
if (use_tbs_index_alt and
|
||||||
if (mcs > max_mcs) {
|
std::find(forbidden_tbs_idx_alt.begin(), forbidden_tbs_idx_alt.end(), tbs_idx) != forbidden_tbs_idx_alt.end()) {
|
||||||
|
// some tbs_idx are invalid for 256QAM. See TS 36.213 - Table 7.1.7.1-1A
|
||||||
|
--tbs_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute I_mcs based on I_TBS. Reverse of TS 36.213 - Table 7.1.7.1-1/1A
|
||||||
|
mcs = srslte_ra_mcs_from_tbs_idx(tbs_idx, use_tbs_index_alt, is_ul);
|
||||||
|
if (mcs < 0) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
if (mcs > (int)max_mcs) {
|
||||||
// bound mcs
|
// bound mcs
|
||||||
mcs = max_mcs;
|
mcs = max_mcs;
|
||||||
tbs_idx = srslte_ra_tbs_idx_from_mcs(mcs, use_tbs_index_alt, is_ul);
|
tbs_idx = srslte_ra_tbs_idx_from_mcs(mcs, use_tbs_index_alt, is_ul);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute real TBS based on max MCS
|
return SRSLTE_SUCCESS;
|
||||||
int tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb);
|
|
||||||
float coderate = srslte_coderate(tbs, nof_re);
|
|
||||||
|
|
||||||
srslte_mod_t mod = (is_ul) ? srslte_ra_ul_mod_from_mcs(mcs) : srslte_ra_dl_mod_from_mcs(mcs, use_tbs_index_alt);
|
|
||||||
float new_maxcoderate = std::min(0.930f * srslte_mod_bits_x_symbol(mod), max_coderate);
|
|
||||||
if (new_maxcoderate > coderate) {
|
|
||||||
tbs_info tb;
|
|
||||||
tb.tbs_bytes = tbs / 8u;
|
|
||||||
tb.mcs = mcs;
|
|
||||||
return tb;
|
|
||||||
}
|
|
||||||
if (mcs == 0) {
|
|
||||||
// solution not found
|
|
||||||
return tbs_info{};
|
|
||||||
}
|
|
||||||
return compute_mcs_and_tbs_recursive(nof_prb, nof_re, mcs - 1, is_ul, use_tbs_index_alt, new_maxcoderate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tbs_info compute_mcs_and_tbs(uint32_t nof_prb,
|
tbs_info compute_mcs_and_tbs(uint32_t nof_prb,
|
||||||
|
@ -81,7 +75,85 @@ tbs_info compute_mcs_and_tbs(uint32_t nof_prb,
|
||||||
uint32_t max_Qm = (is_ul) ? (ulqam64_enabled ? 6 : 4) : (use_tbs_index_alt ? 8 : 6);
|
uint32_t max_Qm = (is_ul) ? (ulqam64_enabled ? 6 : 4) : (use_tbs_index_alt ? 8 : 6);
|
||||||
max_coderate = std::min(max_coderate, 0.930f * max_Qm);
|
max_coderate = std::min(max_coderate, 0.930f * max_Qm);
|
||||||
|
|
||||||
return compute_mcs_and_tbs_recursive(nof_prb, nof_re, max_mcs, is_ul, use_tbs_index_alt, max_coderate);
|
int mcs = 0;
|
||||||
|
float prev_max_coderate = 0;
|
||||||
|
do {
|
||||||
|
// update max TBS based on max coderate
|
||||||
|
int max_tbs = coderate_to_tbs(max_coderate, nof_re);
|
||||||
|
if (max_tbs < 16) {
|
||||||
|
return tbs_info{};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute max {MCS,I_TBS} based on given max_tbs, nof_prb
|
||||||
|
int tbs_idx = 0;
|
||||||
|
if (compute_mcs_from_max_tbs(nof_prb, max_tbs, max_mcs, is_ul, use_tbs_index_alt, mcs, tbs_idx) != SRSLTE_SUCCESS) {
|
||||||
|
return tbs_info{};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcs == 6 and nof_prb == 1) {
|
||||||
|
// Avoid the unusual case n_prb=1, mcs=6 tbs=328 (used in voip)
|
||||||
|
max_mcs = mcs - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute real TBS and coderate based on maximum achievable MCS
|
||||||
|
int tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb);
|
||||||
|
float coderate = srslte_coderate(tbs, nof_re);
|
||||||
|
|
||||||
|
// update max coderate based on mcs
|
||||||
|
srslte_mod_t mod = (is_ul) ? srslte_ra_ul_mod_from_mcs(mcs) : srslte_ra_dl_mod_from_mcs(mcs, use_tbs_index_alt);
|
||||||
|
uint32_t Qm = srslte_mod_bits_x_symbol(mod);
|
||||||
|
max_coderate = std::min(0.930f * Qm, max_coderate);
|
||||||
|
|
||||||
|
if (coderate <= max_coderate) {
|
||||||
|
// solution was found
|
||||||
|
tbs_info tb;
|
||||||
|
tb.tbs_bytes = tbs / 8u;
|
||||||
|
tb.mcs = mcs;
|
||||||
|
return tb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start with smaller max mcs in next iteration
|
||||||
|
max_mcs = mcs - 1;
|
||||||
|
} while (mcs > 0 and max_coderate != prev_max_coderate);
|
||||||
|
|
||||||
|
return tbs_info{};
|
||||||
|
}
|
||||||
|
|
||||||
|
tbs_info compute_min_mcs_and_tbs_from_required_bytes(uint32_t nof_prb,
|
||||||
|
uint32_t nof_re,
|
||||||
|
uint32_t cqi,
|
||||||
|
uint32_t max_mcs,
|
||||||
|
uint32_t req_bytes,
|
||||||
|
bool is_ul,
|
||||||
|
bool ulqam64_enabled,
|
||||||
|
bool use_tbs_index_alt)
|
||||||
|
{
|
||||||
|
assert(req_bytes > 0);
|
||||||
|
|
||||||
|
// get max MCS/TBS
|
||||||
|
tbs_info tb_max = compute_mcs_and_tbs(nof_prb, nof_re, cqi, max_mcs, is_ul, ulqam64_enabled, use_tbs_index_alt);
|
||||||
|
if (tb_max.tbs_bytes + 8 <= (int)req_bytes or tb_max.mcs == 0) {
|
||||||
|
// if mcs cannot be lowered or a decrease in TBS index won't meet req_bytes requirement
|
||||||
|
return tb_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get minimum MCS that leads to tbs < req_bytes (used as max_tbs)
|
||||||
|
int mcs_min = 0, tbs_idx_min = 0;
|
||||||
|
if (compute_mcs_from_max_tbs(nof_prb, req_bytes * 8u, max_mcs, is_ul, use_tbs_index_alt, mcs_min, tbs_idx_min) !=
|
||||||
|
SRSLTE_SUCCESS) {
|
||||||
|
// Failed to compute minimum MCS
|
||||||
|
return tb_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate from min to max MCS until a solution is found
|
||||||
|
for (int mcs = mcs_min + 1; mcs < tb_max.mcs; ++mcs) {
|
||||||
|
tbs_info tb2 = compute_mcs_and_tbs(nof_prb, nof_re, cqi, mcs, is_ul, ulqam64_enabled, use_tbs_index_alt);
|
||||||
|
if (tb2.tbs_bytes >= (int)req_bytes) {
|
||||||
|
return tb2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tb_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace srsenb
|
} // namespace srsenb
|
||||||
|
|
|
@ -221,122 +221,45 @@ std::tuple<int, YType, int, YType> false_position_method(int x1, int x2, YType y
|
||||||
return false_position_method(x1, x2, y0, f, [](int x) { return false; });
|
return false_position_method(x1, x2, y0, f, [](int x) { return false; });
|
||||||
}
|
}
|
||||||
|
|
||||||
float diff_coderate_maxcoderate(int mcs,
|
/**
|
||||||
uint32_t nof_prb,
|
* In this scheduler we tend to use all the available bandwidth and select the MCS
|
||||||
uint32_t nof_re,
|
* that approximates the minimum between the capacity and the requested rate
|
||||||
uint32_t max_Qm,
|
*/
|
||||||
float max_coderate,
|
tbs_info cqi_to_tbs(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, int req_bytes, bool is_ul)
|
||||||
bool use_tbs_index_alt,
|
|
||||||
bool is_ul)
|
|
||||||
{
|
{
|
||||||
uint32_t tbs_idx = srslte_ra_tbs_idx_from_mcs(mcs, use_tbs_index_alt, is_ul);
|
// TODO: Compute real spectral efficiency based on PUSCH-UCI configuration
|
||||||
int tbs = srslte_ra_tbs_from_idx(tbs_idx, nof_prb);
|
using ul64qam_cap = sched_interface::ue_cfg_t::ul64qam_cap;
|
||||||
float coderate = srslte_coderate(tbs, nof_re);
|
uint32_t cqi = (is_ul) ? cell.ul_cqi : cell.dl_cqi;
|
||||||
srslte_mod_t mod = (is_ul) ? srslte_ra_ul_mod_from_mcs(mcs) : srslte_ra_dl_mod_from_mcs(mcs, use_tbs_index_alt);
|
uint32_t max_mcs = (is_ul) ? cell.max_mcs_ul : cell.max_mcs_dl;
|
||||||
uint32_t Qm = std::min(max_Qm, srslte_mod_bits_x_symbol(mod));
|
bool ulqam64_enabled = is_ul and cell.get_ue_cfg()->support_ul64qam == ul64qam_cap::enabled;
|
||||||
return coderate - std::min(max_coderate, 0.930f * Qm);
|
bool use_tbs_index_alt = not is_ul and cell.get_ue_cfg()->use_tbs_index_alt;
|
||||||
}
|
|
||||||
|
|
||||||
tbs_info cqi_to_tbs(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, bool is_ul)
|
tbs_info tb;
|
||||||
{
|
if (req_bytes <= 0) {
|
||||||
using ul64qam_cap = sched_interface::ue_cfg_t::ul64qam_cap;
|
tb = compute_mcs_and_tbs(nof_prb, nof_re, cqi, max_mcs, is_ul, ulqam64_enabled, use_tbs_index_alt);
|
||||||
uint32_t max_Qm;
|
|
||||||
int max_mcs;
|
|
||||||
float max_coderate;
|
|
||||||
if (is_ul) {
|
|
||||||
max_mcs = cell.max_mcs_ul;
|
|
||||||
max_Qm = cell.get_ue_cfg()->support_ul64qam == ul64qam_cap::enabled ? 6 : 4;
|
|
||||||
max_coderate = srslte_cqi_to_coderate(std::min(cell.ul_cqi + 1u, 15u), false);
|
|
||||||
} else {
|
} else {
|
||||||
max_mcs = cell.max_mcs_dl;
|
tb = compute_min_mcs_and_tbs_from_required_bytes(
|
||||||
max_Qm = cell.get_ue_cfg()->use_tbs_index_alt ? 8 : 6;
|
nof_prb, nof_re, cqi, max_mcs, req_bytes, is_ul, ulqam64_enabled, use_tbs_index_alt);
|
||||||
max_coderate = srslte_cqi_to_coderate(std::min(cell.dl_cqi + 1u, 15u), cell.get_ue_cfg()->use_tbs_index_alt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// function with sign-flip at solution
|
|
||||||
auto test_mcs = [&](int sel_mcs) -> float {
|
|
||||||
return diff_coderate_maxcoderate(
|
|
||||||
sel_mcs, nof_prb, nof_re, max_Qm, max_coderate, cell.get_ue_cfg()->use_tbs_index_alt, is_ul);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::tuple<int, float, int, float> ret;
|
|
||||||
if (nof_prb > 1) {
|
|
||||||
// for non-voip case
|
|
||||||
ret = false_position_method(0, max_mcs, 0.0f, test_mcs);
|
|
||||||
} else {
|
|
||||||
// avoid 6 prbs (voip case), where function is not monotonic
|
|
||||||
ret = false_position_method(7, max_mcs, 0.0f, test_mcs);
|
|
||||||
if (std::get<1>(ret) > 0) {
|
|
||||||
ret = false_position_method(0, 5, 0.0f, test_mcs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tbs_info ret2;
|
|
||||||
ret2.mcs = std::get<0>(ret);
|
|
||||||
ret2.tbs_bytes = get_tbs_bytes(ret2.mcs, nof_prb, cell.get_ue_cfg()->use_tbs_index_alt, is_ul);
|
|
||||||
|
|
||||||
tbs_info ret3 = compute_mcs_and_tbs(nof_prb,
|
|
||||||
nof_re,
|
|
||||||
(is_ul) ? cell.ul_cqi : cell.dl_cqi,
|
|
||||||
max_mcs,
|
|
||||||
is_ul,
|
|
||||||
is_ul and cell.get_ue_cfg()->support_ul64qam == ul64qam_cap::enabled,
|
|
||||||
not is_ul and cell.get_ue_cfg()->use_tbs_index_alt);
|
|
||||||
assert((ret3.mcs == ret2.mcs and ret3.tbs_bytes == ret2.tbs_bytes) or (std::get<0>(ret) == std::get<2>(ret)));
|
|
||||||
|
|
||||||
// If coderate > SRSLTE_MIN(max_coderate, 0.930 * Qm) we should set TBS=0. We don't because it's not correctly
|
// If coderate > SRSLTE_MIN(max_coderate, 0.930 * Qm) we should set TBS=0. We don't because it's not correctly
|
||||||
// handled by the scheduler, but we might be scheduling undecodable codewords at very low SNR
|
// handled by the scheduler, but we might be scheduling undecodable codewords at very low SNR
|
||||||
|
if (tb.tbs_bytes < 0) {
|
||||||
return ret2;
|
tb.mcs = 0;
|
||||||
}
|
tb.tbs_bytes = get_tbs_bytes((uint32_t)tb.mcs, nof_prb, use_tbs_index_alt, is_ul);
|
||||||
|
|
||||||
/* In this scheduler we tend to use all the available bandwidth and select the MCS
|
|
||||||
* that approximates the minimum between the capacity and the requested rate
|
|
||||||
*/
|
|
||||||
tbs_info alloc_tbs(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, bool is_ul)
|
|
||||||
{
|
|
||||||
// TODO: Compute real spectral efficiency based on PUSCH-UCI configuration
|
|
||||||
tbs_info ret = cqi_to_tbs(cell, nof_prb, nof_re, is_ul);
|
|
||||||
|
|
||||||
/* If less bytes are requested, lower the MCS */
|
|
||||||
if (ret.tbs_bytes > (int)req_bytes && req_bytes > 0) {
|
|
||||||
int req_tbs_idx = srslte_ra_tbs_to_table_idx(req_bytes * 8, nof_prb);
|
|
||||||
int req_mcs = srslte_ra_mcs_from_tbs_idx(req_tbs_idx, cell.get_ue_cfg()->use_tbs_index_alt, is_ul);
|
|
||||||
while (cell.get_ue_cfg()->use_tbs_index_alt and req_mcs < 0 and req_tbs_idx < 33) {
|
|
||||||
// some tbs_idx are invalid for 256QAM. See TS 36.213 - Table 7.1.7.1-1A
|
|
||||||
req_mcs = srslte_ra_mcs_from_tbs_idx(++req_tbs_idx, cell.get_ue_cfg()->use_tbs_index_alt, is_ul);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req_mcs >= 0 and req_mcs < (int)ret.mcs) {
|
|
||||||
uint32_t max_Qm =
|
|
||||||
(is_ul) ? (cell.get_ue_cfg()->support_ul64qam == sched_interface::ue_cfg_t::ul64qam_cap::enabled ? 6 : 4)
|
|
||||||
: (cell.get_ue_cfg()->use_tbs_index_alt ? 8 : 6);
|
|
||||||
float max_coderate =
|
|
||||||
(is_ul) ? srslte_cqi_to_coderate(std::min(cell.ul_cqi + 1u, 15u), false)
|
|
||||||
: srslte_cqi_to_coderate(std::min(cell.dl_cqi + 1u, 15u), cell.get_ue_cfg()->use_tbs_index_alt);
|
|
||||||
if (diff_coderate_maxcoderate(
|
|
||||||
req_mcs, nof_prb, nof_re, max_Qm, max_coderate, cell.get_ue_cfg()->use_tbs_index_alt, is_ul) < 0) {
|
|
||||||
ret.mcs = req_mcs;
|
|
||||||
ret.tbs_bytes = srslte_ra_tbs_from_idx(req_tbs_idx, nof_prb) / 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Avoid the unusual case n_prb=1, mcs=6 tbs=328 (used in voip)
|
|
||||||
if (nof_prb == 1 && ret.mcs == 6) {
|
|
||||||
ret.mcs--;
|
|
||||||
ret.tbs_bytes = get_tbs_bytes(ret.mcs, nof_prb, cell.get_ue_cfg()->use_tbs_index_alt, is_ul);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbs_info alloc_tbs_dl(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes)
|
tbs_info alloc_tbs_dl(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, int req_bytes)
|
||||||
{
|
{
|
||||||
tbs_info ret;
|
tbs_info ret;
|
||||||
|
|
||||||
// Use a higher MCS for the Msg4 to fit in the 6 PRB case
|
// Use a higher MCS for the Msg4 to fit in the 6 PRB case
|
||||||
if (cell.fixed_mcs_dl < 0 or not cell.dl_cqi_rx) {
|
if (cell.fixed_mcs_dl < 0 or not cell.dl_cqi_rx) {
|
||||||
// Dynamic MCS
|
// Dynamic MCS
|
||||||
ret = alloc_tbs(cell, nof_prb, nof_re, req_bytes, false);
|
ret = cqi_to_tbs(cell, nof_prb, nof_re, req_bytes, false);
|
||||||
} else {
|
} else {
|
||||||
// Fixed MCS
|
// Fixed MCS
|
||||||
ret.mcs = cell.fixed_mcs_dl;
|
ret.mcs = cell.fixed_mcs_dl;
|
||||||
|
@ -345,15 +268,14 @@ tbs_info alloc_tbs_dl(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbs_info
|
tbs_info alloc_tbs_ul(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, int req_bytes, int explicit_mcs)
|
||||||
alloc_tbs_ul(const sched_ue_cell& cell, uint32_t nof_prb, uint32_t nof_re, uint32_t req_bytes, int explicit_mcs)
|
|
||||||
{
|
{
|
||||||
tbs_info ret;
|
tbs_info ret;
|
||||||
int mcs = explicit_mcs >= 0 ? explicit_mcs : cell.fixed_mcs_ul;
|
int mcs = explicit_mcs >= 0 ? explicit_mcs : cell.fixed_mcs_ul;
|
||||||
|
|
||||||
if (mcs < 0) {
|
if (mcs < 0) {
|
||||||
// Dynamic MCS
|
// Dynamic MCS
|
||||||
ret = alloc_tbs(cell, nof_prb, nof_re, req_bytes, true);
|
ret = cqi_to_tbs(cell, nof_prb, nof_re, req_bytes, true);
|
||||||
} else {
|
} else {
|
||||||
// Fixed MCS
|
// Fixed MCS
|
||||||
ret.mcs = mcs;
|
ret.mcs = mcs;
|
||||||
|
@ -367,7 +289,7 @@ int get_required_prb_dl(const sched_ue_cell& cell, tti_point tti_tx_dl, uint32_t
|
||||||
{
|
{
|
||||||
auto compute_tbs_approx = [tti_tx_dl, &cell](uint32_t nof_prb) {
|
auto compute_tbs_approx = [tti_tx_dl, &cell](uint32_t nof_prb) {
|
||||||
uint32_t nof_re = cell.cell_cfg->get_dl_lb_nof_re(tti_tx_dl, nof_prb);
|
uint32_t nof_re = cell.cell_cfg->get_dl_lb_nof_re(tti_tx_dl, nof_prb);
|
||||||
tbs_info tb = alloc_tbs_dl(cell, nof_prb, nof_re, 0);
|
tbs_info tb = alloc_tbs_dl(cell, nof_prb, nof_re, -1);
|
||||||
return tb.tbs_bytes;
|
return tb.tbs_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -386,7 +308,7 @@ uint32_t get_required_prb_ul(const sched_ue_cell& cell, uint32_t req_bytes)
|
||||||
auto compute_tbs_approx = [&cell](uint32_t nof_prb) {
|
auto compute_tbs_approx = [&cell](uint32_t nof_prb) {
|
||||||
const uint32_t N_srs = 0;
|
const uint32_t N_srs = 0;
|
||||||
uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell.cell_cfg->cfg.cell.cp) - 1) - N_srs) * nof_prb * SRSLTE_NRE;
|
uint32_t nof_re = (2 * (SRSLTE_CP_NSYMB(cell.cell_cfg->cfg.cell.cp) - 1) - N_srs) * nof_prb * SRSLTE_NRE;
|
||||||
return alloc_tbs_ul(cell, nof_prb, nof_re, 0).tbs_bytes;
|
return alloc_tbs_ul(cell, nof_prb, nof_re, -1).tbs_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
// find nof prbs that lead to a tbs just above req_bytes
|
// find nof prbs that lead to a tbs just above req_bytes
|
||||||
|
|
|
@ -263,7 +263,7 @@ int common_sched_tester::run_tti(const tti_ev& tti_events)
|
||||||
ul_sched(to_tx_ul(tti_rx).to_uint(), i, tti_info.ul_sched_result[i]);
|
ul_sched(to_tx_ul(tti_rx).to_uint(), i, tti_info.ul_sched_result[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
process_results();
|
TESTASSERT(process_results() == SRSLTE_SUCCESS);
|
||||||
tti_count++;
|
tti_count++;
|
||||||
return SRSLTE_SUCCESS;
|
return SRSLTE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue