the CA and random sched testers now use same structs and common interface.
This commit is contained in:
parent
385fa226e0
commit
b44754f0ae
|
@ -18,16 +18,6 @@
|
|||
# and at http://www.gnu.org/licenses/.
|
||||
#
|
||||
|
||||
# Scheduler test
|
||||
add_executable(scheduler_test scheduler_test.cc)
|
||||
target_link_libraries(scheduler_test srsenb_mac
|
||||
srsenb_phy
|
||||
srslte_common
|
||||
srslte_phy
|
||||
rrc_asn1
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${Boost_LIBRARIES})
|
||||
|
||||
# Scheduler test random
|
||||
add_executable(scheduler_test_rand scheduler_test_rand.cc scheduler_test_common.cc)
|
||||
target_link_libraries(scheduler_test_rand srsenb_mac
|
||||
|
|
|
@ -55,104 +55,8 @@ class sched_ca_tester : public common_sched_tester
|
|||
{
|
||||
public:
|
||||
int process_tti_events(const tti_ev& tti_events);
|
||||
int run_tti(const tti_ev& tti_events) override;
|
||||
};
|
||||
|
||||
int sched_ca_tester::process_tti_events(const tti_ev& tti_ev)
|
||||
{
|
||||
for (const tti_ev::user_cfg_ev& ue_ev : tti_ev.user_updates) {
|
||||
// There is a new configuration
|
||||
if (ue_ev.ue_cfg != nullptr) {
|
||||
if (not ue_tester->user_exists(ue_ev.rnti)) {
|
||||
// new user
|
||||
TESTASSERT(add_user(ue_ev.rnti, *ue_ev.ue_cfg) == SRSLTE_SUCCESS);
|
||||
} else {
|
||||
// reconfiguration
|
||||
TESTASSERT(ue_cfg(ue_ev.rnti, *ue_ev.ue_cfg) == SRSLTE_SUCCESS);
|
||||
ue_tester->user_reconf(ue_ev.rnti, *ue_ev.ue_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
// There is a user to remove
|
||||
if (ue_ev.rem_user) {
|
||||
// bearer_ue_rem(ue_ev.rnti, 0);
|
||||
ue_rem(ue_ev.rnti);
|
||||
ue_tester->rem_user(ue_ev.rnti);
|
||||
log_global->info("[TESTER] Removing user rnti=0x%x\n", ue_ev.rnti);
|
||||
}
|
||||
|
||||
// configure carriers
|
||||
if (ue_ev.bearer_cfg != nullptr) {
|
||||
CONDERROR(not ue_tester->user_exists(ue_ev.rnti), "User rnti=0x%x does not exist\n", ue_ev.rnti);
|
||||
// TODO: Instantiate more bearers
|
||||
bearer_ue_cfg(ue_ev.rnti, 0, ue_ev.bearer_cfg.get());
|
||||
}
|
||||
|
||||
// push UL SRs and DL packets
|
||||
if (ue_ev.buffer_ev != nullptr) {
|
||||
auto* user = ue_tester->get_user_state(ue_ev.rnti);
|
||||
CONDERROR(user == nullptr, "TESTER ERROR: Trying to schedule data for user that does not exist\n");
|
||||
|
||||
if (ue_ev.buffer_ev->dl_data > 0) {
|
||||
// If Msg3 has already been received
|
||||
if (user->msg3_tic.is_valid() and user->msg3_tic <= tic) {
|
||||
// If Msg4 not yet sent, allocate data in SRB0 buffer
|
||||
uint32_t lcid = (user->msg4_tic.is_valid()) ? 2 : 0;
|
||||
uint32_t pending_dl_new_data = ue_db[ue_ev.rnti].get_pending_dl_new_data();
|
||||
if (lcid == 2 and not user->drb_cfg_flag) {
|
||||
// If RRCSetup finished
|
||||
if (pending_dl_new_data == 0) {
|
||||
// setup lcid==2 bearer
|
||||
sched::ue_bearer_cfg_t cfg = {};
|
||||
cfg.direction = ue_bearer_cfg_t::BOTH;
|
||||
ue_tester->bearer_cfg(ue_ev.rnti, 2, cfg);
|
||||
bearer_ue_cfg(ue_ev.rnti, 2, &cfg);
|
||||
} else {
|
||||
// Let SRB0 get emptied
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Update DL buffer
|
||||
uint32_t tot_dl_data = pending_dl_new_data + ue_ev.buffer_ev->dl_data; // TODO: derive pending based on rx
|
||||
dl_rlc_buffer_state(ue_ev.rnti, lcid, tot_dl_data, 0); // TODO: Check retx_queue
|
||||
}
|
||||
}
|
||||
|
||||
if (ue_ev.buffer_ev->sr_data > 0 and user->drb_cfg_flag) {
|
||||
uint32_t tot_ul_data =
|
||||
ue_db[ue_ev.rnti].get_pending_ul_new_data(tti_info.tti_params.tti_tx_ul) + ue_ev.buffer_ev->sr_data;
|
||||
uint32_t lcid = 2;
|
||||
ul_bsr(ue_ev.rnti, lcid, tot_ul_data, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int sched_ca_tester::run_tti(const tti_ev& tti_events)
|
||||
{
|
||||
new_test_tti();
|
||||
log_global->info("[TESTER] ---- tti=%u | nof_ues=%zd ----\n", tic.tti_rx(), ue_db.size());
|
||||
|
||||
process_tti_events(tti_events);
|
||||
process_ack_txs();
|
||||
// before_sched();
|
||||
|
||||
// Call scheduler for all carriers
|
||||
tti_info.dl_sched_result.resize(sched_cell_params.size());
|
||||
for (uint32_t i = 0; i < sched_cell_params.size(); ++i) {
|
||||
dl_sched(tti_info.tti_params.tti_tx_dl, i, tti_info.dl_sched_result[i]);
|
||||
}
|
||||
tti_info.ul_sched_result.resize(sched_cell_params.size());
|
||||
for (uint32_t i = 0; i < sched_cell_params.size(); ++i) {
|
||||
ul_sched(tti_info.tti_params.tti_tx_ul, i, tti_info.ul_sched_result[i]);
|
||||
}
|
||||
|
||||
process_results();
|
||||
schedule_acks();
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Scheduler Tests
|
||||
*****************************/
|
||||
|
@ -176,9 +80,6 @@ sim_sched_args generate_default_sim_args(uint32_t nof_prb, uint32_t nof_ccs)
|
|||
cell_cfg[1].scell_list[0].enb_cc_idx = 0;
|
||||
sim_args.cell_cfg = std::move(cell_cfg);
|
||||
|
||||
sim_args.bearer_cfg = {};
|
||||
sim_args.bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
|
||||
|
||||
/* Setup Derived Params */
|
||||
sim_args.ue_cfg.supported_cc_list.resize(nof_ccs);
|
||||
for (uint32_t i = 0; i < sim_args.ue_cfg.supported_cc_list.size(); ++i) {
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* 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 <unistd.h>
|
||||
|
||||
#include "srsenb/hdr/phy/phy.h"
|
||||
#include "srsenb/hdr/stack/mac/mac.h"
|
||||
|
||||
#include "srslte/common/log_filter.h"
|
||||
#include "srslte/interfaces/enb_interfaces.h"
|
||||
#include "srslte/interfaces/sched_interface.h"
|
||||
#include "srslte/phy/utils/debug.h"
|
||||
#include "srslte/radio/radio.h"
|
||||
|
||||
uint8_t sib1_payload[18] =
|
||||
{0x60, 0x40, 0x04, 0x03, 0x00, 0x01, 0x1a, 0x2d, 0x00, 0x18, 0x02, 0x81, 0x80, 0x42, 0x0c, 0x80, 0x00, 0x00};
|
||||
uint8_t sib2_payload[41] = {0x00, 0x80, 0x1c, 0x31, 0x18, 0x6f, 0xe1, 0x20, 0x00, 0x35, 0x84, 0x8c, 0xe2, 0xd0,
|
||||
0x00, 0x02, 0x00, 0x78, 0xee, 0x31, 0x6a, 0xa5, 0x37, 0x30, 0xa0, 0x70, 0xc9, 0x49,
|
||||
0xfa, 0x8d, 0xd2, 0x78, 0x1a, 0x02, 0x77, 0x4a, 0x92, 0x40, 0x00, 0x00, 0x00};
|
||||
|
||||
// Define dummy RLC always transmitts
|
||||
class rlc : public srsenb::rlc_interface_mac
|
||||
{
|
||||
public:
|
||||
uint32_t get_buffer_state(uint16_t rnti, uint32_t lcid) { return 1; }
|
||||
|
||||
int read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
|
||||
{
|
||||
for (uint32_t i = 0; i < nof_bytes; i++) {
|
||||
payload[i] = i;
|
||||
}
|
||||
return nof_bytes;
|
||||
}
|
||||
|
||||
void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) {}
|
||||
|
||||
void read_pdu_bcch_dlsch(uint32_t sib_index, uint8_t payload[srsenb::sched_interface::MAX_SIB_PAYLOAD_LEN])
|
||||
{
|
||||
switch (sib_index) {
|
||||
case 0:
|
||||
memcpy(payload, sib1_payload, 18);
|
||||
break;
|
||||
case 1:
|
||||
memcpy(payload, sib2_payload, 41);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes) {}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
// Create classes
|
||||
srslte::log_filter log_out("ALL");
|
||||
srsenb::sched my_sched;
|
||||
srsenb::dl_metric_rr dl_metric;
|
||||
srsenb::ul_metric_rr ul_metric;
|
||||
rlc my_rlc;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
log_out.set_level(srslte::LOG_LEVEL_INFO);
|
||||
|
||||
/* Set PHY cell configuration */
|
||||
srslte_cell_t cell_cfg_phy;
|
||||
cell_cfg_phy.id = 1;
|
||||
cell_cfg_phy.cp = SRSLTE_CP_NORM;
|
||||
cell_cfg_phy.nof_ports = 1;
|
||||
cell_cfg_phy.nof_prb = 25;
|
||||
cell_cfg_phy.phich_length = SRSLTE_PHICH_NORM;
|
||||
cell_cfg_phy.phich_resources = SRSLTE_PHICH_R_1;
|
||||
|
||||
std::vector<srsenb::sched_interface::cell_cfg_t> cell_cfg(1);
|
||||
|
||||
/* Set MAC cell configuration */
|
||||
cell_cfg[0] = {};
|
||||
cell_cfg[0].cell = cell_cfg_phy;
|
||||
cell_cfg[0].sibs[0].len = 18;
|
||||
cell_cfg[0].sibs[0].period_rf = 8;
|
||||
cell_cfg[0].sibs[1].len = 41;
|
||||
cell_cfg[0].sibs[1].period_rf = 16;
|
||||
cell_cfg[0].si_window_ms = 40;
|
||||
|
||||
my_sched.init(nullptr);
|
||||
my_sched.cell_cfg(cell_cfg);
|
||||
|
||||
srsenb::sched_interface::dl_sched_res_t sched_result_dl;
|
||||
srsenb::sched_interface::ul_sched_res_t sched_result_ul;
|
||||
|
||||
srsenb::sched_interface::ue_cfg_t ue_cfg = {};
|
||||
ue_cfg.supported_cc_list.emplace_back();
|
||||
ue_cfg.supported_cc_list.back().enb_cc_idx = 0;
|
||||
uint16_t rnti = 30;
|
||||
|
||||
ue_cfg.aperiodic_cqi_period = 40;
|
||||
ue_cfg.maxharq_tx = 5;
|
||||
|
||||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg;
|
||||
bzero(&bearer_cfg, sizeof(srsenb::sched_interface::ue_bearer_cfg_t));
|
||||
bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
|
||||
|
||||
my_sched.ue_cfg(rnti, ue_cfg);
|
||||
my_sched.bearer_ue_cfg(rnti, 0, &bearer_cfg);
|
||||
// my_sched.dl_rlc_buffer_state(rnti, 0, 1e6, 0);
|
||||
my_sched.ul_bsr(rnti, 0, 1e6f, true);
|
||||
|
||||
bool running = true;
|
||||
uint32_t tti = 0;
|
||||
while (running) {
|
||||
log_out.step(tti);
|
||||
if (tti > 50) {
|
||||
running = false;
|
||||
}
|
||||
my_sched.dl_sched(tti, 0, sched_result_dl);
|
||||
my_sched.ul_sched(tti, 0, sched_result_ul);
|
||||
tti = (tti + 1) % 10240;
|
||||
if (tti >= 4) {
|
||||
my_sched.ul_crc_info(tti, rnti, 0, tti % 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -329,6 +329,9 @@ int user_state_sched_tester::add_user(uint16_t r
|
|||
uint32_t preamble_idx,
|
||||
const srsenb::sched_interface::ue_cfg_t& ue_cfg)
|
||||
{
|
||||
CONDERROR(!srslte_prach_tti_opportunity_config_fdd(
|
||||
cell_params[ue_cfg.supported_cc_list[0].enb_cc_idx].prach_config, tic.tti_rx(), -1),
|
||||
"[TESTER] New user added in a non-PRACH TTI\n");
|
||||
TESTASSERT(users.count(rnti) == 0);
|
||||
ue_state ue;
|
||||
ue.user_cfg = ue_cfg;
|
||||
|
@ -368,16 +371,14 @@ void user_state_sched_tester::rem_user(uint16_t rnti)
|
|||
|
||||
/**
|
||||
* Tests whether the RAR and Msg3 were scheduled within the expected windows. Individual tests:
|
||||
* - a user does not get UL allocs before Msg3
|
||||
* - a user does not get DL data allocs before Msg3 is correctly received
|
||||
* - a user RAR alloc falls within its RAR window
|
||||
* - There is only one RAR in the RAR window for a given user
|
||||
* - No UL allocs before Msg3
|
||||
* - No DL data allocs before Msg3 is correctly ACKed
|
||||
* - RAR alloc falls within RAR window and is unique per user
|
||||
* - Msg3 is allocated in expected TTI, without PDCCH, and correct rnti
|
||||
* - First Data allocation happens after Msg3, and contains a ConRes
|
||||
* - No RARs are allocated with wrong enb_cc_idx, preamble_idx or wrong user
|
||||
* TODO:
|
||||
* - check Msg3 PRBs match the ones advertised in the RAR
|
||||
* - space is enough for Msg3
|
||||
*/
|
||||
int user_state_sched_tester::test_ra(uint32_t enb_cc_idx,
|
||||
const sched_interface::dl_sched_res_t& dl_result,
|
||||
|
@ -392,9 +393,10 @@ int user_state_sched_tester::test_ra(uint32_t enb_
|
|||
// No UL allocations before Msg3
|
||||
for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) {
|
||||
if (ul_result.pusch[i].dci.rnti == rnti) {
|
||||
CONDERROR(ul_result.pusch[i].needs_pdcch and not userinfo.msg3_tic.is_valid(),
|
||||
"[TESTER] No UL data allocation allowed before Msg3\n");
|
||||
CONDERROR(not userinfo.rar_tic.is_valid(), "[TESTER] No UL allocs allowed before RAR\n");
|
||||
CONDERROR(not userinfo.rar_tic.is_valid(), "No UL allocs allowed before RAR\n");
|
||||
CONDERROR(ul_result.pusch[i].needs_pdcch and not userinfo.msg3_tic.is_valid() and
|
||||
userinfo.msg3_tic.tti_rx() > tic.tti_rx(),
|
||||
"No UL newtxs allocs allowed before Msg3 Rx\n");
|
||||
tti_counter msg3_tic = userinfo.rar_tic + FDD_HARQ_DELAY_MS + MSG3_DELAY_MS;
|
||||
CONDERROR(msg3_tic > tic.tic_tx_ul(), "No UL allocs allowed before Msg3 alloc\n");
|
||||
}
|
||||
|
@ -403,8 +405,8 @@ int user_state_sched_tester::test_ra(uint32_t enb_
|
|||
// No DL data allocations before Msg3 is received
|
||||
for (uint32_t i = 0; i < dl_result.nof_data_elems; ++i) {
|
||||
if (dl_result.data[i].dci.rnti == rnti) {
|
||||
CONDERROR(not userinfo.msg3_tic.is_valid(), "[TESTER] No DL data alloc allowed before Msg3 alloc\n");
|
||||
CONDERROR(tic < userinfo.msg3_tic, "[TESTER] Msg4 cannot be tx without Msg3 being received\n");
|
||||
CONDERROR(not userinfo.msg3_tic.is_valid(), "No DL data alloc allowed before Msg3 alloc\n");
|
||||
CONDERROR(tic + FDD_HARQ_DELAY_MS < userinfo.msg3_tic, "Msg4 cannot be tx without Msg3 being acked\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,7 +422,7 @@ int user_state_sched_tester::test_ra(uint32_t enb_
|
|||
|
||||
tti_counter tic_tx_dl = tic.tic_tx_dl();
|
||||
CONDERROR(not userinfo.rar_tic.is_valid() and tic.tic_tx_dl() > rar_window[1],
|
||||
"[TESTER] RAR not scheduled within the RAR Window\n");
|
||||
"RAR not scheduled within the RAR Window\n");
|
||||
if (tic_tx_dl <= rar_window[1] and tic_tx_dl >= rar_window[0]) {
|
||||
// Inside RAR window
|
||||
for (uint32_t i = 0; i < dl_result.nof_rar_elems; ++i) {
|
||||
|
@ -428,23 +430,24 @@ int user_state_sched_tester::test_ra(uint32_t enb_
|
|||
auto& data = dl_result.rar[i].msg3_grant[j].data;
|
||||
if (data.prach_tti == (uint32_t)userinfo.prach_tic.tti_rx() and data.preamble_idx == userinfo.preamble_idx) {
|
||||
CONDERROR(userinfo.rar_tic.is_valid(), "There was more than one RAR for the same user\n");
|
||||
userinfo.rar_tic = tic_tx_dl;
|
||||
CONDERROR(rnti != data.temp_crnti, "[TESTER] RAR grant C-RNTI does not match the expected.\n");
|
||||
userinfo.msg3_riv = dl_result.rar[i].msg3_grant[j].grant.rba;
|
||||
userinfo.rar_tic = tic_tx_dl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether Msg3 was allocated in expected TTI
|
||||
/* TEST: Check Msg3 */
|
||||
if (userinfo.rar_tic.is_valid()) {
|
||||
tti_counter expected_msg3_tti = userinfo.rar_tic + FDD_HARQ_DELAY_MS + MSG3_DELAY_MS;
|
||||
if (expected_msg3_tti == tic.tic_tx_ul()) {
|
||||
for (uint32_t i = 0; i < ul_result.nof_dci_elems; ++i) {
|
||||
if (ul_result.pusch[i].dci.rnti == rnti) {
|
||||
CONDERROR(userinfo.msg3_tic.is_valid(), "Only one Msg3 allowed per user\n");
|
||||
CONDERROR(ul_result.pusch[i].needs_pdcch, "[TESTER] Msg3 allocations do not require PDCCH\n");
|
||||
// CONDERROR(tti_data.ul_pending_msg3.rnti != rnti, "[TESTER] The UL pending msg3 RNTI did not
|
||||
// match\n"); CONDERROR(not tti_data.ul_pending_msg3_present, "[TESTER] The UL pending msg3
|
||||
// RNTI did not match\n");
|
||||
CONDERROR(ul_result.pusch[i].needs_pdcch, "Msg3 allocations do not require PDCCH\n");
|
||||
CONDERROR(userinfo.msg3_riv != ul_result.pusch[i].dci.type2_alloc.riv,
|
||||
"The Msg3 was not allocated in the expected PRBs.\n");
|
||||
userinfo.msg3_tic = tic.tic_tx_ul();
|
||||
msg3_count++;
|
||||
}
|
||||
|
@ -623,6 +626,9 @@ int common_sched_tester::sim_cfg(sim_sched_args args)
|
|||
int common_sched_tester::add_user(uint16_t rnti, const ue_cfg_t& ue_cfg_)
|
||||
{
|
||||
CONDERROR(ue_cfg(rnti, ue_cfg_) != SRSLTE_SUCCESS, "[TESTER] Configuring new user rnti=0x%x to sched\n", rnti);
|
||||
// CONDERROR(!srslte_prach_tti_opportunity_config_fdd(
|
||||
// sched_cell_params[CARRIER_IDX].cfg.prach_config, tti_info.tti_params.tti_rx, -1),
|
||||
// "[TESTER] New user added in a non-PRACH TTI\n");
|
||||
|
||||
dl_sched_rar_info_t rar_info = {};
|
||||
rar_info.prach_tti = tti_info.tti_params.tti_rx;
|
||||
|
@ -640,6 +646,8 @@ int common_sched_tester::add_user(uint16_t rnti, const ue_cfg_t& ue_cfg_)
|
|||
|
||||
void common_sched_tester::rem_user(uint16_t rnti)
|
||||
{
|
||||
tester_log->info("[TESTER] Removing user rnti=0x%x\n", rnti);
|
||||
sched::ue_rem(rnti);
|
||||
ue_tester->rem_user(rnti);
|
||||
}
|
||||
|
||||
|
@ -655,6 +663,8 @@ void common_sched_tester::new_test_tti()
|
|||
tti_info.nof_prachs = 0;
|
||||
tti_info.dl_sched_result.clear();
|
||||
tti_info.ul_sched_result.clear();
|
||||
tti_info.dl_sched_result.resize(sched_cell_params.size());
|
||||
tti_info.ul_sched_result.resize(sched_cell_params.size());
|
||||
|
||||
tester_log->step(tti_info.tti_params.tti_rx);
|
||||
|
||||
|
@ -818,6 +828,98 @@ int common_sched_tester::process_results()
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int common_sched_tester::process_tti_events(const tti_ev& tti_ev)
|
||||
{
|
||||
for (const tti_ev::user_cfg_ev& ue_ev : tti_ev.user_updates) {
|
||||
// There is a new configuration
|
||||
if (ue_ev.ue_cfg != nullptr) {
|
||||
if (not ue_tester->user_exists(ue_ev.rnti)) {
|
||||
// new user
|
||||
TESTASSERT(add_user(ue_ev.rnti, *ue_ev.ue_cfg) == SRSLTE_SUCCESS);
|
||||
} else {
|
||||
// reconfiguration
|
||||
TESTASSERT(ue_cfg(ue_ev.rnti, *ue_ev.ue_cfg) == SRSLTE_SUCCESS);
|
||||
ue_tester->user_reconf(ue_ev.rnti, *ue_ev.ue_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
// There is a user to remove
|
||||
if (ue_ev.rem_user) {
|
||||
rem_user(ue_ev.rnti);
|
||||
}
|
||||
|
||||
// configure carriers
|
||||
if (ue_ev.bearer_cfg != nullptr) {
|
||||
CONDERROR(not ue_tester->user_exists(ue_ev.rnti), "User rnti=0x%x does not exist\n", ue_ev.rnti);
|
||||
// TODO: Instantiate more bearers
|
||||
bearer_ue_cfg(ue_ev.rnti, 0, ue_ev.bearer_cfg.get());
|
||||
}
|
||||
|
||||
// push UL SRs and DL packets
|
||||
if (ue_ev.buffer_ev != nullptr) {
|
||||
auto* user = ue_tester->get_user_state(ue_ev.rnti);
|
||||
CONDERROR(user == nullptr, "TESTER ERROR: Trying to schedule data for user that does not exist\n");
|
||||
|
||||
if (ue_ev.buffer_ev->dl_data > 0) {
|
||||
// If Msg3 has already been received
|
||||
if (user->msg3_tic.is_valid() and user->msg3_tic <= tic) {
|
||||
// If Msg4 not yet sent, allocate data in SRB0 buffer
|
||||
uint32_t lcid = (user->msg4_tic.is_valid()) ? 2 : 0;
|
||||
uint32_t pending_dl_new_data = ue_db[ue_ev.rnti].get_pending_dl_new_data();
|
||||
if (lcid == 2 and not user->drb_cfg_flag) {
|
||||
// If RRCSetup finished
|
||||
if (pending_dl_new_data == 0) {
|
||||
// setup lcid==2 bearer
|
||||
sched::ue_bearer_cfg_t cfg = {};
|
||||
cfg.direction = ue_bearer_cfg_t::BOTH;
|
||||
ue_tester->bearer_cfg(ue_ev.rnti, 2, cfg);
|
||||
bearer_ue_cfg(ue_ev.rnti, 2, &cfg);
|
||||
} else {
|
||||
// Let SRB0 get emptied
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Update DL buffer
|
||||
uint32_t tot_dl_data = pending_dl_new_data + ue_ev.buffer_ev->dl_data; // TODO: derive pending based on rx
|
||||
dl_rlc_buffer_state(ue_ev.rnti, lcid, tot_dl_data, 0); // TODO: Check retx_queue
|
||||
}
|
||||
}
|
||||
|
||||
if (ue_ev.buffer_ev->sr_data > 0 and user->drb_cfg_flag) {
|
||||
uint32_t tot_ul_data =
|
||||
ue_db[ue_ev.rnti].get_pending_ul_new_data(tti_info.tti_params.tti_tx_ul) + ue_ev.buffer_ev->sr_data;
|
||||
uint32_t lcid = 2;
|
||||
ul_bsr(ue_ev.rnti, lcid, tot_ul_data, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int common_sched_tester::run_tti(const tti_ev& tti_events)
|
||||
{
|
||||
new_test_tti();
|
||||
tester_log->info("[TESTER] ---- tti=%u | nof_ues=%zd ----\n", tic.tti_rx(), ue_db.size());
|
||||
|
||||
process_tti_events(tti_events);
|
||||
process_ack_txs();
|
||||
before_sched();
|
||||
|
||||
// Call scheduler for all carriers
|
||||
tti_info.dl_sched_result.resize(sched_cell_params.size());
|
||||
for (uint32_t i = 0; i < sched_cell_params.size(); ++i) {
|
||||
dl_sched(tti_info.tti_params.tti_tx_dl, i, tti_info.dl_sched_result[i]);
|
||||
}
|
||||
tti_info.ul_sched_result.resize(sched_cell_params.size());
|
||||
for (uint32_t i = 0; i < sched_cell_params.size(); ++i) {
|
||||
ul_sched(tti_info.tti_params.tti_tx_ul, i, tti_info.ul_sched_result[i]);
|
||||
}
|
||||
|
||||
process_results();
|
||||
TESTASSERT(schedule_acks() == SRSLTE_SUCCESS);
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int common_sched_tester::test_next_ttis(const std::vector<tti_ev>& tti_events)
|
||||
{
|
||||
uint32_t next_idx = tic.is_valid() ? tic.total_count() - sim_args0.start_tti + 1 : 0;
|
||||
|
|
|
@ -84,13 +84,11 @@ class user_state_sched_tester
|
|||
{
|
||||
public:
|
||||
struct ue_state {
|
||||
tti_counter prach_tic, rar_tic, msg3_tic, msg4_tic;
|
||||
// int prach_tic = -1, rar_tic = -1, msg3_tic = -1, msg4_tic = -1;
|
||||
tti_counter prach_tic, rar_tic, msg3_tic, msg4_tic;
|
||||
bool drb_cfg_flag = false;
|
||||
srsenb::sched_interface::ue_cfg_t user_cfg;
|
||||
uint32_t dl_data = 0;
|
||||
uint32_t ul_data = 0;
|
||||
uint32_t preamble_idx = 0;
|
||||
uint32_t msg3_riv = 0;
|
||||
};
|
||||
|
||||
explicit user_state_sched_tester(const std::vector<srsenb::sched::cell_cfg_t>& cell_params_) :
|
||||
|
@ -174,15 +172,18 @@ public:
|
|||
std::vector<sched_interface::ul_sched_res_t> ul_sched_result;
|
||||
};
|
||||
|
||||
int sim_cfg(sim_sched_args args);
|
||||
int add_user(uint16_t rnti, const ue_cfg_t& ue_cfg_);
|
||||
void rem_user(uint16_t rnti);
|
||||
int process_ack_txs();
|
||||
int schedule_acks();
|
||||
int process_results();
|
||||
~common_sched_tester() override = default;
|
||||
|
||||
int test_next_ttis(const std::vector<tti_ev>& tti_events);
|
||||
virtual int run_tti(const tti_ev& tti_events) = 0;
|
||||
int sim_cfg(sim_sched_args args);
|
||||
virtual int add_user(uint16_t rnti, const ue_cfg_t& ue_cfg_);
|
||||
virtual void rem_user(uint16_t rnti);
|
||||
int process_ack_txs();
|
||||
int schedule_acks();
|
||||
virtual int process_results();
|
||||
int process_tti_events(const tti_ev& tti_ev);
|
||||
|
||||
int test_next_ttis(const std::vector<tti_ev>& tti_events);
|
||||
int run_tti(const tti_ev& tti_events);
|
||||
|
||||
// args
|
||||
sim_sched_args sim_args0; ///< arguments used to generate TTI events
|
||||
|
@ -214,7 +215,8 @@ protected:
|
|||
srsenb::ul_harq_proc ul_harq;
|
||||
};
|
||||
|
||||
void new_test_tti();
|
||||
virtual void new_test_tti();
|
||||
virtual void before_sched() {}
|
||||
|
||||
// control params
|
||||
std::multimap<uint32_t, ack_info_t> to_ack;
|
||||
|
|
|
@ -45,19 +45,13 @@
|
|||
/********************************************************
|
||||
* Random Tester for Scheduler.
|
||||
* Current Checks:
|
||||
* - Check if users are only added during a PRACH TTI
|
||||
* - Allocation (DCI+RBs) of users that no longer exist
|
||||
* - RAR is scheduled within the RAR window
|
||||
* - Msg3 checks:
|
||||
* - scheduled/received at expected TTI
|
||||
* - with the correct RNTI and without PDCCH alloc
|
||||
* - unexpected msg3 arrival
|
||||
* - Check correct timing of PRACH, RAR, and Msg3
|
||||
* - Check whether Msg4 contains ConRes
|
||||
* - Check allocs of users that no longer exist
|
||||
* - Check collisions in PDCCH, PUSCH, and PDSCH
|
||||
* - Unexpected Msg3, RAR allocs or with wrong values
|
||||
* - Users without data to Tx cannot be allocated in UL
|
||||
* - Retxs always take precedence
|
||||
* - DCI:
|
||||
* - collisions detected
|
||||
* - mismatch between the union of all dcis and
|
||||
* scheduler class aggregate dci value
|
||||
* - Invalid BC SIB index or TBS
|
||||
* - Harqs:
|
||||
* - invalid pids scheduled
|
||||
|
@ -66,7 +60,6 @@
|
|||
* - consistent NCCE loc
|
||||
* - invalid retx number
|
||||
* - DL adaptive retx/new tx <=> PDCCH alloc
|
||||
* ...
|
||||
*******************************************************/
|
||||
|
||||
// uint32_t const seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
|
@ -109,100 +102,44 @@ srslte::scoped_log<sched_test_log> log_global{};
|
|||
|
||||
constexpr uint32_t CARRIER_IDX = 0;
|
||||
|
||||
struct sched_sim_args {
|
||||
struct tti_event_t {
|
||||
struct user_event_t {
|
||||
uint32_t sr_data = 0;
|
||||
uint32_t dl_data = 0;
|
||||
uint32_t dl_nof_retxs = 0;
|
||||
};
|
||||
std::map<uint16_t, user_event_t> users;
|
||||
bool new_user = false;
|
||||
bool rem_user = false;
|
||||
uint32_t new_rnti;
|
||||
uint32_t rem_rnti;
|
||||
};
|
||||
|
||||
std::vector<tti_event_t> tti_events2;
|
||||
sim_sched_args sim_args;
|
||||
// std::vector<tti_ev> sim_events;
|
||||
};
|
||||
|
||||
// Designed for testing purposes
|
||||
struct sched_tester : public srsenb::common_sched_tester {
|
||||
struct tester_user_results {
|
||||
uint32_t dl_pending_data = 0;
|
||||
uint32_t ul_pending_data = 0; ///< data pending for UL
|
||||
bool has_dl_retx = false;
|
||||
bool has_dl_tx = false;
|
||||
bool has_ul_tx = false; ///< has either tx or retx
|
||||
bool has_ul_retx = false;
|
||||
bool has_ul_newtx = false; ///< *no* retx, but has tx
|
||||
bool ul_retx_got_delayed = false;
|
||||
srsenb::sched_interface::ul_sched_data_t* ul_sched = nullptr; // fast lookup
|
||||
srsenb::sched_interface::dl_sched_data_t* dl_sched = nullptr; // fast lookup
|
||||
srsenb::dl_harq_proc dl_harqs[2 * FDD_HARQ_DELAY_MS];
|
||||
srsenb::ul_harq_proc ul_harq;
|
||||
uint32_t dl_pending_data = 0;
|
||||
uint32_t ul_pending_data = 0; ///< data pending for UL
|
||||
bool has_dl_tx = false;
|
||||
bool has_ul_tx = false; ///< has either tx or retx
|
||||
bool has_ul_retx = false;
|
||||
bool has_ul_newtx = false; ///< *no* retx, but has tx
|
||||
bool ul_retx_got_delayed = false;
|
||||
srsenb::dl_harq_proc dl_harqs[2 * FDD_HARQ_DELAY_MS];
|
||||
srsenb::ul_harq_proc ul_harq;
|
||||
};
|
||||
struct sched_tti_data {
|
||||
uint32_t current_cfi;
|
||||
uint32_t nof_prachs = 0;
|
||||
bool ul_pending_msg3_present = false;
|
||||
srsenb::sf_sched::pending_msg3_t ul_pending_msg3;
|
||||
srslte::bounded_bitset<128, true> used_cce;
|
||||
std::map<uint16_t, tester_user_results> ue_data; ///< stores buffer state of each user
|
||||
tester_user_results total_ues; ///< stores combined UL/DL buffer state
|
||||
srsenb::sched_interface::ul_sched_res_t sched_result_ul;
|
||||
srsenb::sched_interface::dl_sched_res_t sched_result_dl;
|
||||
};
|
||||
struct ue_info {
|
||||
bool drb_cfg_flag = false;
|
||||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg;
|
||||
uint32_t preamble_idx = 0;
|
||||
};
|
||||
|
||||
sched_sim_args sim_events;
|
||||
|
||||
// tester control data
|
||||
std::map<uint16_t, ue_info> tester_ues;
|
||||
|
||||
// sched results
|
||||
sched_tti_data tti_data;
|
||||
|
||||
int add_user(uint16_t rnti,
|
||||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg,
|
||||
srsenb::sched_interface::ue_cfg_t ue_cfg_);
|
||||
void rem_user(uint16_t rnti);
|
||||
int test_tti_result();
|
||||
~sched_tester() override = default;
|
||||
|
||||
void rem_user(uint16_t rnti) override;
|
||||
int test_pdcch_collisions();
|
||||
int assert_no_empty_allocs();
|
||||
int test_collisions();
|
||||
int test_sch_collisions();
|
||||
int test_harqs();
|
||||
int run_tti(const tti_ev& tti_events) final;
|
||||
|
||||
private:
|
||||
void new_test_tti();
|
||||
int process_tti_args();
|
||||
void before_sched();
|
||||
int process_results();
|
||||
void new_test_tti() override;
|
||||
void before_sched() override;
|
||||
int process_results() override;
|
||||
};
|
||||
|
||||
int sched_tester::add_user(uint16_t rnti,
|
||||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg,
|
||||
srsenb::sched_interface::ue_cfg_t ue_cfg_)
|
||||
{
|
||||
TESTASSERT(common_sched_tester::add_user(rnti, ue_cfg_) == SRSLTE_SUCCESS);
|
||||
ue_info info;
|
||||
info.bearer_cfg = bearer_cfg;
|
||||
info.preamble_idx = tti_data.nof_prachs++;
|
||||
tester_ues.insert(std::make_pair(rnti, info));
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
void sched_tester::rem_user(uint16_t rnti)
|
||||
{
|
||||
common_sched_tester::rem_user(rnti);
|
||||
tester_ues.erase(rnti);
|
||||
tti_data.ue_data.erase(rnti);
|
||||
}
|
||||
|
||||
|
@ -210,70 +147,8 @@ void sched_tester::new_test_tti()
|
|||
{
|
||||
common_sched_tester::new_test_tti();
|
||||
// NOTE: make a local copy, since some of these variables may be cleared during scheduling
|
||||
auto& pending_msg3s = carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx)->get_pending_msg3();
|
||||
tti_data.ul_pending_msg3_present = false;
|
||||
if (not pending_msg3s.empty()) {
|
||||
tti_data.ul_pending_msg3_present = true;
|
||||
tti_data.ul_pending_msg3 = pending_msg3s.front();
|
||||
}
|
||||
tti_data.current_cfi = sched_cfg.nof_ctrl_symbols;
|
||||
tti_data.used_cce.resize(srslte_regs_pdcch_ncce(sched_cell_params[CARRIER_IDX].regs.get(), tti_data.current_cfi));
|
||||
tti_data.used_cce.reset();
|
||||
tti_data.ue_data.clear();
|
||||
tti_data.total_ues = tester_user_results();
|
||||
tti_data.nof_prachs = 0;
|
||||
}
|
||||
|
||||
int sched_tester::process_tti_args()
|
||||
{
|
||||
// may add a new user
|
||||
if (sim_events.tti_events2[tti_info.tti_params.tti_rx].new_user) {
|
||||
CONDERROR(!srslte_prach_tti_opportunity_config_fdd(
|
||||
sched_cell_params[CARRIER_IDX].cfg.prach_config, tti_info.tti_params.tti_rx, -1),
|
||||
"[TESTER] New user added in a non-PRACH TTI\n");
|
||||
uint16_t rnti = sim_events.tti_events2[tti_info.tti_params.tti_rx].new_rnti;
|
||||
add_user(rnti, sim_events.sim_args.bearer_cfg, sim_events.sim_args.ue_cfg);
|
||||
}
|
||||
|
||||
// may remove an existing user
|
||||
if (sim_events.tti_events2[tti_info.tti_params.tti_rx].rem_user) {
|
||||
uint16_t rnti = sim_events.tti_events2[tti_info.tti_params.tti_rx].rem_rnti;
|
||||
bearer_ue_rem(rnti, 0);
|
||||
ue_rem(rnti);
|
||||
rem_user(rnti);
|
||||
log_global->info("[TESTER] Removing user rnti=0x%x\n", rnti);
|
||||
}
|
||||
|
||||
// push UL SRs and DL packets
|
||||
for (auto& e : sim_events.tti_events2[tti_info.tti_params.tti_rx].users) {
|
||||
if (e.second.sr_data > 0 and tester_ues[e.first].drb_cfg_flag) {
|
||||
uint32_t tot_ul_data = ue_db[e.first].get_pending_ul_new_data(tti_info.tti_params.tti_tx_ul) + e.second.sr_data;
|
||||
uint32_t lcid = 0;
|
||||
ul_bsr(e.first, lcid, tot_ul_data, true);
|
||||
}
|
||||
auto* user = ue_tester->get_user_state(e.first);
|
||||
if (e.second.dl_data > 0 and user->msg3_tic.is_valid() and user->msg3_tic.tti_rx() < tti_info.tti_params.tti_rx) {
|
||||
// If Msg4 not yet sent, allocate data in SRB0 buffer
|
||||
uint32_t lcid = (user->msg4_tic.is_valid()) ? 2 : 0;
|
||||
uint32_t pending_dl_new_data = ue_db[e.first].get_pending_dl_new_data();
|
||||
if (lcid == 2 and not tester_ues[e.first].drb_cfg_flag) {
|
||||
// If RRCSetup finished
|
||||
if (pending_dl_new_data == 0) {
|
||||
// setup lcid==2 bearer
|
||||
tester_ues[e.first].drb_cfg_flag = true;
|
||||
bearer_ue_cfg(e.first, 2, &tester_ues[e.first].bearer_cfg);
|
||||
} else {
|
||||
// Let SRB0 get emptied
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// TODO: Does it need TTI for checking pending data?
|
||||
uint32_t tot_dl_data = pending_dl_new_data + e.second.dl_data;
|
||||
dl_rlc_buffer_state(e.first, lcid, tot_dl_data, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
tti_data.total_ues = tester_user_results();
|
||||
}
|
||||
|
||||
void sched_tester::before_sched()
|
||||
|
@ -291,7 +166,6 @@ void sched_tester::before_sched()
|
|||
d.has_ul_retx = hul->has_pending_retx();
|
||||
d.has_ul_tx = d.has_ul_retx or d.ul_pending_data > 0;
|
||||
srsenb::dl_harq_proc* hdl = user->get_pending_dl_harq(tti_info.tti_params.tti_tx_dl, CARRIER_IDX);
|
||||
d.has_dl_retx = (hdl != nullptr) and hdl->has_pending_retx(0, tti_info.tti_params.tti_tx_dl);
|
||||
d.has_dl_tx = (hdl != nullptr) or (it.second.get_empty_dl_harq(CARRIER_IDX) != nullptr and d.dl_pending_data > 0);
|
||||
d.has_ul_newtx = not d.has_ul_retx and d.ul_pending_data > 0;
|
||||
tti_data.ue_data.insert(std::make_pair(rnti, d));
|
||||
|
@ -314,54 +188,17 @@ void sched_tester::before_sched()
|
|||
|
||||
int sched_tester::process_results()
|
||||
{
|
||||
tti_info.dl_sched_result.resize(1);
|
||||
tti_info.dl_sched_result[0] = tti_data.sched_result_dl;
|
||||
tti_info.ul_sched_result.resize(1);
|
||||
tti_info.ul_sched_result[0] = tti_data.sched_result_ul;
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_dci_elems; ++i) {
|
||||
uint16_t rnti = tti_data.sched_result_ul.pusch[i].dci.rnti;
|
||||
tti_data.ue_data[rnti].ul_sched = &tti_data.sched_result_ul.pusch[i];
|
||||
CONDERROR(tester_ues.count(rnti) == 0,
|
||||
"[TESTER] [%d] The user rnti=0x%x that no longer exists got allocated.\n",
|
||||
tti_info.tti_params.tti_rx,
|
||||
rnti);
|
||||
}
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_data_elems; ++i) {
|
||||
uint16_t rnti = tti_data.sched_result_dl.data[i].dci.rnti;
|
||||
tti_data.ue_data[rnti].dl_sched = &tti_data.sched_result_dl.data[i];
|
||||
CONDERROR(tester_ues.count(rnti) == 0,
|
||||
"[TESTER] [%d] The user rnti=0x%x that no longer exists got allocated.\n",
|
||||
tti_info.tti_params.tti_rx,
|
||||
rnti);
|
||||
}
|
||||
|
||||
test_tti_result();
|
||||
ue_tester->test_ra(0, tti_info.dl_sched_result[CARRIER_IDX], tti_info.ul_sched_result[CARRIER_IDX]);
|
||||
test_collisions();
|
||||
test_pdcch_collisions();
|
||||
TESTASSERT(ue_tester->test_all(0, tti_info.dl_sched_result[CARRIER_IDX], tti_info.ul_sched_result[CARRIER_IDX]) ==
|
||||
SRSLTE_SUCCESS);
|
||||
test_sch_collisions();
|
||||
assert_no_empty_allocs();
|
||||
test_harqs();
|
||||
output_tester[CARRIER_IDX].test_sib_scheduling(tti_info.tti_params, tti_data.sched_result_dl);
|
||||
output_tester[CARRIER_IDX].test_sib_scheduling(tti_info.tti_params, tti_info.dl_sched_result[CARRIER_IDX]);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int sched_tester::run_tti(const tti_ev& tti_events)
|
||||
{
|
||||
new_test_tti();
|
||||
log_global->info("[TESTER] ---- tti=%u | nof_ues=%zd ----\n", tic.tti_rx(), ue_db.size());
|
||||
|
||||
process_tti_args();
|
||||
|
||||
process_ack_txs();
|
||||
before_sched();
|
||||
|
||||
dl_sched(tti_info.tti_params.tti_tx_dl, CARRIER_IDX, tti_data.sched_result_dl);
|
||||
ul_sched(tti_info.tti_params.tti_tx_ul, CARRIER_IDX, tti_data.sched_result_ul);
|
||||
|
||||
process_results();
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int sched_tester::assert_no_empty_allocs()
|
||||
{
|
||||
// Test if allocations only take place for users with pending data or in RAR
|
||||
|
@ -369,10 +206,14 @@ int sched_tester::assert_no_empty_allocs()
|
|||
uint16_t rnti = iter.first;
|
||||
// srsenb::sched_ue* user = &ue_db[rnti];
|
||||
|
||||
if (!iter.second.has_ul_tx and tti_data.ue_data[rnti].ul_sched != nullptr and
|
||||
tti_data.ue_data[rnti].ul_sched->needs_pdcch) {
|
||||
// TODO: This test does not work for adaptive re-tx
|
||||
TESTERROR("[TESTER] There was a user without data that got allocated in UL\n");
|
||||
if (not iter.second.has_ul_tx) {
|
||||
for (uint32_t i = 0; i < tti_info.ul_sched_result[CARRIER_IDX].nof_dci_elems; ++i) {
|
||||
auto& pusch = tti_info.ul_sched_result[CARRIER_IDX].pusch[i];
|
||||
if (pusch.dci.rnti == rnti and pusch.needs_pdcch) {
|
||||
// TODO: This test does not work for adaptive re-tx
|
||||
TESTERROR("[TESTER] There was a user without data that got allocated in UL\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
// srsenb::ul_harq_proc* hul = user->get_ul_harq(tti_info.tti_params.tti_tx_ul);
|
||||
iter.second.ul_retx_got_delayed = iter.second.has_ul_retx and iter.second.ul_harq.is_empty(0);
|
||||
|
@ -397,45 +238,25 @@ int sched_tester::assert_no_empty_allocs()
|
|||
/**
|
||||
* Tests whether there were collisions in the DCI allocations
|
||||
*/
|
||||
int sched_tester::test_tti_result()
|
||||
int sched_tester::test_pdcch_collisions()
|
||||
{
|
||||
srslte::bounded_bitset<128, true> used_cce;
|
||||
used_cce.resize(srslte_regs_pdcch_ncce(sched_cell_params[CARRIER_IDX].regs.get(), sched_cfg.nof_ctrl_symbols));
|
||||
|
||||
/* TEST: Check if there are collisions in the PDCCH */
|
||||
TESTASSERT(output_tester[CARRIER_IDX].test_pdcch_collisions(
|
||||
tti_data.sched_result_dl, tti_data.sched_result_ul, &tti_data.used_cce) == SRSLTE_SUCCESS);
|
||||
TESTASSERT(output_tester[CARRIER_IDX].test_pdcch_collisions(tti_info.dl_sched_result[CARRIER_IDX],
|
||||
tti_info.ul_sched_result[CARRIER_IDX],
|
||||
&used_cce) == SRSLTE_SUCCESS);
|
||||
|
||||
/* TEST: Check whether dci values are correct */
|
||||
TESTASSERT(output_tester[CARRIER_IDX].test_dci_values_consistency(tti_data.sched_result_dl,
|
||||
tti_data.sched_result_ul) == SRSLTE_SUCCESS);
|
||||
|
||||
const srsenb::sf_sched* tti_sched = carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx);
|
||||
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_dci_elems; ++i) {
|
||||
const auto& pusch = tti_data.sched_result_ul.pusch[i];
|
||||
CONDERROR(ue_db.count(pusch.dci.rnti) == 0, "The allocated rnti=0x%x does not exist\n", pusch.dci.rnti);
|
||||
}
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_data_elems; ++i) {
|
||||
auto& data = tti_data.sched_result_dl.data[i];
|
||||
CONDERROR(ue_db.count(data.dci.rnti) == 0, "Allocated rnti=0x%x that does not exist\n", data.dci.rnti);
|
||||
}
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_rar_elems; ++i) {
|
||||
const auto& rar = tti_data.sched_result_dl.rar[i];
|
||||
for (uint32_t j = 0; j < rar.nof_grants; ++j) {
|
||||
const auto& msg3_grant = rar.msg3_grant[j];
|
||||
const auto& msg3_list =
|
||||
carrier_schedulers[0]->get_sf_sched_ptr(tti_sched->get_tti_rx() + MSG3_DELAY_MS)->get_pending_msg3();
|
||||
const auto& p = msg3_list.front();
|
||||
CONDERROR(msg3_list.empty(), "Pending Msg3 should have been set\n");
|
||||
uint32_t rba = srslte_ra_type2_to_riv(p.L, p.n_prb, sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb);
|
||||
CONDERROR(msg3_grant.grant.rba != rba, "Pending Msg3 RBA is not valid\n");
|
||||
}
|
||||
}
|
||||
TESTASSERT(output_tester[CARRIER_IDX].test_dci_values_consistency(
|
||||
tti_info.dl_sched_result[CARRIER_IDX], tti_info.ul_sched_result[CARRIER_IDX]) == SRSLTE_SUCCESS);
|
||||
|
||||
/* verify if sched_result "used_cce" coincide with sched "used_cce" */
|
||||
auto* tti_alloc = carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx);
|
||||
if (tti_data.used_cce != tti_alloc->get_pdcch_mask()) {
|
||||
if (used_cce != tti_alloc->get_pdcch_mask()) {
|
||||
std::string mask_str = tti_alloc->get_pdcch_mask().to_string();
|
||||
TESTERROR(
|
||||
"[TESTER] The used_cce do not match: (%s!=%s)\n", mask_str.c_str(), tti_data.used_cce.to_string().c_str());
|
||||
TESTERROR("[TESTER] The used_cce do not match: (%s!=%s)\n", mask_str.c_str(), used_cce.to_string().c_str());
|
||||
}
|
||||
|
||||
// TODO: Check postponed retxs
|
||||
|
@ -457,8 +278,8 @@ int sched_tester::test_tti_result()
|
|||
int sched_tester::test_harqs()
|
||||
{
|
||||
/* check consistency of DL harq procedures and allocations */
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_dl.nof_data_elems; ++i) {
|
||||
const auto& data = tti_data.sched_result_dl.data[i];
|
||||
for (uint32_t i = 0; i < tti_info.dl_sched_result[CARRIER_IDX].nof_data_elems; ++i) {
|
||||
const auto& data = tti_info.dl_sched_result[CARRIER_IDX].data[i];
|
||||
uint32_t h_id = data.dci.pid;
|
||||
uint16_t rnti = data.dci.rnti;
|
||||
const srsenb::dl_harq_proc* h = ue_db[rnti].get_dl_harq(h_id, CARRIER_IDX);
|
||||
|
@ -473,17 +294,17 @@ int sched_tester::test_harqs()
|
|||
CONDERROR(tti_data.ue_data[rnti].dl_harqs[h_id].nof_retx(0) + 1 != h->nof_retx(0),
|
||||
"[TESTER] A dl harq of user rnti=0x%x was likely overwritten.\n",
|
||||
rnti);
|
||||
CONDERROR(h->nof_retx(0) >= sim_events.sim_args.ue_cfg.maxharq_tx,
|
||||
CONDERROR(h->nof_retx(0) >= sim_args0.ue_cfg.maxharq_tx,
|
||||
"[TESTER] The number of retx=%d exceeded its max=%d\n",
|
||||
h->nof_retx(0),
|
||||
sim_events.sim_args.ue_cfg.maxharq_tx);
|
||||
sim_args0.ue_cfg.maxharq_tx);
|
||||
} else { // newtx
|
||||
CONDERROR(h->nof_retx(0) != 0, "[TESTER] A new harq was scheduled but with invalid number of retxs\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_dci_elems; ++i) {
|
||||
const auto& pusch = tti_data.sched_result_ul.pusch[i];
|
||||
for (uint32_t i = 0; i < tti_info.ul_sched_result[CARRIER_IDX].nof_dci_elems; ++i) {
|
||||
const auto& pusch = tti_info.ul_sched_result[CARRIER_IDX].pusch[i];
|
||||
uint16_t rnti = pusch.dci.rnti;
|
||||
const auto& ue_data = tti_data.ue_data[rnti];
|
||||
const srsenb::ul_harq_proc* h = ue_db[rnti].get_ul_harq(tti_info.tti_params.tti_tx_ul, CARRIER_IDX);
|
||||
|
@ -506,8 +327,8 @@ int sched_tester::test_harqs()
|
|||
}
|
||||
|
||||
/* Check PHICH allocations */
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_phich_elems; ++i) {
|
||||
const auto& phich = tti_data.sched_result_ul.phich[i];
|
||||
for (uint32_t i = 0; i < tti_info.ul_sched_result[CARRIER_IDX].nof_phich_elems; ++i) {
|
||||
const auto& phich = tti_info.ul_sched_result[CARRIER_IDX].phich[i];
|
||||
CONDERROR(tti_data.ue_data.count(phich.rnti) == 0, "[TESTER] Allocated PHICH rnti no longer exists\n");
|
||||
const auto& hprev = tti_data.ue_data[phich.rnti].ul_harq;
|
||||
const auto* h = ue_db[phich.rnti].get_ul_harq(tti_info.tti_params.tti_tx_ul, CARRIER_IDX);
|
||||
|
@ -525,19 +346,16 @@ int sched_tester::test_harqs()
|
|||
continue;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for (; i < tti_data.sched_result_ul.nof_phich_elems; ++i) {
|
||||
const auto& phich = tti_data.sched_result_ul.phich[i];
|
||||
for (; i < tti_info.ul_sched_result[CARRIER_IDX].nof_phich_elems; ++i) {
|
||||
const auto& phich = tti_info.ul_sched_result[CARRIER_IDX].phich[i];
|
||||
if (phich.rnti == ue.first) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CONDERROR(i == tti_data.sched_result_ul.nof_phich_elems,
|
||||
CONDERROR(i == tti_info.ul_sched_result[CARRIER_IDX].nof_phich_elems,
|
||||
"[TESTER] harq had pending ack but no phich was allocked\n");
|
||||
}
|
||||
|
||||
// schedule future acks
|
||||
TESTASSERT(schedule_acks() == SRSLTE_SUCCESS);
|
||||
|
||||
// Check whether some pids got old
|
||||
if (check_old_pids) {
|
||||
for (auto& user : ue_db) {
|
||||
|
@ -557,65 +375,43 @@ int sched_tester::test_harqs()
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int sched_tester::test_collisions()
|
||||
int sched_tester::test_sch_collisions()
|
||||
{
|
||||
const srsenb::sf_sched* tti_sched = carrier_schedulers[0]->get_sf_sched_ptr(tti_info.tti_params.tti_rx);
|
||||
srsenb::prbmask_t ul_allocs(sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb);
|
||||
|
||||
/* TEST: any collision in PUCCH and PUSCH */
|
||||
TESTASSERT(output_tester[CARRIER_IDX].test_pusch_collisions(
|
||||
tti_info.tti_params, tti_data.sched_result_ul, ul_allocs) == SRSLTE_SUCCESS);
|
||||
tti_info.tti_params, tti_info.ul_sched_result[CARRIER_IDX], ul_allocs) == SRSLTE_SUCCESS);
|
||||
|
||||
/* TEST: check whether cumulative UL PRB masks coincide */
|
||||
if (ul_allocs != tti_sched->get_ul_mask()) {
|
||||
TESTERROR("[TESTER] The UL PRB mask and the scheduler result UL mask are not consistent\n");
|
||||
}
|
||||
|
||||
/* TEST: Check if there is a collision with Msg3 or Msg3 alloc data is not consistent */
|
||||
if (tti_data.ul_pending_msg3_present) {
|
||||
bool passed = false;
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_dci_elems; ++i) {
|
||||
if (tti_data.ul_pending_msg3.rnti == tti_data.sched_result_ul.pusch[i].dci.rnti) {
|
||||
CONDERROR(passed, "[TESTER] There can only be one msg3 allocation per UE\n");
|
||||
CONDERROR(tti_data.sched_result_ul.pusch[i].needs_pdcch, "[TESTER] Msg3 allocations do not need PDCCH DCI\n");
|
||||
uint32_t L, RBstart;
|
||||
srslte_ra_type2_from_riv(tti_data.sched_result_ul.pusch[i].dci.type2_alloc.riv,
|
||||
&L,
|
||||
&RBstart,
|
||||
sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb,
|
||||
sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb);
|
||||
if (RBstart != tti_data.ul_pending_msg3.n_prb or L != tti_data.ul_pending_msg3.L) {
|
||||
TESTERROR("[TESTER] The Msg3 allocation does not coincide with the expected.\n");
|
||||
}
|
||||
passed = true;
|
||||
}
|
||||
}
|
||||
CONDERROR(not passed, "[TESTER] No Msg3 allocation was found in the sched_result\n");
|
||||
}
|
||||
|
||||
// update ue stats with number of allocated UL PRBs
|
||||
for (uint32_t i = 0; i < tti_data.sched_result_ul.nof_dci_elems; ++i) {
|
||||
for (uint32_t i = 0; i < tti_info.ul_sched_result[CARRIER_IDX].nof_dci_elems; ++i) {
|
||||
uint32_t L, RBstart;
|
||||
srslte_ra_type2_from_riv(tti_data.sched_result_ul.pusch[i].dci.type2_alloc.riv,
|
||||
srslte_ra_type2_from_riv(tti_info.ul_sched_result[CARRIER_IDX].pusch[i].dci.type2_alloc.riv,
|
||||
&L,
|
||||
&RBstart,
|
||||
sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb,
|
||||
sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb);
|
||||
ue_stats[tti_data.sched_result_ul.pusch[i].dci.rnti].nof_ul_rbs += L;
|
||||
ue_stats[tti_info.ul_sched_result[CARRIER_IDX].pusch[i].dci.rnti].nof_ul_rbs += L;
|
||||
}
|
||||
|
||||
/* TEST: check any collision in PDSCH */
|
||||
srsenb::rbgmask_t rbgmask(sched_cell_params[CARRIER_IDX].cfg.cell.nof_prb);
|
||||
TESTASSERT(output_tester[CARRIER_IDX].test_pdsch_collisions(tti_info.tti_params, tti_data.sched_result_dl, rbgmask) ==
|
||||
SRSLTE_SUCCESS);
|
||||
TESTASSERT(output_tester[CARRIER_IDX].test_pdsch_collisions(
|
||||
tti_info.tti_params, tti_info.dl_sched_result[CARRIER_IDX], rbgmask) == SRSLTE_SUCCESS);
|
||||
|
||||
// update ue stats with number of DL RB allocations
|
||||
srslte::bounded_bitset<100, true> alloc_mask(sched_cell_params[CARRIER_IDX].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_info.dl_sched_result[CARRIER_IDX].nof_data_elems; ++i) {
|
||||
TESTASSERT(srsenb::extract_dl_prbmask(sched_cell_params[CARRIER_IDX].cfg.cell,
|
||||
tti_data.sched_result_dl.data[i].dci,
|
||||
tti_info.dl_sched_result[CARRIER_IDX].data[i].dci,
|
||||
&alloc_mask) == SRSLTE_SUCCESS);
|
||||
ue_stats[tti_data.sched_result_dl.data[i].dci.rnti].nof_dl_rbs += alloc_mask.count();
|
||||
ue_stats[tti_info.dl_sched_result[CARRIER_IDX].data[i].dci.rnti].nof_dl_rbs += alloc_mask.count();
|
||||
}
|
||||
|
||||
// TEST: check if resulting DL mask is equal to scheduler internal DL mask
|
||||
|
@ -631,129 +427,65 @@ int sched_tester::test_collisions()
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
srsenb::sched_interface::cell_cfg_t generate_cell_cfg()
|
||||
{
|
||||
srsenb::sched_interface::cell_cfg_t cell_cfg = {};
|
||||
srslte_cell_t& cell_cfg_phy = cell_cfg.cell;
|
||||
|
||||
std::uniform_int_distribution<uint32_t> dist_prb_idx(0, 5);
|
||||
uint32_t prb_idx = dist_prb_idx(srsenb::get_rand_gen());
|
||||
|
||||
/* Set PHY cell configuration */
|
||||
cell_cfg_phy.id = 1;
|
||||
cell_cfg_phy.cp = SRSLTE_CP_NORM;
|
||||
cell_cfg_phy.nof_ports = 1;
|
||||
cell_cfg_phy.nof_prb = std::array<uint32_t, 6>({6, 15, 25, 50, 75, 100})[prb_idx];
|
||||
cell_cfg_phy.phich_length = SRSLTE_PHICH_NORM;
|
||||
cell_cfg_phy.phich_resources = SRSLTE_PHICH_R_1;
|
||||
|
||||
cell_cfg.sibs[0].len = 18;
|
||||
cell_cfg.sibs[0].period_rf = 8;
|
||||
cell_cfg.sibs[1].len = 41;
|
||||
cell_cfg.sibs[1].period_rf = 16;
|
||||
cell_cfg.si_window_ms = 40;
|
||||
cell_cfg.nrb_pucch = 2;
|
||||
cell_cfg.prach_freq_offset = (cell_cfg_phy.nof_prb == 6) ? 0 : 2;
|
||||
cell_cfg.prach_rar_window = 3;
|
||||
cell_cfg.maxharq_msg3tx = 3;
|
||||
|
||||
return cell_cfg;
|
||||
}
|
||||
|
||||
void test_scheduler_rand(const sched_sim_args& args)
|
||||
void test_scheduler_rand(sched_sim_events sim)
|
||||
{
|
||||
// Create classes
|
||||
sched_tester tester;
|
||||
srsenb::sched my_sched;
|
||||
|
||||
log_global->set_level(srslte::LOG_LEVEL_INFO);
|
||||
|
||||
tester.sim_events = args;
|
||||
sim_sched_args sim_args = args.sim_args;
|
||||
sim_args.ue_cfg = args.sim_args.ue_cfg;
|
||||
sim_args.bearer_cfg = args.sim_args.bearer_cfg;
|
||||
sim_args.start_tti = 0;
|
||||
sim_args.sim_log = log_global.get();
|
||||
|
||||
tester.init(nullptr);
|
||||
tester.sim_cfg(sim_args);
|
||||
tester.sim_cfg(std::move(sim.sim_args));
|
||||
|
||||
uint32_t tti = 0;
|
||||
uint32_t nof_ttis = 0;
|
||||
while (nof_ttis <= args.tti_events2.size()) {
|
||||
log_global->step(tti);
|
||||
|
||||
tester.run_tti({});
|
||||
|
||||
nof_ttis++;
|
||||
tti = (tti + 1) % 10240;
|
||||
}
|
||||
tester.test_next_ttis(sim.tti_events);
|
||||
}
|
||||
|
||||
sched_sim_args rand_sim_params(uint32_t nof_ttis)
|
||||
sched_sim_events rand_sim_params(uint32_t nof_ttis)
|
||||
{
|
||||
sched_sim_args sim_gen;
|
||||
std::vector<std::vector<uint32_t> > current_rntis;
|
||||
uint16_t rnti_start = 70;
|
||||
uint32_t max_conn_dur = 10000, min_conn_dur = 5000;
|
||||
float P_ul_sr = srsenb::randf() * 0.5, P_dl = srsenb::randf() * 0.5;
|
||||
float P_prach = 0.99f; // 0.1f + randf()*0.3f;
|
||||
float ul_sr_exps[] = {1, 4}; // log rand
|
||||
float dl_data_exps[] = {1, 4}; // log rand
|
||||
uint32_t max_nof_users = 5;
|
||||
std::uniform_int_distribution<> connection_dur_dist(min_conn_dur, max_conn_dur);
|
||||
sched_sim_events sim_gen;
|
||||
uint32_t max_conn_dur = 10000, min_conn_dur = 500;
|
||||
float P_ul_sr = srsenb::randf() * 0.5, P_dl = srsenb::randf() * 0.5;
|
||||
float P_prach = 0.99f; // 0.1f + randf()*0.3f;
|
||||
float ul_sr_exps[] = {1, 4}; // log rand
|
||||
float dl_data_exps[] = {1, 4}; // log rand
|
||||
uint32_t max_nof_users = 5;
|
||||
std::uniform_int_distribution<> connection_dur_dist(min_conn_dur, max_conn_dur);
|
||||
std::uniform_int_distribution<uint32_t> dist_prb_idx(0, 5);
|
||||
uint32_t prb_idx = dist_prb_idx(srsenb::get_rand_gen());
|
||||
uint32_t nof_prb = std::array<uint32_t, 6>({6, 15, 25, 50, 75, 100})[prb_idx];
|
||||
|
||||
sim_gen.sim_args.cell_cfg = {generate_cell_cfg()};
|
||||
sched_sim_event_generator generator;
|
||||
|
||||
sim_gen.sim_args.ue_cfg = generate_default_ue_cfg();
|
||||
sim_gen.sim_args.cell_cfg = {generate_default_cell_cfg(nof_prb)};
|
||||
sim_gen.sim_args.ue_cfg = generate_default_ue_cfg();
|
||||
sim_gen.sim_args.P_retx = 0.1;
|
||||
sim_gen.sim_args.start_tti = 0;
|
||||
sim_gen.sim_args.sim_log = log_global.get();
|
||||
generator.tti_events.resize(nof_ttis);
|
||||
|
||||
bzero(&sim_gen.sim_args.bearer_cfg, sizeof(srsenb::sched_interface::ue_bearer_cfg_t));
|
||||
sim_gen.sim_args.bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
|
||||
|
||||
sim_gen.sim_args.P_retx = 0.1;
|
||||
sim_gen.tti_events2.resize(nof_ttis);
|
||||
// sim_gen.sim_events.resize(nof_ttis);
|
||||
|
||||
for (uint32_t tti = 0; tti < sim_gen.tti_events2.size(); ++tti) {
|
||||
if (not current_rntis.empty()) {
|
||||
// may rem user
|
||||
for (uint32_t i = 0; i < current_rntis.size(); ++i) {
|
||||
if (current_rntis[i][2] + current_rntis[i][1] <= tti) {
|
||||
auto it_to_rem = current_rntis.begin() + i;
|
||||
sim_gen.tti_events2[tti].rem_user = true;
|
||||
sim_gen.tti_events2[tti].rem_rnti = (*it_to_rem)[0];
|
||||
current_rntis.erase(it_to_rem);
|
||||
}
|
||||
for (uint32_t tti = 0; tti < nof_ttis; ++tti) {
|
||||
for (auto& u : generator.current_users) {
|
||||
uint32_t rnti = u.first;
|
||||
if (srsenb::randf() < P_ul_sr) {
|
||||
float exp = ul_sr_exps[0] + srsenb::randf() * (ul_sr_exps[1] - ul_sr_exps[0]);
|
||||
generator.add_ul_data(rnti, (uint32_t)pow(10, exp));
|
||||
}
|
||||
|
||||
for (auto& current_rnti : current_rntis) {
|
||||
uint32_t rnti = current_rnti[0];
|
||||
if (srsenb::randf() < P_ul_sr) {
|
||||
float exp = ul_sr_exps[0] + srsenb::randf() * (ul_sr_exps[1] - ul_sr_exps[0]);
|
||||
sim_gen.tti_events2[tti].users[rnti].sr_data = (uint32_t)pow(10, exp);
|
||||
}
|
||||
if (srsenb::randf() < P_dl) {
|
||||
float exp = dl_data_exps[0] + srsenb::randf() * (dl_data_exps[1] - dl_data_exps[0]);
|
||||
sim_gen.tti_events2[tti].users[rnti].dl_data = (uint32_t)pow(10, exp);
|
||||
}
|
||||
if (srsenb::randf() < P_dl) {
|
||||
float exp = dl_data_exps[0] + srsenb::randf() * (dl_data_exps[1] - dl_data_exps[0]);
|
||||
generator.add_dl_data(rnti, (uint32_t)pow(10, exp));
|
||||
}
|
||||
}
|
||||
|
||||
// may add new user (For now, we only support one UE per PRACH)
|
||||
bool is_prach_tti =
|
||||
srslte_prach_tti_opportunity_config_fdd(sim_gen.sim_args.cell_cfg[CARRIER_IDX].prach_config, tti, -1);
|
||||
if (is_prach_tti and current_rntis.size() < max_nof_users and srsenb::randf() < P_prach) {
|
||||
std::vector<uint32_t> elem(3);
|
||||
elem[0] = rnti_start;
|
||||
elem[1] = tti;
|
||||
elem[2] = connection_dur_dist(srsenb::get_rand_gen());
|
||||
current_rntis.push_back(elem);
|
||||
sim_gen.tti_events2[tti].new_user = true;
|
||||
sim_gen.tti_events2[tti].new_rnti = rnti_start;
|
||||
rnti_start++;
|
||||
if (is_prach_tti and generator.current_users.size() < max_nof_users and srsenb::randf() < P_prach) {
|
||||
generator.add_new_default_user(connection_dur_dist(srsenb::get_rand_gen()));
|
||||
}
|
||||
generator.step_tti();
|
||||
}
|
||||
|
||||
sim_gen.tti_events = std::move(generator.tti_events);
|
||||
|
||||
return sim_gen;
|
||||
}
|
||||
|
||||
|
@ -761,16 +493,15 @@ int main()
|
|||
{
|
||||
// Setup seed
|
||||
srsenb::set_randseed(seed);
|
||||
printf("[TESTER] This is the chosen seed: %u\n", seed);
|
||||
|
||||
srslte::logmap::set_default_log_level(srslte::LOG_LEVEL_INFO);
|
||||
printf("[TESTER] This is the chosen seed: %u\n", seed);
|
||||
/* initialize random seed: */
|
||||
uint32_t N_runs = 1, nof_ttis = 10240 + 10;
|
||||
|
||||
for (uint32_t n = 0; n < N_runs; ++n) {
|
||||
printf("Sim run number: %u\n", n + 1);
|
||||
sched_sim_args sim_args = rand_sim_params(nof_ttis);
|
||||
test_scheduler_rand(sim_args);
|
||||
sched_sim_events sim = rand_sim_params(nof_ttis);
|
||||
test_scheduler_rand(std::move(sim));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "srslte/interfaces/sched_interface.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
|
||||
struct tti_counter {
|
||||
tti_counter() = default;
|
||||
|
@ -153,7 +154,6 @@ struct sim_sched_args {
|
|||
uint32_t start_tti = 0;
|
||||
float P_retx;
|
||||
srsenb::sched_interface::ue_cfg_t ue_cfg;
|
||||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg;
|
||||
std::vector<srsenb::sched_interface::cell_cfg_t> cell_cfg;
|
||||
srslte::log* sim_log = nullptr;
|
||||
};
|
||||
|
@ -170,14 +170,16 @@ struct sched_sim_event_generator {
|
|||
|
||||
struct user_data {
|
||||
uint16_t rnti;
|
||||
uint32_t tti_start;
|
||||
uint32_t tti_duration;
|
||||
uint32_t tti_start = 0;
|
||||
uint32_t tti_duration = 0;
|
||||
};
|
||||
std::vector<user_data> current_users;
|
||||
std::unordered_map<uint16_t, user_data> current_users;
|
||||
|
||||
// generated events
|
||||
std::vector<tti_ev> tti_events;
|
||||
|
||||
sched_sim_event_generator() { tti_events.push_back(tti_ev{}); }
|
||||
|
||||
void step_tti(uint32_t nof_ttis = 1)
|
||||
{
|
||||
tti_counter += nof_ttis;
|
||||
|
@ -210,10 +212,10 @@ struct sched_sim_event_generator {
|
|||
user.rnti = next_rnti++;
|
||||
// creates a user with one supported CC (PRACH stage)
|
||||
user.ue_cfg.reset(new srsenb::sched_interface::ue_cfg_t{generate_default_ue_cfg()});
|
||||
current_users.emplace_back();
|
||||
current_users.back().rnti = user.rnti;
|
||||
current_users.back().tti_start = tti_counter;
|
||||
current_users.back().tti_duration = duration;
|
||||
auto& u = current_users[user.rnti];
|
||||
u.rnti = user.rnti;
|
||||
u.tti_start = tti_counter;
|
||||
u.tti_duration = duration;
|
||||
return &user;
|
||||
}
|
||||
|
||||
|
@ -265,34 +267,30 @@ private:
|
|||
return &(*it);
|
||||
}
|
||||
|
||||
bool user_exists(uint16_t rnti)
|
||||
{
|
||||
return std::find_if(current_users.begin(), current_users.end(), [&rnti](const user_data& u) {
|
||||
return u.rnti == rnti;
|
||||
}) != current_users.end();
|
||||
}
|
||||
bool user_exists(uint16_t rnti) { return current_users.find(rnti) != current_users.end(); }
|
||||
|
||||
void rem_old_users()
|
||||
{
|
||||
// remove users that pass their connection duration
|
||||
auto rem_it = std::remove_if(current_users.begin(), current_users.end(), [this](const user_data& u) {
|
||||
return u.tti_start + u.tti_duration < tti_counter;
|
||||
});
|
||||
|
||||
// set the call rem_user(...) at the right tti
|
||||
for (auto it = rem_it; it != current_users.end(); ++it) {
|
||||
uint32_t rem_tti = it->tti_start + it->tti_duration;
|
||||
auto& l = tti_events[rem_tti].user_updates;
|
||||
auto user_it = std::find_if(l.begin(), l.end(), [&it](tti_ev::user_cfg_ev& u) { return it->rnti == u.rnti; });
|
||||
for (auto it = current_users.begin(); it != current_users.end();) {
|
||||
user_data& user = it->second;
|
||||
uint32_t rem_tti = user.tti_start + user.tti_duration;
|
||||
if (rem_tti > tti_counter) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
// set the call rem_user(...) at the right tti
|
||||
auto& l = tti_events[rem_tti].user_updates;
|
||||
auto user_it = std::find_if(l.begin(), l.end(), [&it](tti_ev::user_cfg_ev& u) { return it->first == u.rnti; });
|
||||
if (user_it == l.end()) {
|
||||
l.emplace_back();
|
||||
l.back().rem_user = true;
|
||||
l.back().rnti = it->first;
|
||||
} else {
|
||||
user_it->rem_user = true;
|
||||
}
|
||||
it = current_users.erase(it);
|
||||
}
|
||||
|
||||
current_users.erase(rem_it, current_users.end());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue