mirror of https://github.com/PentHertz/srsLTE.git
sched - wrote benchmark to detect regressions in DL/UL data rates, and to analyse the total latency of the scheduler
This commit is contained in:
parent
5f954ab379
commit
d334907afe
|
@ -58,3 +58,7 @@ add_test(sched_tpc_test sched_tpc_test)
|
|||
add_executable(sched_dci_test sched_dci_test.cc)
|
||||
target_link_libraries(sched_dci_test srslte_common srsenb_mac srslte_mac sched_test_common)
|
||||
add_test(sched_dci_test sched_dci_test)
|
||||
|
||||
add_executable(sched_benchmark_test sched_benchmark.cc)
|
||||
target_link_libraries(sched_benchmark_test srslte_common srsenb_mac srslte_mac sched_test_common)
|
||||
add_test(sched_benchmark_test sched_benchmark_test)
|
||||
|
|
|
@ -0,0 +1,401 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sched_test_common.h"
|
||||
#include "srsenb/hdr/stack/mac/sched.h"
|
||||
#include "srslte/adt/accumulators.h"
|
||||
#include <chrono>
|
||||
|
||||
const uint32_t seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
struct run_params {
|
||||
uint32_t nof_prbs;
|
||||
uint32_t nof_ues;
|
||||
uint32_t nof_ttis;
|
||||
uint32_t cqi;
|
||||
const char* sched_policy;
|
||||
};
|
||||
|
||||
struct run_params_range {
|
||||
std::vector<uint32_t> nof_prbs = {6, 15, 25, 50, 75, 100};
|
||||
std::vector<uint32_t> nof_ues = {1, 2, 5};
|
||||
uint32_t nof_ttis = 10000;
|
||||
std::vector<uint32_t> cqi = {5, 10, 15};
|
||||
std::vector<const char*> sched_policy = {"time_rr", "time_pf"};
|
||||
|
||||
size_t nof_runs() const { return nof_prbs.size() * nof_ues.size() * cqi.size() * sched_policy.size(); }
|
||||
run_params get_params(size_t idx) const
|
||||
{
|
||||
run_params r = {};
|
||||
r.nof_ttis = nof_ttis;
|
||||
r.nof_prbs = nof_prbs[idx % nof_prbs.size()];
|
||||
idx /= nof_prbs.size();
|
||||
r.nof_ues = nof_ues[idx % nof_ues.size()];
|
||||
idx /= nof_ues.size();
|
||||
r.cqi = cqi[idx % cqi.size()];
|
||||
idx /= cqi.size();
|
||||
r.sched_policy = sched_policy.at(idx);
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
class sched_tester : public sched_sim_base
|
||||
{
|
||||
static std::vector<sched_interface::cell_cfg_t> get_cell_cfg(srslte::span<const sched_cell_params_t> cell_params)
|
||||
{
|
||||
std::vector<sched_interface::cell_cfg_t> cell_cfg_list;
|
||||
for (auto& c : cell_params) {
|
||||
cell_cfg_list.push_back(c.cfg);
|
||||
}
|
||||
return cell_cfg_list;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit sched_tester(sched* sched_obj_,
|
||||
const sched_interface::sched_args_t& sched_args,
|
||||
const std::vector<sched_interface::cell_cfg_t>& cell_cfg_list) :
|
||||
sched_sim_base(sched_obj_, sched_args, cell_cfg_list),
|
||||
sched_ptr(sched_obj_),
|
||||
dl_result(cell_cfg_list.size()),
|
||||
ul_result(cell_cfg_list.size())
|
||||
{}
|
||||
|
||||
srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("MAC");
|
||||
sched* sched_ptr;
|
||||
uint32_t dl_bytes_per_tti = 100000;
|
||||
uint32_t ul_bytes_per_tti = 100000;
|
||||
run_params current_run_params = {};
|
||||
|
||||
std::vector<sched_interface::dl_sched_res_t> dl_result;
|
||||
std::vector<sched_interface::ul_sched_res_t> ul_result;
|
||||
|
||||
struct throughput_stats {
|
||||
srslte::rolling_average<float> mean_dl_tbs, mean_ul_tbs, avg_dl_mcs, avg_ul_mcs;
|
||||
srslte::rolling_average<float> avg_latency;
|
||||
};
|
||||
throughput_stats total_stats;
|
||||
|
||||
int advance_tti()
|
||||
{
|
||||
tti_point tti_rx = get_tti_rx().is_valid() ? get_tti_rx() + 1 : tti_point(0);
|
||||
mac_logger.set_context(tti_rx.to_uint());
|
||||
new_tti(tti_rx);
|
||||
|
||||
for (uint32_t cc = 0; cc < get_cell_params().size(); ++cc) {
|
||||
std::chrono::time_point<std::chrono::steady_clock> tp = std::chrono::steady_clock::now();
|
||||
TESTASSERT(sched_ptr->dl_sched(to_tx_dl(tti_rx).to_uint(), cc, dl_result[cc]) == SRSLTE_SUCCESS);
|
||||
TESTASSERT(sched_ptr->ul_sched(to_tx_ul(tti_rx).to_uint(), cc, ul_result[cc]) == SRSLTE_SUCCESS);
|
||||
std::chrono::time_point<std::chrono::steady_clock> tp2 = std::chrono::steady_clock::now();
|
||||
std::chrono::nanoseconds tdur = std::chrono::duration_cast<std::chrono::nanoseconds>(tp2 - tp);
|
||||
total_stats.avg_latency.push(tdur.count());
|
||||
}
|
||||
|
||||
sf_output_res_t sf_out{get_cell_params(), tti_rx, ul_result, dl_result};
|
||||
update(sf_out);
|
||||
process_stats(sf_out);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void set_external_tti_events(const sim_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) override
|
||||
{
|
||||
// do nothing
|
||||
if (ue_ctxt.conres_rx) {
|
||||
sched_ptr->ul_bsr(ue_ctxt.rnti, 1, dl_bytes_per_tti);
|
||||
sched_ptr->dl_rlc_buffer_state(ue_ctxt.rnti, 3, ul_bytes_per_tti, 0);
|
||||
|
||||
if (get_tti_rx().to_uint() % 5 == 0) {
|
||||
for (uint32_t cc = 0; cc < pending_events.cc_list.size(); ++cc) {
|
||||
pending_events.cc_list[cc].dl_cqi = current_run_params.cqi;
|
||||
pending_events.cc_list[cc].ul_snr = 40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_stats(sf_output_res_t& sf_out)
|
||||
{
|
||||
for (uint32_t cc = 0; cc < get_cell_params().size(); ++cc) {
|
||||
uint32_t dl_tbs = 0, ul_tbs = 0, dl_mcs = 0, ul_mcs = 0;
|
||||
for (uint32_t i = 0; i < sf_out.dl_cc_result[cc].nof_data_elems; ++i) {
|
||||
dl_tbs += sf_out.dl_cc_result[cc].data[i].tbs[0];
|
||||
dl_tbs += sf_out.dl_cc_result[cc].data[i].tbs[1];
|
||||
dl_mcs = std::max(dl_mcs, sf_out.dl_cc_result[cc].data[i].dci.tb[0].mcs_idx);
|
||||
}
|
||||
total_stats.mean_dl_tbs.push(dl_tbs);
|
||||
if (sf_out.dl_cc_result[cc].nof_data_elems > 0) {
|
||||
total_stats.avg_dl_mcs.push(dl_mcs);
|
||||
}
|
||||
for (uint32_t i = 0; i < sf_out.ul_cc_result[cc].nof_dci_elems; ++i) {
|
||||
ul_tbs += sf_out.ul_cc_result[cc].pusch[i].tbs;
|
||||
ul_mcs = std::max(ul_mcs, sf_out.ul_cc_result[cc].pusch[i].dci.tb.mcs_idx);
|
||||
}
|
||||
total_stats.mean_ul_tbs.push(ul_tbs);
|
||||
if (sf_out.ul_cc_result[cc].nof_dci_elems) {
|
||||
total_stats.avg_ul_mcs.push(ul_mcs);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int run_sched_new_ue(sched_tester& sched_tester,
|
||||
const run_params& params,
|
||||
uint16_t rnti,
|
||||
const sched_interface::ue_cfg_t& ue_cfg)
|
||||
{
|
||||
const uint32_t ENB_CC_IDX = 0;
|
||||
|
||||
sched_tester.total_stats = {};
|
||||
sched_tester.current_run_params = params;
|
||||
|
||||
// Add user (first need to advance to a PRACH TTI)
|
||||
while (not srslte_prach_tti_opportunity_config_fdd(
|
||||
sched_tester.get_cell_params()[ue_cfg.supported_cc_list[0].enb_cc_idx].cfg.prach_config,
|
||||
sched_tester.get_tti_rx().to_uint(),
|
||||
-1)) {
|
||||
TESTASSERT(sched_tester.advance_tti() == SRSLTE_SUCCESS);
|
||||
}
|
||||
TESTASSERT(sched_tester.add_user(rnti, ue_cfg, 16) == SRSLTE_SUCCESS);
|
||||
|
||||
// Ignore stats of the first TTIs until UE DRB1 is added
|
||||
while (not sched_tester.get_enb_ctxt().ue_db.at(rnti)->conres_rx) {
|
||||
sched_tester.advance_tti();
|
||||
}
|
||||
sched_tester.total_stats = {};
|
||||
|
||||
for (uint32_t count = 0; count < params.nof_ttis; ++count) {
|
||||
sched_tester.advance_tti();
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
struct run_data {
|
||||
run_params params;
|
||||
float avg_dl_throughput;
|
||||
float avg_ul_throughput;
|
||||
float avg_dl_mcs;
|
||||
float avg_ul_mcs;
|
||||
std::chrono::microseconds avg_latency;
|
||||
};
|
||||
|
||||
int run_benchmark_scenario(run_params params, std::vector<run_data>& run_results)
|
||||
{
|
||||
std::vector<sched_interface::cell_cfg_t> cell_list(1, generate_default_cell_cfg(params.nof_prbs));
|
||||
sched_interface::ue_cfg_t ue_cfg_default = generate_default_ue_cfg();
|
||||
sched_interface::sched_args_t sched_args = {};
|
||||
sched_args.sched_policy = params.sched_policy;
|
||||
|
||||
sched sched_obj;
|
||||
sched_obj.init(nullptr, sched_args);
|
||||
sched_tester tester(&sched_obj, sched_args, cell_list);
|
||||
|
||||
tester.total_stats = {};
|
||||
tester.current_run_params = params;
|
||||
|
||||
for (uint32_t ue_idx = 0; ue_idx < params.nof_ues; ++ue_idx) {
|
||||
uint16_t rnti = 0x46 + ue_idx;
|
||||
// Add user (first need to advance to a PRACH TTI)
|
||||
while (not srslte_prach_tti_opportunity_config_fdd(
|
||||
tester.get_cell_params()[ue_cfg_default.supported_cc_list[0].enb_cc_idx].cfg.prach_config,
|
||||
tester.get_tti_rx().to_uint(),
|
||||
-1)) {
|
||||
TESTASSERT(tester.advance_tti() == SRSLTE_SUCCESS);
|
||||
}
|
||||
TESTASSERT(tester.add_user(rnti, ue_cfg_default, 16) == SRSLTE_SUCCESS);
|
||||
TESTASSERT(tester.advance_tti() == SRSLTE_SUCCESS);
|
||||
}
|
||||
|
||||
// Ignore stats of the first TTIs until all UEs DRB1 are created
|
||||
auto ue_db_ctxt = tester.get_enb_ctxt().ue_db;
|
||||
while (not std::all_of(ue_db_ctxt.begin(), ue_db_ctxt.end(), [](std::pair<uint16_t, const sim_ue_ctxt_t*> p) {
|
||||
return p.second->conres_rx;
|
||||
})) {
|
||||
tester.advance_tti();
|
||||
ue_db_ctxt = tester.get_enb_ctxt().ue_db;
|
||||
}
|
||||
tester.total_stats = {};
|
||||
|
||||
// Run benchmark
|
||||
for (uint32_t count = 0; count < params.nof_ttis; ++count) {
|
||||
tester.advance_tti();
|
||||
}
|
||||
|
||||
run_data run_result = {};
|
||||
run_result.params = params;
|
||||
run_result.avg_dl_throughput = tester.total_stats.mean_dl_tbs.value() * 8.0 / 1e-3;
|
||||
run_result.avg_ul_throughput = tester.total_stats.mean_ul_tbs.value() * 8.0 / 1e-3;
|
||||
run_result.avg_dl_mcs = tester.total_stats.avg_dl_mcs.value();
|
||||
run_result.avg_ul_mcs = tester.total_stats.avg_ul_mcs.value();
|
||||
run_result.avg_latency = std::chrono::microseconds(static_cast<int>(tester.total_stats.avg_latency.value() / 1000));
|
||||
run_results.push_back(run_result);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
run_data expected_run_result(run_params params)
|
||||
{
|
||||
assert(params.cqi == 15 && "only cqi=15 supported for now");
|
||||
run_data ret{};
|
||||
float dl_overhead = 0.9, ul_overhead = 0.75;
|
||||
switch (params.nof_prbs) {
|
||||
case 6:
|
||||
ret.avg_dl_mcs = 25;
|
||||
ret.avg_ul_mcs = 22;
|
||||
dl_overhead = 0.8;
|
||||
ul_overhead = 0.4;
|
||||
break;
|
||||
default:
|
||||
ret.avg_dl_mcs = 26;
|
||||
ret.avg_ul_mcs = 22;
|
||||
}
|
||||
|
||||
int tbs_idx = srslte_ra_tbs_idx_from_mcs(ret.avg_dl_mcs, false, false);
|
||||
int tbs = srslte_ra_tbs_from_idx(tbs_idx, params.nof_prbs);
|
||||
ret.avg_dl_throughput = tbs * 1e3 * dl_overhead; // bps
|
||||
|
||||
tbs_idx = srslte_ra_tbs_idx_from_mcs(ret.avg_ul_mcs, false, true);
|
||||
tbs = srslte_ra_tbs_from_idx(tbs_idx, params.nof_prbs - 2);
|
||||
ret.avg_ul_throughput = tbs * 1e3 * ul_overhead; // bps
|
||||
return ret;
|
||||
}
|
||||
|
||||
int run_rate_test()
|
||||
{
|
||||
run_params_range run_param_list{};
|
||||
srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("MAC");
|
||||
|
||||
run_param_list.nof_ues = {1};
|
||||
run_param_list.cqi = {15};
|
||||
|
||||
std::vector<run_data> run_results;
|
||||
size_t nof_runs = run_param_list.nof_runs();
|
||||
|
||||
for (size_t r = 0; r < nof_runs; ++r) {
|
||||
run_params runparams = run_param_list.get_params(r);
|
||||
|
||||
mac_logger.info("\n### New run {} ###\n", r);
|
||||
TESTASSERT(run_benchmark_scenario(runparams, run_results) == SRSLTE_SUCCESS);
|
||||
}
|
||||
|
||||
const std::array<float, 6> expected_dl_rate_Mbps{2.5, 8.8, 15, 31, 47, 64};
|
||||
const std::array<float, 6> expected_ul_rate_Mbps{0.1, 1.8, 4, 8.3, 13, 19};
|
||||
bool success = true;
|
||||
for (auto& run : run_results) {
|
||||
run_data expected = expected_run_result(run.params);
|
||||
if (run.avg_dl_mcs < expected.avg_dl_mcs) {
|
||||
fmt::print(
|
||||
"Nprb={:>2d}: DL mcs below expected ({} < {})\n", run.params.nof_prbs, run.avg_dl_mcs, expected.avg_dl_mcs);
|
||||
success = false;
|
||||
}
|
||||
if (run.avg_dl_throughput < expected.avg_dl_throughput) {
|
||||
fmt::print("Nprb={:>2d}: DL rate below expected ({:.2} < {:.2}) Mbps\n",
|
||||
run.params.nof_prbs,
|
||||
run.avg_dl_throughput / 1e6,
|
||||
expected.avg_dl_throughput / 1e6);
|
||||
success = false;
|
||||
}
|
||||
if (run.avg_ul_mcs < expected.avg_ul_mcs) {
|
||||
fmt::print(
|
||||
"Nprb={:>2d}: UL mcs below expected ({} < {})\n", run.params.nof_prbs, run.avg_ul_mcs, expected.avg_ul_mcs);
|
||||
success = false;
|
||||
}
|
||||
if (run.avg_ul_throughput < expected.avg_ul_throughput) {
|
||||
fmt::print("Nprb={:>2d}: UL rate below expected ({:.2} < {:.2}) Mbps\n",
|
||||
run.params.nof_prbs,
|
||||
run.avg_ul_throughput / 1e6,
|
||||
expected.avg_ul_throughput / 1e6);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success ? SRSLTE_SUCCESS : SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
void print_benchmark_results(const std::vector<run_data>& run_results)
|
||||
{
|
||||
srslog::flush();
|
||||
fmt::print("run | Nprb | cqi | sched pol | Nue | DL [Mbps] | UL [Mbps] | DL mcs | UL mcs | latency [usec]\n");
|
||||
fmt::print("---------------------------------------------------------------------------------------------\n");
|
||||
for (uint32_t i = 0; i < run_results.size(); ++i) {
|
||||
const run_data& r = run_results[i];
|
||||
fmt::print("{:>3d}{:>6d}{:>6d}{:>12}{:>6d}{:12.2}{:12.2}{:9.1f}{:9.1f}{:12d}\n",
|
||||
i,
|
||||
r.params.nof_prbs,
|
||||
r.params.cqi,
|
||||
r.params.sched_policy,
|
||||
r.params.nof_ues,
|
||||
r.avg_dl_throughput / 1e6,
|
||||
r.avg_ul_throughput / 1e6,
|
||||
r.avg_dl_mcs,
|
||||
r.avg_ul_mcs,
|
||||
r.avg_latency.count());
|
||||
}
|
||||
}
|
||||
|
||||
int run_benchmark()
|
||||
{
|
||||
run_params_range run_param_list{};
|
||||
srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("MAC");
|
||||
|
||||
std::vector<run_data> run_results;
|
||||
size_t nof_runs = run_param_list.nof_runs();
|
||||
for (size_t r = 0; r < nof_runs; ++r) {
|
||||
run_params runparams = run_param_list.get_params(r);
|
||||
|
||||
mac_logger.info("\n### New run {} ###\n", r);
|
||||
TESTASSERT(run_benchmark_scenario(runparams, run_results) == SRSLTE_SUCCESS);
|
||||
}
|
||||
|
||||
print_benchmark_results(run_results);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
int main()
|
||||
{
|
||||
// Setup seed
|
||||
srsenb::set_randseed(seed);
|
||||
printf("This is the chosen seed: %u\n", seed);
|
||||
|
||||
// Setup the log spy to intercept error and warning log entries.
|
||||
if (!srslog::install_custom_sink(
|
||||
srslte::log_sink_spy::name(),
|
||||
std::unique_ptr<srslte::log_sink_spy>(new srslte::log_sink_spy(srslog::get_default_log_formatter())))) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
auto* spy = static_cast<srslte::log_sink_spy*>(srslog::find_sink(srslte::log_sink_spy::name()));
|
||||
if (!spy) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
auto& mac_log = srslog::fetch_basic_logger("MAC");
|
||||
mac_log.set_level(srslog::basic_levels::warning);
|
||||
auto& test_log = srslog::fetch_basic_logger("TEST", *spy, false);
|
||||
test_log.set_level(srslog::basic_levels::warning);
|
||||
|
||||
// Start the log backend.
|
||||
srslog::init();
|
||||
|
||||
bool run_benchmark = false;
|
||||
|
||||
TESTASSERT(srsenb::run_rate_test() == SRSLTE_SUCCESS);
|
||||
if (run_benchmark) {
|
||||
TESTASSERT(srsenb::run_benchmark() == SRSLTE_SUCCESS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -211,10 +211,21 @@ void ue_sim::update_conn_state(const sf_output_res_t& sf_out)
|
|||
}
|
||||
}
|
||||
|
||||
sched_sim_base::sched_sim_base(sched_interface* sched_ptr_,
|
||||
const sched_interface::sched_args_t& sched_args,
|
||||
const std::vector<sched_interface::cell_cfg_t>& cell_cfg_list) :
|
||||
logger(srslog::fetch_basic_logger("TEST")), sched_ptr(sched_ptr_), cell_params(cell_cfg_list.size())
|
||||
{
|
||||
for (uint32_t cc = 0; cc < cell_params.size(); ++cc) {
|
||||
cell_params[cc].set_cfg(cc, cell_cfg_list[cc], sched_args);
|
||||
}
|
||||
sched_ptr->cell_cfg(cell_cfg_list); // call parent cfg
|
||||
}
|
||||
|
||||
int sched_sim_base::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx)
|
||||
{
|
||||
CONDERROR(!srslte_prach_tti_opportunity_config_fdd(
|
||||
(*cell_params)[ue_cfg_.supported_cc_list[0].enb_cc_idx].prach_config, current_tti_rx.to_uint(), -1),
|
||||
cell_params[ue_cfg_.supported_cc_list[0].enb_cc_idx].cfg.prach_config, current_tti_rx.to_uint(), -1),
|
||||
"New user added in a non-PRACH TTI");
|
||||
TESTASSERT(ue_db.count(rnti) == 0);
|
||||
|
||||
|
@ -278,7 +289,7 @@ sim_enb_ctxt_t sched_sim_base::get_enb_ctxt() const
|
|||
int sched_sim_base::set_default_tti_events(const sim_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events)
|
||||
{
|
||||
pending_events.cc_list.clear();
|
||||
pending_events.cc_list.resize(cell_params->size());
|
||||
pending_events.cc_list.resize(cell_params.size());
|
||||
pending_events.tti_rx = current_tti_rx;
|
||||
|
||||
for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_events.cc_list.size(); ++enb_cc_idx) {
|
||||
|
@ -371,8 +382,8 @@ int sched_sim_base::apply_tti_events(sim_ue_ctxt_t& ue_ctxt, const ue_tti_events
|
|||
sched_ptr->dl_cqi_info(events.tti_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.dl_cqi);
|
||||
}
|
||||
|
||||
if (cc_feedback.ul_cqi >= 0) {
|
||||
sched_ptr->ul_snr_info(events.tti_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.ul_cqi, 0);
|
||||
if (cc_feedback.ul_snr >= 0) {
|
||||
sched_ptr->ul_snr_info(events.tti_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.ul_snr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,8 +52,8 @@ struct sim_ue_ctxt_t {
|
|||
};
|
||||
|
||||
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;
|
||||
srslte::span<const sched_cell_params_t> cell_params;
|
||||
std::map<uint16_t, const sim_ue_ctxt_t*> ue_db;
|
||||
};
|
||||
struct ue_tti_events {
|
||||
struct cc_data {
|
||||
|
@ -65,7 +65,7 @@ struct ue_tti_events {
|
|||
int ul_pid = -1;
|
||||
bool ul_ack = false;
|
||||
int dl_cqi = -1;
|
||||
int ul_cqi = -1;
|
||||
int ul_snr = -1;
|
||||
};
|
||||
srslte::tti_point tti_rx;
|
||||
std::vector<cc_data> cc_list;
|
||||
|
@ -99,11 +99,9 @@ private:
|
|||
class sched_sim_base
|
||||
{
|
||||
public:
|
||||
sched_sim_base(sched_interface* sched_ptr_, const std::vector<sched_interface::cell_cfg_t>& cell_params_) :
|
||||
logger(srslog::fetch_basic_logger("MAC")), sched_ptr(sched_ptr_), cell_params(&cell_params_)
|
||||
{
|
||||
sched_ptr->cell_cfg(cell_params_); // call parent cfg
|
||||
}
|
||||
sched_sim_base(sched_interface* sched_ptr_,
|
||||
const sched_interface::sched_args_t& sched_args,
|
||||
const std::vector<sched_interface::cell_cfg_t>& cell_params_);
|
||||
virtual ~sched_sim_base() = default;
|
||||
|
||||
int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx);
|
||||
|
@ -133,6 +131,9 @@ public:
|
|||
const ue_sim* ret = find_rnti(rnti);
|
||||
return ret == nullptr ? nullptr : &ret->get_ctxt().ue_cfg;
|
||||
}
|
||||
sched_interface* get_sched() { return sched_ptr; }
|
||||
srslte::const_span<sched_cell_params_t> get_cell_params() { return cell_params; }
|
||||
tti_point get_tti_rx() const { return current_tti_rx; }
|
||||
|
||||
std::map<uint16_t, ue_sim>::iterator begin() { return ue_db.begin(); }
|
||||
std::map<uint16_t, ue_sim>::iterator end() { return ue_db.end(); }
|
||||
|
@ -144,9 +145,9 @@ private:
|
|||
int set_default_tti_events(const sim_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events);
|
||||
int apply_tti_events(sim_ue_ctxt_t& ue_ctxt, const ue_tti_events& events);
|
||||
|
||||
srslog::basic_logger& logger;
|
||||
sched_interface* sched_ptr;
|
||||
const std::vector<sched_interface::cell_cfg_t>* cell_params;
|
||||
srslog::basic_logger& logger;
|
||||
sched_interface* sched_ptr;
|
||||
std::vector<sched_cell_params_t> cell_params;
|
||||
|
||||
srslte::tti_point current_tti_rx;
|
||||
std::map<uint16_t, ue_sim> ue_db;
|
||||
|
|
|
@ -74,8 +74,8 @@ void sched_sim_random::set_external_tti_events(const sim_ue_ctxt_t& ue_ctxt, ue_
|
|||
}
|
||||
|
||||
// UL CQI
|
||||
if (cc_feedback.ul_cqi >= 0) {
|
||||
cc_feedback.ul_cqi = std::uniform_int_distribution<uint32_t>{5, 40}(get_rand_gen());
|
||||
if (cc_feedback.ul_snr >= 0) {
|
||||
cc_feedback.ul_snr = std::uniform_int_distribution<uint32_t>{5, 40}(get_rand_gen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ int common_sched_tester::sim_cfg(sim_sched_args args)
|
|||
|
||||
sched::init(&rrc_ptr, sim_args0.sched_args);
|
||||
|
||||
sched_sim.reset(new sched_sim_random{this, sim_args0.cell_cfg});
|
||||
sched_sim.reset(new sched_sim_random{this, sim_args0.sched_args, sim_args0.cell_cfg});
|
||||
sched_stats.reset(new sched_result_stats{sim_args0.cell_cfg});
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
|
|
|
@ -65,7 +65,7 @@ int test_pdsch_grant(const sim_enb_ctxt_t& enb_ctxt,
|
|||
tti_point tti_rx = sf_out.tti_rx;
|
||||
const sim_ue_ctxt_t& ue_ctxt = *enb_ctxt.ue_db.at(pdsch.dci.rnti);
|
||||
const sched_interface::ue_cfg_t::cc_cfg_t* cc_cfg = ue_ctxt.get_cc_cfg(enb_cc_idx);
|
||||
const sched_interface::cell_cfg_t& cell_params = (*enb_ctxt.cell_params)[enb_cc_idx];
|
||||
const sched_cell_params_t& cell_params = enb_ctxt.cell_params[enb_cc_idx];
|
||||
bool has_pusch_grant = find_pusch_grant(pdsch.dci.rnti, sf_out.ul_cc_result[enb_cc_idx]) != nullptr;
|
||||
|
||||
// TEST: Check if CC is configured and active
|
||||
|
@ -100,8 +100,8 @@ int test_pdsch_grant(const sim_enb_ctxt_t& enb_ctxt,
|
|||
srslte_dl_sf_cfg_t dl_sf = {};
|
||||
dl_sf.cfi = sf_out.dl_cc_result[enb_cc_idx].cfi;
|
||||
dl_sf.tti = to_tx_dl(tti_rx).to_uint();
|
||||
srslte_ra_dl_grant_to_grant_prb_allocation(&pdsch.dci, &grant, cell_params.cell.nof_prb);
|
||||
uint32_t nof_re = srslte_ra_dl_grant_nof_re(&cell_params.cell, &dl_sf, &grant);
|
||||
srslte_ra_dl_grant_to_grant_prb_allocation(&pdsch.dci, &grant, cell_params.nof_prb());
|
||||
uint32_t nof_re = srslte_ra_dl_grant_nof_re(&cell_params.cfg.cell, &dl_sf, &grant);
|
||||
float coderate = srslte_coderate(pdsch.tbs[0] * 8, nof_re);
|
||||
srslte_mod_t mod = srslte_ra_dl_mod_from_mcs(pdsch.dci.tb[0].mcs_idx, ue_ctxt.ue_cfg.use_tbs_index_alt);
|
||||
uint32_t max_Qm = ue_ctxt.ue_cfg.use_tbs_index_alt ? 8 : 6;
|
||||
|
@ -112,7 +112,7 @@ int test_pdsch_grant(const sim_enb_ctxt_t& enb_ctxt,
|
|||
// TEST: PUCCH-ACK will not collide with SR
|
||||
CONDERROR(not has_pusch_grant and is_pucch_sr_collision(ue_ctxt.ue_cfg.pucch_cfg,
|
||||
to_tx_dl_ack(sf_out.tti_rx),
|
||||
pdsch.dci.location.ncce + cell_params.n1pucch_an),
|
||||
pdsch.dci.location.ncce + cell_params.cfg.n1pucch_an),
|
||||
"Collision detected between UE PUCCH-ACK and SR");
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
|
@ -120,7 +120,7 @@ int test_pdsch_grant(const sim_enb_ctxt_t& enb_ctxt,
|
|||
|
||||
int test_dl_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
|
||||
{
|
||||
for (uint32_t cc = 0; cc < enb_ctxt.cell_params->size(); ++cc) {
|
||||
for (uint32_t cc = 0; cc < enb_ctxt.cell_params.size(); ++cc) {
|
||||
for (uint32_t i = 0; i < sf_out.dl_cc_result[cc].nof_data_elems; ++i) {
|
||||
const sched_interface::dl_sched_data_t& data = sf_out.dl_cc_result[cc].data[i];
|
||||
CONDERROR(
|
||||
|
@ -135,7 +135,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t&
|
|||
{
|
||||
uint32_t pid = to_tx_ul(sf_out.tti_rx).to_uint() % (FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS);
|
||||
|
||||
for (size_t cc = 0; cc < enb_ctxt.cell_params->size(); ++cc) {
|
||||
for (size_t cc = 0; cc < enb_ctxt.cell_params.size(); ++cc) {
|
||||
const auto* phich_begin = &sf_out.ul_cc_result[cc].phich[0];
|
||||
const auto* phich_end = &sf_out.ul_cc_result[cc].phich[sf_out.ul_cc_result[cc].nof_phich_elems];
|
||||
const auto* pusch_begin = &sf_out.ul_cc_result[cc].pusch[0];
|
||||
|
@ -228,7 +228,7 @@ int test_ul_sched_result(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t&
|
|||
|
||||
int test_ra(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
|
||||
{
|
||||
for (uint32_t cc = 0; cc < enb_ctxt.cell_params->size(); ++cc) {
|
||||
for (uint32_t cc = 0; cc < enb_ctxt.cell_params.size(); ++cc) {
|
||||
const auto& dl_cc_res = sf_out.dl_cc_result[cc];
|
||||
const auto& ul_cc_res = sf_out.ul_cc_result[cc];
|
||||
for (const auto& ue_pair : enb_ctxt.ue_db) {
|
||||
|
@ -242,7 +242,7 @@ int test_ra(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
|
|||
}
|
||||
|
||||
// TEST: RAR allocation
|
||||
uint32_t rar_win_size = (*enb_ctxt.cell_params)[cc].prach_rar_window;
|
||||
uint32_t rar_win_size = enb_ctxt.cell_params[cc].cfg.prach_rar_window;
|
||||
srslte::tti_interval rar_window{ue.prach_tti_rx + 3, ue.prach_tti_rx + 3 + rar_win_size};
|
||||
srslte::tti_point tti_tx_dl = to_tx_dl(sf_out.tti_rx);
|
||||
|
||||
|
@ -365,7 +365,7 @@ bool is_in_measgap(srslte::tti_point tti, uint32_t period, uint32_t offset)
|
|||
|
||||
int test_meas_gaps(const sim_enb_ctxt_t& enb_ctxt, const sf_output_res_t& sf_out)
|
||||
{
|
||||
for (uint32_t cc = 0; cc < enb_ctxt.cell_params->size(); ++cc) {
|
||||
for (uint32_t cc = 0; cc < enb_ctxt.cell_params.size(); ++cc) {
|
||||
const auto& dl_cc_res = sf_out.dl_cc_result[cc];
|
||||
const auto& ul_cc_res = sf_out.ul_cc_result[cc];
|
||||
for (const auto& ue_pair : enb_ctxt.ue_db) {
|
||||
|
|
Loading…
Reference in New Issue