nr,gnb,sched,test: extend scheduler testing to generate UL HARQ acks

master
Francisco 3 years ago committed by Francisco Paisana
parent ed1514cf68
commit 17f7a86647

@ -13,7 +13,7 @@
#ifndef SRSRAN_SCHED_NR_CFG_H
#define SRSRAN_SCHED_NR_CFG_H
#include "sched_nr_interface.h"
#include "sched_nr_interface_utils.h"
#include "sched_nr_rb.h"
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/adt/optional_array.h"
@ -148,12 +148,11 @@ public:
}
const srsran_search_space_t* find_ss_with_dci_format(srsran_dci_format_nr_t valid_format) const
{
for (uint32_t ss_id = 0; ss_id < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ss_id) {
if (phy().pdcch.search_space_present[ss_id]) {
for (uint32_t i = 0; i < phy().pdcch.search_space[ss_id].nof_formats; ++i) {
if (phy().pdcch.search_space[ss_id].formats[i] == valid_format) {
return &phy().pdcch.search_space[ss_id];
}
auto active_ss_lst = view_active_search_spaces(phy().pdcch);
for (const srsran_search_space_t& ss : active_ss_lst) {
for (uint32_t i = 0; i < ss.nof_formats; ++i) {
if (ss.formats[i] == valid_format) {
return &ss;
}
}
}
@ -192,7 +191,6 @@ private:
};
} // namespace sched_nr_impl
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_CFG_H

@ -15,6 +15,7 @@
#include "sched_nr_cfg.h"
#include "sched_nr_ue.h"
#include "srsran/adt/optional_array.h"
namespace srsenb {
namespace sched_nr_impl {
@ -23,8 +24,6 @@ class slot_ue;
class ul_harq_proc;
struct bwp_res_grid;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool fill_dci_sib(prb_interval interv,
uint32_t sib_idx,
uint32_t si_ntx,

@ -0,0 +1,36 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_SCHED_NR_INTERFACE_HELPERS_H
#define SRSRAN_SCHED_NR_INTERFACE_HELPERS_H
#include "sched_nr_interface.h"
#include "srsran/adt/optional_array.h"
namespace srsenb {
// Helpers to handle PHY struct types
/// Get a range of active search spaces in a PDCCH configuration
inline srsran::split_optional_span<srsran_search_space_t> view_active_search_spaces(srsran_pdcch_cfg_nr_t& pdcch)
{
return srsran::split_optional_span<srsran_search_space_t>{pdcch.search_space, pdcch.search_space_present};
}
inline srsran::split_optional_span<const srsran_search_space_t>
view_active_search_spaces(const srsran_pdcch_cfg_nr_t& pdcch)
{
return srsran::split_optional_span<const srsran_search_space_t>{pdcch.search_space, pdcch.search_space_present};
}
} // namespace srsenb
#endif // SRSRAN_SCHED_NR_INTERFACE_HELPERS_H

@ -419,7 +419,6 @@ int sched_nr::dl_rach_info(const rar_info_t& rar_info, const ue_cfg_t& uecfg)
auto add_ue = [this, uecfg, rar_info](event_manager::logger& ev_logger) {
// create user
// Note: UEs being created in sched main thread, which has higher priority
logger->info("SCHED: New user rnti=0x%x, cc=%d", rar_info.temp_crnti, uecfg.carriers[0].cc);
std::unique_ptr<ue> u{new ue{rar_info.temp_crnti, uecfg, cfg}};
uint16_t rnti = rar_info.temp_crnti;

@ -110,7 +110,7 @@ ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params_t& sched_cfg_) :
void ue::set_cfg(const ue_cfg_t& cfg)
{
bool conres_needed = cfg.is_temp_crnti != ue_cfg.is_temp_crnti;
bool conres_needed = not cfg.is_temp_crnti and ue_cfg.is_temp_crnti;
ue_cfg = cfg;
for (auto& ue_cc_cfg : cfg.carriers) {

@ -6,16 +6,17 @@
# the distribution.
#
add_library(sched_nr_test_suite sched_nr_common_test.cc sched_nr_ue_ded_test_suite.cc)
add_library(sched_nr_test_suite sched_nr_common_test.cc sched_nr_ue_ded_test_suite.cc sched_nr_sim_ue.cc)
target_link_libraries(sched_nr_test_suite srsgnb_mac srsran_common)
add_executable(sched_nr_test sched_nr_test.cc sched_nr_sim_ue.cc)
target_link_libraries(sched_nr_test
add_executable(sched_nr_parallel_test sched_nr_parallel_test.cc)
target_link_libraries(sched_nr_parallel_test
srsgnb_mac
sched_nr_test_suite
srsran_common
${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES})
add_nr_test(sched_nr_test sched_nr_test)
add_nr_test(sched_nr_parallel_test sched_nr_parallel_test)
add_executable(sched_nr_prb_test sched_nr_prb_test.cc)
target_link_libraries(sched_nr_prb_test
@ -28,3 +29,11 @@ add_nr_test(sched_nr_prb_test sched_nr_prb_test)
add_executable(sched_nr_rar_test sched_nr_rar_test.cc)
target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common)
add_nr_test(sched_nr_rar_test sched_nr_rar_test)
add_executable(sched_nr_test sched_nr_test.cc)
target_link_libraries(sched_nr_test
srsgnb_mac
sched_nr_test_suite
srsran_common ${CMAKE_THREAD_LIBS_INIT}
${Boost_LIBRARIES})
add_nr_test(sched_nr_test sched_nr_test)

@ -13,7 +13,7 @@
#ifndef SRSRAN_SCHED_NR_CFG_GENERATORS_H
#define SRSRAN_SCHED_NR_CFG_GENERATORS_H
#include "srsgnb/hdr/stack/mac/sched_nr_interface.h"
#include "srsgnb/hdr/stack/mac/sched_nr_interface_utils.h"
#include "srsran/common/phy_cfg_nr_default.h"
namespace srsenb {
@ -62,11 +62,14 @@ inline std::vector<sched_nr_interface::cell_cfg_t> get_default_cells_cfg(
return cells;
}
inline sched_nr_interface::ue_cfg_t get_rach_ue_cfg(uint32_t cc)
inline sched_nr_interface::ue_cfg_t get_rach_ue_cfg(uint32_t cc,
const srsran::phy_cfg_nr_t& phy_cfg = srsran::phy_cfg_nr_default_t{
srsran::phy_cfg_nr_default_t::reference_cfg_t{}})
{
sched_nr_interface::ue_cfg_t uecfg{};
uecfg.is_temp_crnti = true;
// set Pcell
// set PCell
uecfg.carriers.resize(1);
uecfg.carriers[0].active = true;
uecfg.carriers[0].cc = cc;
@ -77,6 +80,12 @@ inline sched_nr_interface::ue_cfg_t get_rach_ue_cfg(uint32_t cc)
// set basic PHY config
uecfg.phy_cfg = srsran::phy_cfg_nr_default_t{srsran::phy_cfg_nr_default_t::reference_cfg_t{}};
uecfg.phy_cfg.csi = {};
for (srsran_search_space_t& ss : view_active_search_spaces(uecfg.phy_cfg.pdcch)) {
// disable UE-specific search spaces
if (ss.type == srsran_search_space_type_ue) {
uecfg.phy_cfg.pdcch.search_space_present[ss.id] = false;
}
}
return uecfg;
}

@ -16,13 +16,23 @@
namespace srsenb {
void test_dl_pdcch_consistency(srsran::const_span<sched_nr_impl::pdcch_dl_t> dl_pdcchs)
void test_dl_pdcch_consistency(const sched_nr_interface::cell_cfg_t& cell_cfg,
srsran::const_span<sched_nr_impl::pdcch_dl_t> dl_pdcchs)
{
for (const auto& pdcch : dl_pdcchs) {
TESTASSERT(pdcch.dci.bwp_id < cell_cfg.bwps.size());
const srsran_pdcch_cfg_nr_t& pdcch_cfg = cell_cfg.bwps[pdcch.dci.bwp_id].pdcch;
TESTASSERT(pdcch_cfg.coreset_present[pdcch.dci.ctx.coreset_id]);
if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) {
TESTASSERT_EQ(pdcch.dci.ctx.format, srsran_dci_format_nr_1_0);
TESTASSERT_EQ(pdcch.dci.ctx.ss_type, srsran_search_space_type_common_1);
TESTASSERT(pdcch.dci.ctx.location.L > 0);
TESTASSERT(pdcch.dci.ctx.location.L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR);
// check consistency with cell_cfg
TESTASSERT(pdcch_cfg.ra_search_space_present);
TESTASSERT_EQ(pdcch_cfg.ra_search_space.coreset_id, pdcch.dci.ctx.coreset_id);
TESTASSERT(pdcch_cfg.ra_search_space.nof_candidates[pdcch.dci.ctx.location.L] > 0);
} else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) {
TESTASSERT(pdcch.dci.ctx.format == srsran_dci_format_nr_1_0 or pdcch.dci.ctx.format == srsran_dci_format_nr_1_1);
}

@ -18,7 +18,8 @@
namespace srsenb {
void test_dl_pdcch_consistency(srsran::const_span<sched_nr_impl::pdcch_dl_t> dl_pdcch);
void test_dl_pdcch_consistency(const sched_nr_interface::cell_cfg_t& cell_cfg,
srsran::const_span<sched_nr_impl::pdcch_dl_t> dl_pdcch);
void test_pdsch_consistency(srsran::const_span<mac_interface_phy_nr::pdsch_t> dl_pdcch);
/// @brief Test whether the SSB grant gets scheduled with the correct periodicity.
void test_ssb_scheduled_grant(

@ -74,7 +74,7 @@ void test_single_prach()
log_sched_bwp_result(mac_logger, alloc.get_pdcch_tti(), alloc.res_grid(), slot_ues);
const bwp_slot_grid* result = &alloc.res_grid()[alloc.get_pdcch_tti()];
test_dl_pdcch_consistency(result->dl.phy.pdcch_dl);
test_dl_pdcch_consistency(res_grid->cfg->cell_cfg, result->dl.phy.pdcch_dl);
++pdcch_slot;
return result;
};

@ -64,6 +64,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_result_view& cc_out)
void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_result_view& cc_out)
{
uint32_t cc = cc_out.cc;
// Update DL Harqs
for (uint32_t i = 0; i < cc_out.dl->phy.pdcch_dl.size(); ++i) {
const auto& data = cc_out.dl->phy.pdcch_dl[i];
if (data.dci.ctx.rnti != ctxt.rnti) {
@ -89,6 +91,61 @@ void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_result_view& cc_out)
.dl_data_to_ul_ack[h.last_slot_tx.slot_idx() % ctxt.ue_cfg.phy_cfg.harq_ack.nof_dl_data_to_ul_ack];
h.nof_txs++;
}
// Update UL harqs
for (uint32_t i = 0; i < cc_out.dl->phy.pdcch_ul.size(); ++i) {
const auto& data = cc_out.dl->phy.pdcch_ul[i];
if (data.dci.ctx.rnti != ctxt.rnti) {
continue;
}
auto& h = ctxt.cc_list[cc].ul_harqs[data.dci.pid];
if (h.nof_txs == 0 or h.ndi != data.dci.ndi) {
// It is newtx
h.nof_retxs = 0;
h.ndi = data.dci.ndi;
h.first_slot_tx = cc_out.slot + 4; // TODO
h.dci_loc = data.dci.ctx.location;
h.tbs = 100; // TODO
} else {
// it is retx
h.nof_retxs++;
}
h.active = true;
h.last_slot_tx = cc_out.slot + 4; // TODO
h.last_slot_ack = h.last_slot_tx;
h.nof_txs++;
}
uint32_t rar_count = 0;
for (uint32_t i = 0; i < cc_out.dl->phy.pdcch_dl.size(); ++i) {
const auto& rar_pdcch = cc_out.dl->phy.pdcch_dl[i];
if (rar_pdcch.dci.ctx.rnti_type != srsran_rnti_type_ra) {
continue;
}
const auto& rar_data = cc_out.dl->rar[rar_count++];
for (uint32_t j = 0; j < rar_data.grants.size(); ++j) {
auto& msg3_grant = rar_data.grants[j];
if (msg3_grant.msg3_dci.ctx.rnti != ctxt.rnti) {
continue;
}
auto& h = ctxt.cc_list[cc].ul_harqs[msg3_grant.msg3_dci.pid];
if (h.nof_txs == 0) {
// It is newtx
h.nof_retxs = 0;
h.ndi = msg3_grant.msg3_dci.ndi;
h.first_slot_tx = cc_out.slot + 4 + MSG3_DELAY_MS; // TODO
h.dci_loc = msg3_grant.msg3_dci.ctx.location;
h.tbs = 100; // TODO
} else {
// it is retx
h.nof_retxs++;
}
h.active = true;
h.last_slot_tx = cc_out.slot + 4 + MSG3_DELAY_MS; // TODO
h.last_slot_ack = h.last_slot_tx;
h.nof_txs++;
}
}
}
sched_nr_base_tester::sched_nr_base_tester(const sched_nr_interface::sched_args_t& sched_args,
@ -98,11 +155,10 @@ sched_nr_base_tester::sched_nr_base_tester(const sched_nr_interface::sched_args_
logger(srslog::fetch_basic_logger("TEST")),
mac_logger(srslog::fetch_basic_logger("MAC-NR")),
sched_ptr(new sched_nr()),
test_name(std::move(test_name_))
test_delimiter(new srsran::test_delimit_logger{test_name_.c_str()})
{
sem_init(&slot_sem, 0, 1);
printf("\n=========== Start %s ===========\n", test_name.c_str());
cell_params.reserve(cell_cfg_list.size());
for (uint32_t cc = 0; cc < cell_cfg_list.size(); ++cc) {
cell_params.emplace_back(cc, cell_cfg_list[cc], sched_args);
@ -136,7 +192,7 @@ void sched_nr_base_tester::stop()
worker->stop();
}
sem_destroy(&slot_sem);
printf("============ End %s ===========\n", test_name.c_str());
test_delimiter.reset();
}
}
@ -163,6 +219,14 @@ int sched_nr_base_tester::add_user(uint16_t rnti,
return SRSRAN_SUCCESS;
}
void sched_nr_base_tester::user_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_)
{
TESTASSERT(ue_db.count(rnti) > 0);
ue_db.at(rnti).get_ctxt().ue_cfg = ue_cfg_;
sched_ptr->ue_cfg(rnti, ue_cfg_);
}
void sched_nr_base_tester::run_slot(slot_point slot_tx)
{
srsran_assert(not stopped.load(std::memory_order_relaxed), "Running scheduler when it has already been stopped");
@ -236,7 +300,7 @@ void sched_nr_base_tester::process_results()
sched_nr_cc_result_view cc_out = cc_results[cc].res;
// Run common tests
test_dl_pdcch_consistency(cc_out.dl->phy.pdcch_dl);
test_dl_pdcch_consistency(cell_params[cc].cfg, cc_out.dl->phy.pdcch_dl);
test_pdsch_consistency(cc_out.dl->phy.pdsch);
test_ssb_scheduled_grant(cc_out.slot, cell_params[cc_out.cc].cfg, cc_out.dl->phy.ssb);
@ -265,12 +329,12 @@ int sched_nr_base_tester::set_default_slot_events(const sim_nr_ue_ctxt_t& ue_ctx
auto& ul_h = ue_ctxt.cc_list[enb_cc_idx].ul_harqs[pid];
// Set default DL ACK
if (dl_h.active and (dl_h.last_slot_ack) == current_slot_tx) {
if (dl_h.active and dl_h.last_slot_ack == current_slot_tx) {
cc_feedback.dl_acks.push_back(ue_nr_slot_events::ack_t{pid, true});
}
// Set default UL ACK
if (ul_h.active and (ul_h.last_slot_tx + 8) == current_slot_tx) {
if (ul_h.active and ul_h.last_slot_ack == current_slot_tx) {
cc_feedback.ul_acks.emplace_back(ue_nr_slot_events::ack_t{pid, true});
}
@ -314,11 +378,8 @@ int sched_nr_base_tester::apply_slot_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_
"UL ACK rnti=0x%x, slot_ul_tx=%u, cc=%d pid=%d", ue_ctxt.rnti, h.last_slot_tx.to_uint(), enb_cc_idx, h.pid);
}
// // update scheduler
// if (sched_ptr->ul_crc_info(events.slot_rx.to_uint(), ue_ctxt.rnti, enb_cc_idx, cc_feedback.ul_ack) < 0) {
// logger.error("The ACKed UL Harq pid=%d does not exist.", cc_feedback.ul_pid);
// error_counter++;
// }
// update scheduler
sched_ptr->ul_crc_info(ue_ctxt.rnti, enb_cc_idx, ack.pid, ack.ack);
}
}

@ -16,6 +16,7 @@
#include "srsenb/test/mac/sched_sim_ue.h"
#include "srsgnb/hdr/stack/mac/sched_nr.h"
#include "srsran/adt/circular_array.h"
#include "srsran/common/test_common.h"
#include <condition_variable>
#include <semaphore.h>
@ -103,7 +104,7 @@ private:
sim_nr_ue_ctxt_t ctxt;
};
/// Implementation of features common to sched_nr_sim_parallel and sched_nr_sim
/// Implementation of features common to parallel and sequential sched nr testers
class sched_nr_base_tester
{
public:
@ -121,8 +122,12 @@ public:
void run_slot(slot_point slot_tx);
void stop();
slot_point get_slot_tx() const { return current_slot_tx; }
int add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_, slot_point tti_rx, uint32_t preamble_idx);
void user_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_);
srsran::const_span<sched_nr_impl::cell_params_t> get_cell_params() { return cell_params; }
// configurable by simulator concrete implementation
@ -141,7 +146,7 @@ protected:
/// Runs general tests to verify result consistency, and updates UE state
void process_results();
std::string test_name;
std::unique_ptr<srsran::test_delimit_logger> test_delimiter;
srslog::basic_logger& logger;
srslog::basic_logger& mac_logger;
std::unique_ptr<sched_nr> sched_ptr;

@ -25,7 +25,7 @@ struct sched_event_t {
sched_event_t add_user(uint32_t slot_count, uint16_t rnti, uint32_t preamble_idx)
{
auto task = [rnti, preamble_idx](sched_nr_base_tester& tester) {
tester.add_user(rnti, get_rach_ue_cfg(1), tester.get_slot_tx() - TX_ENB_DELAY, preamble_idx);
tester.add_user(rnti, get_rach_ue_cfg(0), tester.get_slot_tx() - TX_ENB_DELAY, preamble_idx);
};
return sched_event_t{slot_count, task};
}
@ -76,7 +76,7 @@ int main()
auto& test_logger = srslog::fetch_basic_logger("TEST");
test_logger.set_level(srslog::basic_levels::warning);
auto& mac_nr_logger = srslog::fetch_basic_logger("MAC-NR");
mac_nr_logger.set_level(srslog::basic_levels::warning);
mac_nr_logger.set_level(srslog::basic_levels::debug);
auto& pool_logger = srslog::fetch_basic_logger("POOL");
pool_logger.set_level(srslog::basic_levels::debug);

Loading…
Cancel
Save