mirror of https://github.com/PentHertz/srsLTE.git
separated sched tests based on output into a separate file. Added scheduler random tester to unit tests
This commit is contained in:
parent
f6ed99b71b
commit
c537d38650
|
@ -32,6 +32,25 @@
|
||||||
|
|
||||||
namespace srslte {
|
namespace srslte {
|
||||||
|
|
||||||
|
class test_log_singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static srslte::log* get_log() { return get_instance()->current_log; }
|
||||||
|
|
||||||
|
static test_log_singleton* get_instance()
|
||||||
|
{
|
||||||
|
static test_log_singleton* inst = new test_log_singleton{};
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_log(srslte::log* log_) { current_log = log_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
test_log_singleton() = default;
|
||||||
|
|
||||||
|
srslte::log* current_log = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
// logger that we can instantiate in a specific test scope
|
// logger that we can instantiate in a specific test scope
|
||||||
// useful if we want to define specific logging policies within a scope (e.g. null logger, count number of errors,
|
// useful if we want to define specific logging policies within a scope (e.g. null logger, count number of errors,
|
||||||
// exit on error, log special diagnostics on destruction). It restores the previous logger after exiting the scope
|
// exit on error, log special diagnostics on destruction). It restores the previous logger after exiting the scope
|
||||||
|
@ -40,15 +59,15 @@ class scoped_tester_log : public srslte::log_filter
|
||||||
public:
|
public:
|
||||||
explicit scoped_tester_log(std::string layer) : srslte::log_filter(layer)
|
explicit scoped_tester_log(std::string layer) : srslte::log_filter(layer)
|
||||||
{
|
{
|
||||||
previous_log_test = current_log;
|
previous_log_test = test_log_singleton::get_log();
|
||||||
current_log = this;
|
test_log_singleton::get_instance()->register_log(this);
|
||||||
set_level(srslte::LOG_LEVEL_DEBUG);
|
set_level(srslte::LOG_LEVEL_DEBUG);
|
||||||
}
|
}
|
||||||
scoped_tester_log(const scoped_tester_log&) = delete;
|
scoped_tester_log(const scoped_tester_log&) = delete;
|
||||||
scoped_tester_log(scoped_tester_log&&) = delete;
|
scoped_tester_log(scoped_tester_log&&) = delete;
|
||||||
scoped_tester_log& operator=(const scoped_tester_log&) = delete;
|
scoped_tester_log& operator=(const scoped_tester_log&) = delete;
|
||||||
scoped_tester_log& operator=(scoped_tester_log&&) = delete;
|
scoped_tester_log& operator=(scoped_tester_log&&) = delete;
|
||||||
~scoped_tester_log() override { current_log = previous_log_test; }
|
~scoped_tester_log() override { test_log_singleton::get_instance()->register_log(previous_log_test); }
|
||||||
|
|
||||||
void error(const char* message, ...) override __attribute__((format(printf, 2, 3)))
|
void error(const char* message, ...) override __attribute__((format(printf, 2, 3)))
|
||||||
{
|
{
|
||||||
|
@ -91,13 +110,9 @@ public:
|
||||||
bool exit_on_error = false;
|
bool exit_on_error = false;
|
||||||
uint32_t error_counter = 0, warn_counter = 0;
|
uint32_t error_counter = 0, warn_counter = 0;
|
||||||
|
|
||||||
static srslte::log* get_instance() { return current_log; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
srslte::log* previous_log_test = nullptr;
|
srslte::log* previous_log_test = nullptr;
|
||||||
static srslte::log* current_log;
|
|
||||||
};
|
};
|
||||||
srslte::log* scoped_tester_log::current_log = nullptr;
|
|
||||||
|
|
||||||
// specialization of scoped_tester_log to store last logged message
|
// specialization of scoped_tester_log to store last logged message
|
||||||
class nullsink_log : public scoped_tester_log
|
class nullsink_log : public scoped_tester_log
|
||||||
|
@ -162,20 +177,20 @@ private:
|
||||||
|
|
||||||
#define TESTERROR(fmt, ...) \
|
#define TESTERROR(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (srslte::scoped_tester_log::get_instance() == nullptr) { \
|
if (srslte::test_log_singleton::get_instance() == nullptr) { \
|
||||||
printf(fmt, ##__VA_ARGS__); \
|
printf(fmt, ##__VA_ARGS__); \
|
||||||
} else { \
|
} else { \
|
||||||
srslte::scoped_tester_log::get_instance()->error(fmt, ##__VA_ARGS__); \
|
srslte::test_log_singleton::get_log()->error(fmt, ##__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
return SRSLTE_ERROR; \
|
return SRSLTE_ERROR; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define TESTWARN(fmt, ...) \
|
#define TESTWARN(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (srslte::scoped_tester_log::get_instance() == nullptr) { \
|
if (srslte::test_log_singleton::get_instance() == nullptr) { \
|
||||||
printf(fmt, ##__VA_ARGS__); \
|
printf(fmt, ##__VA_ARGS__); \
|
||||||
} else { \
|
} else { \
|
||||||
srslte::scoped_tester_log::get_instance()->warning(fmt, ##__VA_ARGS__); \
|
srslte::test_log_singleton::get_log()->warning(fmt, ##__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ int test_nullsink_log()
|
||||||
// without contaminating the console/log file
|
// without contaminating the console/log file
|
||||||
srslte::nullsink_log null_logger{"TEST"};
|
srslte::nullsink_log null_logger{"TEST"};
|
||||||
|
|
||||||
TESTASSERT(srslte::scoped_tester_log::get_instance() == &null_logger);
|
TESTASSERT(srslte::test_log_singleton::get_log() == &null_logger);
|
||||||
|
|
||||||
TESTASSERT(null_logger.error_counter == 0);
|
TESTASSERT(null_logger.error_counter == 0);
|
||||||
TESTASSERT(null_logger.last_log_level == srslte::LOG_LEVEL_NONE);
|
TESTASSERT(null_logger.last_log_level == srslte::LOG_LEVEL_NONE);
|
||||||
|
@ -48,7 +48,7 @@ int test_log_scoping()
|
||||||
// This behavior is useful for the cases we have one generic logger for all tests, but in a specific test
|
// This behavior is useful for the cases we have one generic logger for all tests, but in a specific test
|
||||||
// we want to use a different one
|
// we want to use a different one
|
||||||
srslte::nullsink_log logger1("TEST1");
|
srslte::nullsink_log logger1("TEST1");
|
||||||
TESTASSERT(srslte::scoped_tester_log::get_instance() == &logger1);
|
TESTASSERT(srslte::test_log_singleton::get_log() == &logger1);
|
||||||
|
|
||||||
logger1.error("message1");
|
logger1.error("message1");
|
||||||
logger1.error("message2");
|
logger1.error("message2");
|
||||||
|
@ -57,7 +57,7 @@ int test_log_scoping()
|
||||||
{
|
{
|
||||||
// the global test log should be overwriten here, and used by TESTASSERT macro
|
// the global test log should be overwriten here, and used by TESTASSERT macro
|
||||||
srslte::nullsink_log logger2("TEST2");
|
srslte::nullsink_log logger2("TEST2");
|
||||||
TESTASSERT(srslte::scoped_tester_log::get_instance() == &logger2);
|
TESTASSERT(srslte::test_log_singleton::get_log() == &logger2);
|
||||||
TESTASSERT(logger2.error_counter == 0);
|
TESTASSERT(logger2.error_counter == 0);
|
||||||
logger2.error("error message in logger2\n");
|
logger2.error("error message in logger2\n");
|
||||||
TESTASSERT(logger2.last_log_msg == "error message in logger2\n");
|
TESTASSERT(logger2.last_log_msg == "error message in logger2\n");
|
||||||
|
@ -65,7 +65,7 @@ int test_log_scoping()
|
||||||
}
|
}
|
||||||
// the last logger should be recovered
|
// the last logger should be recovered
|
||||||
|
|
||||||
TESTASSERT(srslte::scoped_tester_log::get_instance() == &logger1);
|
TESTASSERT(srslte::test_log_singleton::get_log() == &logger1);
|
||||||
TESTASSERT(logger1.error_counter == 2);
|
TESTASSERT(logger1.error_counter == 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ public:
|
||||||
|
|
||||||
void init(rrc_interface_mac* rrc, srslte::log* log);
|
void init(rrc_interface_mac* rrc, srslte::log* log);
|
||||||
void set_metric(metric_dl* dl_metric, metric_ul* ul_metric);
|
void set_metric(metric_dl* dl_metric, metric_ul* ul_metric);
|
||||||
int cell_cfg(cell_cfg_t* cell_cfg) final;
|
int cell_cfg(cell_cfg_t* cell_cfg) override;
|
||||||
void set_sched_cfg(sched_args_t* sched_cfg);
|
void set_sched_cfg(sched_args_t* sched_cfg);
|
||||||
int reset() final;
|
int reset() final;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ target_link_libraries(scheduler_test srsenb_mac
|
||||||
${Boost_LIBRARIES})
|
${Boost_LIBRARIES})
|
||||||
|
|
||||||
# Scheduler test random
|
# Scheduler test random
|
||||||
add_executable(scheduler_test_rand scheduler_test_rand.cc)
|
add_executable(scheduler_test_rand scheduler_test_rand.cc scheduler_test_common.cc)
|
||||||
target_link_libraries(scheduler_test_rand srsenb_mac
|
target_link_libraries(scheduler_test_rand srsenb_mac
|
||||||
srsenb_phy
|
srsenb_phy
|
||||||
srslte_common
|
srslte_common
|
||||||
|
@ -37,3 +37,4 @@ target_link_libraries(scheduler_test_rand srsenb_mac
|
||||||
rrc_asn1
|
rrc_asn1
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${Boost_LIBRARIES})
|
${Boost_LIBRARIES})
|
||||||
|
add_test(scheduler_test_rand scheduler_test_rand)
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "scheduler_test_common.h"
|
||||||
|
#include "srsenb/hdr/stack/mac/scheduler.h"
|
||||||
|
|
||||||
|
#include "srslte/common/test_common.h"
|
||||||
|
|
||||||
|
using namespace srsenb;
|
||||||
|
|
||||||
|
int output_sched_tester::test_ul_rb_collisions(const tti_params_t& tti_params,
|
||||||
|
const sched_interface::ul_sched_res_t& ul_result,
|
||||||
|
prbmask_t& ul_allocs) const
|
||||||
|
{
|
||||||
|
uint32_t nof_prb = params.cfg->cell.nof_prb;
|
||||||
|
ul_allocs.resize(nof_prb);
|
||||||
|
ul_allocs.reset();
|
||||||
|
|
||||||
|
auto try_ul_fill = [&](srsenb::ul_harq_proc::ul_alloc_t alloc, const char* ch_str, bool strict = true) {
|
||||||
|
CONDERROR((alloc.RB_start + alloc.L) > nof_prb,
|
||||||
|
"[TESTER] Allocated RBs (%d,%d) out-of-bounds\n",
|
||||||
|
alloc.RB_start,
|
||||||
|
alloc.RB_start + alloc.L);
|
||||||
|
CONDERROR(alloc.L == 0, "[TESTER] Allocations must have at least one PRB\n");
|
||||||
|
if (strict and ul_allocs.any(alloc.RB_start, alloc.RB_start + alloc.L)) {
|
||||||
|
TESTERROR("[TESTER] Collision Detected of %s alloc=(%d,%d) and cumulative_mask=0x%s\n",
|
||||||
|
ch_str,
|
||||||
|
alloc.RB_start,
|
||||||
|
alloc.RB_start + alloc.L,
|
||||||
|
ul_allocs.to_hex().c_str());
|
||||||
|
}
|
||||||
|
ul_allocs.fill(alloc.RB_start, alloc.RB_start + alloc.L, true);
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TEST: Check if there is space for PRACH */
|
||||||
|
bool is_prach_tti_tx_ul = srslte_prach_tti_opportunity_config_fdd(params.cfg->prach_config, tti_params.tti_tx_ul, -1);
|
||||||
|
if (is_prach_tti_tx_ul) {
|
||||||
|
try_ul_fill({params.cfg->prach_freq_offset, 6}, "PRACH");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TEST: check collisions in PUCCH */
|
||||||
|
bool strict = nof_prb != 6 or (not is_prach_tti_tx_ul); // and not tti_data.ul_pending_msg3_present);
|
||||||
|
try_ul_fill({0, (uint32_t)params.cfg->nrb_pucch}, "PUCCH", strict);
|
||||||
|
try_ul_fill({params.cfg->cell.nof_prb - params.cfg->nrb_pucch, (uint32_t)params.cfg->nrb_pucch}, "PUCCH", strict);
|
||||||
|
|
||||||
|
/* TEST: check collisions in the UL PUSCH */
|
||||||
|
for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) {
|
||||||
|
uint32_t L, RBstart;
|
||||||
|
srslte_ra_type2_from_riv(ul_result.pusch[i].dci.type2_alloc.riv, &L, &RBstart, nof_prb, nof_prb);
|
||||||
|
strict = ul_result.pusch[i].needs_pdcch or nof_prb != 6; // Msg3 may collide with PUCCH at PRB==6
|
||||||
|
try_ul_fill({RBstart, L}, "PUSCH", strict);
|
||||||
|
// ue_stats[ul_result.pusch[i].dci.rnti].nof_ul_rbs += L;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int output_sched_tester::test_dl_rb_collisions(const tti_params_t& tti_params,
|
||||||
|
const sched_interface::dl_sched_res_t& dl_result,
|
||||||
|
rbgmask_t& rbgmask) const
|
||||||
|
{
|
||||||
|
srslte::bounded_bitset<100, true> dl_allocs(params.cfg->cell.nof_prb), alloc_mask(params.cfg->cell.nof_prb);
|
||||||
|
|
||||||
|
auto try_dl_mask_fill = [&](const srslte_dci_dl_t& dci, const char* channel) {
|
||||||
|
if (extract_dl_prbmask(params.cfg->cell, dci, &alloc_mask) != SRSLTE_SUCCESS) {
|
||||||
|
return SRSLTE_ERROR;
|
||||||
|
}
|
||||||
|
if ((dl_allocs & alloc_mask).any()) {
|
||||||
|
TESTERROR("[TESTER] Detected collision in the DL %s allocation (%s intersects %s)\n",
|
||||||
|
channel,
|
||||||
|
dl_allocs.to_string().c_str(),
|
||||||
|
alloc_mask.to_string().c_str());
|
||||||
|
}
|
||||||
|
dl_allocs |= alloc_mask;
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Decode BC allocations, check collisions, and fill cumulative mask
|
||||||
|
for (uint32_t i = 0; i < dl_result.nof_bc_elems; ++i) {
|
||||||
|
TESTASSERT(try_dl_mask_fill(dl_result.bc[i].dci, "BC") == SRSLTE_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode RAR allocations, check collisions, and fill cumulative mask
|
||||||
|
for (uint32_t i = 0; i < dl_result.nof_rar_elems; ++i) {
|
||||||
|
TESTASSERT(try_dl_mask_fill(dl_result.rar[i].dci, "RAR") == SRSLTE_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// forbid Data in DL if it conflicts with PRACH for PRB==6
|
||||||
|
if (params.cfg->cell.nof_prb == 6) {
|
||||||
|
uint32_t tti_rx_ack = TTI_RX_ACK(tti_params.tti_rx);
|
||||||
|
if (srslte_prach_tti_opportunity_config_fdd(params.cfg->prach_config, tti_rx_ack, -1)) {
|
||||||
|
dl_allocs.fill(0, dl_allocs.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode Data allocations, check collisions and fill cumulative mask
|
||||||
|
for (uint32_t i = 0; i < dl_result.nof_data_elems; ++i) {
|
||||||
|
TESTASSERT(try_dl_mask_fill(dl_result.data[i].dci, "data") == SRSLTE_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEST: check for holes in the PRB mask (RBGs not fully filled)
|
||||||
|
rbgmask.resize(params.nof_rbgs);
|
||||||
|
rbgmask.reset();
|
||||||
|
srslte::bounded_bitset<100, true> rev_alloc = ~dl_allocs;
|
||||||
|
for (uint32_t i = 0; i < params.nof_rbgs; ++i) {
|
||||||
|
uint32_t lim = SRSLTE_MIN((i + 1) * params.P, dl_allocs.size());
|
||||||
|
bool val = dl_allocs.any(i * params.P, lim);
|
||||||
|
CONDERROR(rev_alloc.any(i * params.P, lim) and val, "[TESTER] No holes can be left in an RBG\n");
|
||||||
|
if (val) {
|
||||||
|
rbgmask.set(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int output_sched_tester::test_sib_scheduling(const tti_params_t& tti_params,
|
||||||
|
const sched_interface::dl_sched_res_t& dl_result) const
|
||||||
|
{
|
||||||
|
uint32_t sfn = tti_params.sfn;
|
||||||
|
uint32_t sf_idx = tti_params.sf_idx;
|
||||||
|
bool sib1_present = ((sfn % 2) == 0) and sf_idx == 5;
|
||||||
|
|
||||||
|
using bc_elem = const sched_interface::dl_sched_bc_t;
|
||||||
|
bc_elem* bc_begin = &dl_result.bc[0];
|
||||||
|
bc_elem* bc_end = &dl_result.bc[dl_result.nof_bc_elems];
|
||||||
|
|
||||||
|
/* Test if SIB1 was correctly scheduled */
|
||||||
|
if (sib1_present) {
|
||||||
|
auto it = std::find_if(bc_begin, bc_end, [](bc_elem& elem) { return elem.index == 0; });
|
||||||
|
CONDERROR(it == bc_end, "Failed to allocate SIB1 in even sfn, sf_idx==5\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test if any SIB was scheduled outside of its window */
|
||||||
|
for (bc_elem* bc = bc_begin; bc != bc_end; ++bc) {
|
||||||
|
if (bc->index == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint32_t x = (bc->index - 1) * params.cfg->si_window_ms;
|
||||||
|
uint32_t sf = x % 10;
|
||||||
|
uint32_t sfn_start = sfn;
|
||||||
|
while ((sfn_start % params.cfg->sibs[bc->index].period_rf) != x / 10) {
|
||||||
|
sfn_start--;
|
||||||
|
}
|
||||||
|
uint32_t win_start = sfn_start * 10 + sf;
|
||||||
|
uint32_t win_end = win_start + params.cfg->si_window_ms;
|
||||||
|
CONDERROR(tti_params.tti_tx_dl < win_start or tti_params.tti_tx_dl > win_end,
|
||||||
|
"Scheduled SIB is outside of its SIB window\n");
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
srslte_pdsch_grant_t grant;
|
||||||
|
srslte_dl_sf_cfg_t dl_sf = {};
|
||||||
|
srslte_dci_dl_t* dci_dyn = const_cast<srslte_dci_dl_t*>(&dci); // TODO
|
||||||
|
srslte_cell_t* cell_dyn = const_cast<srslte_cell_t*>(&cell);
|
||||||
|
|
||||||
|
alloc_mask->resize(cell.nof_prb);
|
||||||
|
alloc_mask->reset();
|
||||||
|
|
||||||
|
CONDERROR(srslte_ra_dl_dci_to_grant(cell_dyn, &dl_sf, SRSLTE_TM1, false, dci_dyn, &grant) == SRSLTE_ERROR,
|
||||||
|
"Failed to decode PDSCH grant\n");
|
||||||
|
for (uint32_t j = 0; j < alloc_mask->size(); ++j) {
|
||||||
|
if (grant.prb_idx[0][j]) {
|
||||||
|
alloc_mask->set(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013-2019 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_SCHEDULER_TEST_COMMON_H
|
||||||
|
#define SRSLTE_SCHEDULER_TEST_COMMON_H
|
||||||
|
|
||||||
|
#include "srsenb/hdr/stack/mac/scheduler.h"
|
||||||
|
|
||||||
|
namespace srsenb {
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
int extract_dl_prbmask(const srslte_cell_t& cell,
|
||||||
|
const srslte_dci_dl_t& dci,
|
||||||
|
srslte::bounded_bitset<100, true>* alloc_mask);
|
||||||
|
|
||||||
|
class output_sched_tester
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit output_sched_tester(const sched_params_t& params_) : params(params_) {}
|
||||||
|
|
||||||
|
/* Check for collisions between RB allocations in the PUSCH and PUCCH */
|
||||||
|
int test_ul_rb_collisions(const tti_params_t& tti_params,
|
||||||
|
const sched_interface::ul_sched_res_t& ul_result,
|
||||||
|
prbmask_t& ul_allocs) const;
|
||||||
|
|
||||||
|
/* Check for collision between RB allocations in the PDSCH */
|
||||||
|
int test_dl_rb_collisions(const tti_params_t& tti_params,
|
||||||
|
const sched_interface::dl_sched_res_t& dl_result,
|
||||||
|
rbgmask_t& dl_mask) const;
|
||||||
|
|
||||||
|
/* Check if SIBs are scheduled within their window */
|
||||||
|
int test_sib_scheduling(const tti_params_t& tti_params, const sched_interface::dl_sched_res_t& dl_result) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const sched_params_t& params;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srsenb
|
||||||
|
|
||||||
|
#endif // SRSLTE_SCHEDULER_TEST_COMMON_H
|
|
@ -37,6 +37,7 @@
|
||||||
#include "srslte/phy/utils/debug.h"
|
#include "srslte/phy/utils/debug.h"
|
||||||
#include "srslte/radio/radio.h"
|
#include "srslte/radio/radio.h"
|
||||||
|
|
||||||
|
#include "scheduler_test_common.h"
|
||||||
#include "srslte/common/test_common.h"
|
#include "srslte/common/test_common.h"
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
|
@ -69,10 +70,11 @@
|
||||||
/***************************
|
/***************************
|
||||||
* Setup Random generators
|
* Setup Random generators
|
||||||
**************************/
|
**************************/
|
||||||
// uint32_t const seed = std::random_device()();
|
uint32_t const seed = time(nullptr);
|
||||||
uint32_t const seed = 2452071795; // time(nullptr);
|
// uint32_t const seed = 2452071795;
|
||||||
std::default_random_engine rand_gen(seed);
|
std::default_random_engine rand_gen(seed);
|
||||||
std::uniform_real_distribution<float> unif_dist(0, 1.0);
|
std::uniform_real_distribution<float> unif_dist(0, 1.0);
|
||||||
|
bool check_old_pids = false;
|
||||||
|
|
||||||
float randf()
|
float randf()
|
||||||
{
|
{
|
||||||
|
@ -119,7 +121,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
log_tester log_global;
|
log_tester log_global;
|
||||||
bool check_old_pids = true;
|
|
||||||
|
|
||||||
/*******************
|
/*******************
|
||||||
* Dummies *
|
* Dummies *
|
||||||
|
@ -165,8 +166,6 @@ struct sched_tester : public srsenb::sched {
|
||||||
srsenb::ul_harq_proc ul_harq;
|
srsenb::ul_harq_proc ul_harq;
|
||||||
};
|
};
|
||||||
struct sched_tti_data {
|
struct sched_tti_data {
|
||||||
bool is_prach_tti_tx_ul = false;
|
|
||||||
uint32_t ul_sf_idx;
|
|
||||||
uint32_t tti_rx;
|
uint32_t tti_rx;
|
||||||
uint32_t tti_tx_dl;
|
uint32_t tti_tx_dl;
|
||||||
uint32_t tti_tx_ul;
|
uint32_t tti_tx_ul;
|
||||||
|
@ -204,7 +203,6 @@ struct sched_tester : public srsenb::sched {
|
||||||
srsenb::ul_harq_proc ul_harq;
|
srsenb::ul_harq_proc ul_harq;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t nof_rbgs = 0;
|
|
||||||
sched_sim_args sim_args;
|
sched_sim_args sim_args;
|
||||||
|
|
||||||
// tester control data
|
// tester control data
|
||||||
|
@ -214,8 +212,10 @@ struct sched_tester : public srsenb::sched {
|
||||||
typedef std::multimap<uint32_t, ack_info_t>::iterator ack_it_t;
|
typedef std::multimap<uint32_t, ack_info_t>::iterator ack_it_t;
|
||||||
|
|
||||||
// sched results
|
// sched results
|
||||||
sched_tti_data tti_data;
|
sched_tti_data tti_data;
|
||||||
|
srsenb::tti_params_t tti_params{10241};
|
||||||
|
|
||||||
|
int cell_cfg(sched_interface::cell_cfg_t* cell_cfg) final;
|
||||||
int add_user(uint16_t rnti,
|
int add_user(uint16_t rnti,
|
||||||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg,
|
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg,
|
||||||
srsenb::sched_interface::ue_cfg_t ue_cfg_);
|
srsenb::sched_interface::ue_cfg_t ue_cfg_);
|
||||||
|
@ -234,8 +234,17 @@ private:
|
||||||
void before_sched();
|
void before_sched();
|
||||||
int process_results();
|
int process_results();
|
||||||
int ack_txs();
|
int ack_txs();
|
||||||
|
|
||||||
|
std::unique_ptr<srsenb::output_sched_tester> output_tester;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int sched_tester::cell_cfg(sched_interface::cell_cfg_t* cell_cfg)
|
||||||
|
{
|
||||||
|
sched::cell_cfg(cell_cfg);
|
||||||
|
output_tester.reset(new srsenb::output_sched_tester{sched_params});
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int sched_tester::add_user(uint16_t rnti,
|
int sched_tester::add_user(uint16_t rnti,
|
||||||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg,
|
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg,
|
||||||
srsenb::sched_interface::ue_cfg_t ue_cfg_)
|
srsenb::sched_interface::ue_cfg_t ue_cfg_)
|
||||||
|
@ -273,15 +282,10 @@ void sched_tester::rem_user(uint16_t rnti)
|
||||||
void sched_tester::new_test_tti(uint32_t tti_)
|
void sched_tester::new_test_tti(uint32_t tti_)
|
||||||
{
|
{
|
||||||
// NOTE: make a local copy, since some of these variables may be cleared during scheduling
|
// NOTE: make a local copy, since some of these variables may be cleared during scheduling
|
||||||
tti_data.tti_rx = tti_;
|
tti_params = srsenb::tti_params_t{tti_};
|
||||||
tti_data.tti_tx_dl = TTI_TX(tti_);
|
tti_data.tti_rx = tti_;
|
||||||
tti_data.tti_tx_ul = TTI_RX_ACK(tti_);
|
tti_data.tti_tx_dl = TTI_TX(tti_);
|
||||||
tti_data.is_prach_tti_tx_ul = srslte_prach_tti_opportunity_config_fdd(cfg.prach_config, tti_data.tti_tx_ul, -1);
|
tti_data.tti_tx_ul = TTI_RX_ACK(tti_);
|
||||||
if (tti_data.tti_tx_ul > FDD_HARQ_DELAY_MS) {
|
|
||||||
tti_data.ul_sf_idx = (tti_data.tti_tx_ul - FDD_HARQ_DELAY_MS) % 10;
|
|
||||||
} else {
|
|
||||||
tti_data.ul_sf_idx = (tti_data.tti_tx_ul + 10240 - FDD_HARQ_DELAY_MS) % 10;
|
|
||||||
}
|
|
||||||
auto& pending_msg3s = carrier_schedulers[0]->get_sf_sched_ptr(tti_data.tti_rx)->get_pending_msg3();
|
auto& pending_msg3s = carrier_schedulers[0]->get_sf_sched_ptr(tti_data.tti_rx)->get_pending_msg3();
|
||||||
tti_data.ul_pending_msg3_present = false;
|
tti_data.ul_pending_msg3_present = false;
|
||||||
if (not pending_msg3s.empty()) {
|
if (not pending_msg3s.empty()) {
|
||||||
|
@ -779,82 +783,22 @@ int sched_tester::test_harqs()
|
||||||
|
|
||||||
int sched_tester::test_sibs()
|
int sched_tester::test_sibs()
|
||||||
{
|
{
|
||||||
uint32_t sfn = tti_data.tti_tx_dl / 10;
|
return output_tester->test_sib_scheduling(tti_params, tti_data.sched_result_dl);
|
||||||
uint32_t sf_idx = TTI_TX(tti_data.tti_rx) % 10;
|
|
||||||
bool sib1_present = ((sfn % 2) == 0) and sf_idx == 5;
|
|
||||||
|
|
||||||
using bc_elem = sched_interface::dl_sched_bc_t;
|
|
||||||
bc_elem* bc_begin = &tti_data.sched_result_dl.bc[0];
|
|
||||||
bc_elem* bc_end = &tti_data.sched_result_dl.bc[tti_data.sched_result_dl.nof_bc_elems];
|
|
||||||
|
|
||||||
/* Test if SIB1 was correctly scheduled */
|
|
||||||
if (sib1_present) {
|
|
||||||
auto it = std::find_if(bc_begin, bc_end, [](bc_elem& elem) { return elem.index == 0; });
|
|
||||||
CONDERROR(it == bc_end, "Failed to allocate SIB1 in even sfn, sf_idx==5\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Test if any SIB was scheduled outside of its window */
|
|
||||||
for (bc_elem* bc = bc_begin; bc != bc_end; ++bc) {
|
|
||||||
if (bc->index == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
uint32_t x = (bc->index - 1) * cfg.si_window_ms;
|
|
||||||
uint32_t sf = x % 10;
|
|
||||||
uint32_t sfn_start = sfn;
|
|
||||||
while ((sfn_start % cfg.sibs[bc->index].period_rf) != x / 10) {
|
|
||||||
sfn_start--;
|
|
||||||
}
|
|
||||||
uint32_t win_start = sfn_start * 10 + sf;
|
|
||||||
uint32_t win_end = win_start + cfg.si_window_ms;
|
|
||||||
CONDERROR(tti_data.tti_tx_dl < win_start or tti_data.tti_tx_dl > win_end,
|
|
||||||
"Scheduled SIB is outside of its SIB window\n");
|
|
||||||
}
|
|
||||||
return SRSLTE_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sched_tester::test_collisions()
|
int sched_tester::test_collisions()
|
||||||
{
|
{
|
||||||
const srsenb::sf_sched* tti_sched = carrier_schedulers[0]->get_sf_sched_ptr(tti_data.tti_rx);
|
const srsenb::sf_sched* tti_sched = carrier_schedulers[0]->get_sf_sched_ptr(tti_data.tti_rx);
|
||||||
|
srsenb::prbmask_t ul_allocs(cfg.cell.nof_prb);
|
||||||
|
|
||||||
srsenb::prbmask_t ul_allocs(cfg.cell.nof_prb);
|
/* TEST: any collision in PUCCH and PUSCH */
|
||||||
|
TESTASSERT(output_tester->test_ul_rb_collisions(tti_params, tti_data.sched_result_ul, ul_allocs) == SRSLTE_SUCCESS);
|
||||||
|
|
||||||
// Helper function to fill RBG mask
|
/* TEST: check whether cumulative UL PRB masks coincide */
|
||||||
auto try_ul_fill = [&](srsenb::ul_harq_proc::ul_alloc_t alloc, const char* ch_str, bool strict = true) {
|
if (ul_allocs != tti_sched->get_ul_mask()) {
|
||||||
CONDERROR((alloc.RB_start + alloc.L) > cfg.cell.nof_prb,
|
TESTERROR("[TESTER] The UL PRB mask and the scheduler result UL mask are not consistent\n");
|
||||||
"[TESTER] Allocated RBs (%d,%d) out of bounds\n",
|
|
||||||
alloc.RB_start,
|
|
||||||
alloc.RB_start + alloc.L);
|
|
||||||
CONDERROR(alloc.L == 0, "[TESTER] Allocations must have at least one PRB\n");
|
|
||||||
if (strict and ul_allocs.any(alloc.RB_start, alloc.RB_start + alloc.L)) {
|
|
||||||
TESTERROR("[TESTER] There is a collision of %s alloc=(%d,%d) and cumulative_mask=%s\n",
|
|
||||||
ch_str,
|
|
||||||
alloc.RB_start,
|
|
||||||
alloc.RB_start + alloc.L,
|
|
||||||
ul_allocs.to_hex().c_str());
|
|
||||||
}
|
|
||||||
ul_allocs.fill(alloc.RB_start, alloc.RB_start + alloc.L, true);
|
|
||||||
return SRSLTE_SUCCESS;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* TEST: Check if there is space for PRACH */
|
|
||||||
if (tti_data.is_prach_tti_tx_ul) {
|
|
||||||
try_ul_fill({cfg.prach_freq_offset, 6}, "PRACH");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TEST: check collisions in the UL PUSCH and PUCCH */
|
|
||||||
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_dci_elems; ++i) {
|
|
||||||
uint32_t L, RBstart;
|
|
||||||
srslte_ra_type2_from_riv(
|
|
||||||
tti_data.sched_result_ul.pusch[i].dci.type2_alloc.riv, &L, &RBstart, cfg.cell.nof_prb, cfg.cell.nof_prb);
|
|
||||||
try_ul_fill({RBstart, L}, "PUSCH");
|
|
||||||
ue_stats[tti_data.sched_result_ul.pusch[i].dci.rnti].nof_ul_rbs += L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TEST: check collisions with PUCCH */
|
|
||||||
bool strict = cfg.cell.nof_prb != 6 or (not tti_data.is_prach_tti_tx_ul and not tti_data.ul_pending_msg3_present);
|
|
||||||
try_ul_fill({0, (uint32_t)cfg.nrb_pucch}, "PUCCH", strict);
|
|
||||||
try_ul_fill({cfg.cell.nof_prb - cfg.nrb_pucch, (uint32_t)cfg.nrb_pucch}, "PUCCH", strict);
|
|
||||||
|
|
||||||
/* TEST: Check if there is a collision with Msg3 or Msg3 alloc data is not consistent */
|
/* TEST: Check if there is a collision with Msg3 or Msg3 alloc data is not consistent */
|
||||||
if (tti_data.ul_pending_msg3_present) {
|
if (tti_data.ul_pending_msg3_present) {
|
||||||
bool passed = false;
|
bool passed = false;
|
||||||
|
@ -874,99 +818,27 @@ int sched_tester::test_collisions()
|
||||||
CONDERROR(not passed, "[TESTER] No Msg3 allocation was found in the sched_result\n");
|
CONDERROR(not passed, "[TESTER] No Msg3 allocation was found in the sched_result\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TEST: check whether cumulative UL PRB masks coincide */
|
// update ue stats with number of allocated UL PRBs
|
||||||
if (ul_allocs != tti_sched->get_ul_mask()) {
|
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_dci_elems; ++i) {
|
||||||
TESTERROR("[TESTER] The UL PRB mask and the scheduler result UL mask are not consistent\n");
|
uint32_t L, RBstart;
|
||||||
|
srslte_ra_type2_from_riv(
|
||||||
|
tti_data.sched_result_ul.pusch[i].dci.type2_alloc.riv, &L, &RBstart, cfg.cell.nof_prb, cfg.cell.nof_prb);
|
||||||
|
ue_stats[tti_data.sched_result_ul.pusch[i].dci.rnti].nof_ul_rbs += L;
|
||||||
}
|
}
|
||||||
|
|
||||||
srslte::bounded_bitset<100, true> dl_allocs(cfg.cell.nof_prb), alloc_mask(cfg.cell.nof_prb);
|
/* TEST: check any collision in PDSCH */
|
||||||
srslte_dl_sf_cfg_t dl_sf;
|
srsenb::rbgmask_t rbgmask(cfg.cell.nof_prb);
|
||||||
ZERO_OBJECT(dl_sf);
|
TESTASSERT(output_tester->test_dl_rb_collisions(tti_params, tti_data.sched_result_dl, rbgmask) == SRSLTE_SUCCESS);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_bc_elems; ++i) {
|
|
||||||
srslte_pdsch_grant_t grant;
|
|
||||||
CONDERROR(srslte_ra_dl_dci_to_grant(
|
|
||||||
&cfg.cell, &dl_sf, SRSLTE_TM1, false, &tti_data.sched_result_dl.bc[i].dci, &grant) == SRSLTE_ERROR,
|
|
||||||
"Failed to decode PDSCH grant\n");
|
|
||||||
alloc_mask.reset();
|
|
||||||
for (uint32_t j = 0; j < alloc_mask.size(); ++j) {
|
|
||||||
if (grant.prb_idx[0][j]) {
|
|
||||||
alloc_mask.set(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((dl_allocs & alloc_mask).any()) {
|
|
||||||
TESTERROR("[TESTER] Detected collision in the DL bc allocation (%s intersects %s)\n",
|
|
||||||
dl_allocs.to_string().c_str(),
|
|
||||||
alloc_mask.to_string().c_str());
|
|
||||||
}
|
|
||||||
dl_allocs |= alloc_mask;
|
|
||||||
}
|
|
||||||
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_rar_elems; ++i) {
|
|
||||||
alloc_mask.reset();
|
|
||||||
srslte_pdsch_grant_t grant;
|
|
||||||
CONDERROR(srslte_ra_dl_dci_to_grant(
|
|
||||||
&cfg.cell, &dl_sf, SRSLTE_TM1, false, &tti_data.sched_result_dl.rar[i].dci, &grant) == SRSLTE_ERROR,
|
|
||||||
"Failed to decode PDSCH grant\n");
|
|
||||||
for (uint32_t j = 0; j < alloc_mask.size(); ++j) {
|
|
||||||
if (grant.prb_idx[0][j]) {
|
|
||||||
alloc_mask.set(j);
|
|
||||||
} else {
|
|
||||||
alloc_mask.reset(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((dl_allocs & alloc_mask).any()) {
|
|
||||||
TESTERROR("[TESTER] Detected collision in the DL RAR allocation (%s intersects %s)\n",
|
|
||||||
dl_allocs.to_string().c_str(),
|
|
||||||
alloc_mask.to_string().c_str());
|
|
||||||
}
|
|
||||||
dl_allocs |= alloc_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
// forbid Data in DL if it conflicts with PRACH for PRB==6
|
|
||||||
if (cfg.cell.nof_prb == 6) {
|
|
||||||
uint32_t tti_rx_ack = TTI_RX_ACK(tti_data.tti_rx);
|
|
||||||
if (srslte_prach_tti_opportunity_config_fdd(cfg.prach_config, tti_rx_ack, -1)) {
|
|
||||||
dl_allocs.fill(0, dl_allocs.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// update ue stats with number of DL RB allocations
|
||||||
|
srslte::bounded_bitset<100, true> alloc_mask(cfg.cell.nof_prb);
|
||||||
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_data_elems; ++i) {
|
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_data_elems; ++i) {
|
||||||
alloc_mask.reset();
|
TESTASSERT(srsenb::extract_dl_prbmask(cfg.cell, tti_data.sched_result_dl.data[i].dci, &alloc_mask) ==
|
||||||
srslte_pdsch_grant_t grant;
|
SRSLTE_SUCCESS);
|
||||||
CONDERROR(srslte_ra_dl_dci_to_grant(
|
|
||||||
&cfg.cell, &dl_sf, SRSLTE_TM1, false, &tti_data.sched_result_dl.data[i].dci, &grant) == SRSLTE_ERROR,
|
|
||||||
"Failed to decode PDSCH grant\n");
|
|
||||||
for (uint32_t j = 0; j < alloc_mask.size(); ++j) {
|
|
||||||
if (grant.prb_idx[0][j]) {
|
|
||||||
alloc_mask.set(j);
|
|
||||||
} else {
|
|
||||||
alloc_mask.reset(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((dl_allocs & alloc_mask).any()) {
|
|
||||||
TESTERROR("[TESTER] Detected collision in the DL data allocation (%s intersects %s)\n",
|
|
||||||
dl_allocs.to_string().c_str(),
|
|
||||||
alloc_mask.to_string().c_str());
|
|
||||||
}
|
|
||||||
dl_allocs |= alloc_mask;
|
|
||||||
ue_stats[tti_data.sched_result_dl.data[i].dci.rnti].nof_dl_rbs += alloc_mask.count();
|
ue_stats[tti_data.sched_result_dl.data[i].dci.rnti].nof_dl_rbs += alloc_mask.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEST: check if resulting DL mask is equal to scheduler internal DL mask
|
// TEST: check if resulting DL mask is equal to scheduler internal DL mask
|
||||||
uint32_t P = srslte_ra_type0_P(cfg.cell.nof_prb);
|
|
||||||
nof_rbgs = srslte::ceil_div(cfg.cell.nof_prb, P);
|
|
||||||
srsenb::rbgmask_t rbgmask(nof_rbgs);
|
|
||||||
srslte::bounded_bitset<100, true> rev_alloc = ~dl_allocs;
|
|
||||||
for (uint32_t i = 0; i < nof_rbgs; ++i) {
|
|
||||||
uint32_t lim = SRSLTE_MIN((i + 1) * P, dl_allocs.size());
|
|
||||||
bool val = dl_allocs.any(i * P, lim);
|
|
||||||
CONDERROR(rev_alloc.any(i * P, lim) and val, "[TESTER] No holes can be left in an RBG\n");
|
|
||||||
if (val) {
|
|
||||||
rbgmask.set(i);
|
|
||||||
} else {
|
|
||||||
rbgmask.reset(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rbgmask != carrier_schedulers[0]->get_sf_sched_ptr(tti_data.tti_rx)->get_dl_mask()) {
|
if (rbgmask != carrier_schedulers[0]->get_sf_sched_ptr(tti_data.tti_rx)->get_dl_mask()) {
|
||||||
TESTERROR("[TESTER] The UL PRB mask and the scheduler result UL mask are not consistent (%s!=%s)\n",
|
TESTERROR("[TESTER] The UL PRB mask and the scheduler result UL mask are not consistent (%s!=%s)\n",
|
||||||
rbgmask.to_string().c_str(),
|
rbgmask.to_string().c_str(),
|
||||||
|
@ -1131,7 +1003,7 @@ sched_sim_args rand_sim_params(const srsenb::sched_interface::cell_cfg_t& cell_c
|
||||||
float P_prach = 0.99f; // 0.1f + randf()*0.3f;
|
float P_prach = 0.99f; // 0.1f + randf()*0.3f;
|
||||||
float ul_sr_exps[] = {1, 4}; // log rand
|
float ul_sr_exps[] = {1, 4}; // log rand
|
||||||
float dl_data_exps[] = {1, 4}; // log rand
|
float dl_data_exps[] = {1, 4}; // log rand
|
||||||
uint32_t max_nof_users = 500;
|
uint32_t max_nof_users = 5;
|
||||||
std::uniform_int_distribution<> connection_dur_dist(min_conn_dur, max_conn_dur);
|
std::uniform_int_distribution<> connection_dur_dist(min_conn_dur, max_conn_dur);
|
||||||
|
|
||||||
bzero(&sim_args.ue_cfg, sizeof(srsenb::sched_interface::ue_cfg_t));
|
bzero(&sim_args.ue_cfg, sizeof(srsenb::sched_interface::ue_cfg_t));
|
||||||
|
@ -1200,8 +1072,5 @@ int main()
|
||||||
test_scheduler_rand(cell_cfg, sim_args);
|
test_scheduler_rand(cell_cfg, sim_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// // low UL-Txs
|
return 0;
|
||||||
// printf("\n\n********* New Test ***********\n");
|
|
||||||
// sim_args.P_sr = 0.05;
|
|
||||||
// test_scheduler_rand(sim_args);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue