mirror of https://github.com/pvnis/srsRAN_4G.git
sched,nr: implementation of sched sim test class
parent
f1b3cfc764
commit
75153c7c83
@ -0,0 +1,211 @@
|
||||
/**
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sched_nr_sim_ue.h"
|
||||
#include "lib/include/srsran/common/test_common.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
sched_nr_ue_sim::sched_nr_ue_sim(uint16_t rnti_,
|
||||
const sched_nr_interface::ue_cfg_t& ue_cfg_,
|
||||
tti_point prach_tti_rx,
|
||||
uint32_t preamble_idx) :
|
||||
logger(srslog::fetch_basic_logger("MAC"))
|
||||
{
|
||||
ctxt.rnti = rnti_;
|
||||
ctxt.prach_tti_rx = prach_tti_rx;
|
||||
ctxt.preamble_idx = preamble_idx;
|
||||
ctxt.ue_cfg = ue_cfg_;
|
||||
|
||||
ctxt.cc_list.resize(ue_cfg_.carriers.size());
|
||||
for (auto& cc : ctxt.cc_list) {
|
||||
for (size_t pid = 0; pid < SCHED_NR_MAX_HARQ; ++pid) {
|
||||
cc.ul_harqs[pid].pid = pid;
|
||||
cc.dl_harqs[pid].pid = pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out)
|
||||
{
|
||||
update_dl_harqs(cc_out);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
void sched_nr_ue_sim::update_dl_harqs(const sched_nr_cc_output_res_t& cc_out)
|
||||
{
|
||||
uint32_t cc = cc_out.cc;
|
||||
for (uint32_t i = 0; i < cc_out.dl_cc_result->pdsch.size(); ++i) {
|
||||
const auto& data = cc_out.dl_cc_result->pdsch[i];
|
||||
if (data.dci.ctx.rnti != ctxt.rnti) {
|
||||
continue;
|
||||
}
|
||||
auto& h = ctxt.cc_list[cc].dl_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_tti_rx = cc_out.tti_rx;
|
||||
h.dci_loc = data.dci.ctx.location;
|
||||
h.tbs = 100; // TODO
|
||||
} else {
|
||||
// it is retx
|
||||
h.nof_retxs++;
|
||||
}
|
||||
h.active = true;
|
||||
h.last_tti_rx = cc_out.tti_rx;
|
||||
h.nof_txs++;
|
||||
}
|
||||
}
|
||||
|
||||
sched_nr_sim_base::sched_nr_sim_base(const sched_nr_interface::sched_cfg_t& sched_args,
|
||||
const std::vector<sched_nr_interface::cell_cfg_t>& cell_cfg_list,
|
||||
std::string test_name_) :
|
||||
logger(srslog::fetch_basic_logger("TEST")),
|
||||
mac_logger(srslog::fetch_basic_logger("MAC")),
|
||||
sched_ptr(new sched_nr(sched_args)),
|
||||
test_name(std::move(test_name_))
|
||||
{
|
||||
logger.info("\n=========== Start %s ===========", 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);
|
||||
}
|
||||
sched_ptr->cell_cfg(cell_cfg_list); // call parent cfg
|
||||
TESTASSERT(cell_params.size() > 0);
|
||||
}
|
||||
|
||||
sched_nr_sim_base::~sched_nr_sim_base()
|
||||
{
|
||||
logger.info("=========== End %s ==========\n", test_name.c_str());
|
||||
}
|
||||
|
||||
int sched_nr_sim_base::add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx)
|
||||
{
|
||||
TESTASSERT(ue_db.count(rnti) == 0);
|
||||
|
||||
ue_db.insert(std::make_pair(rnti, sched_nr_ue_sim(rnti, ue_cfg_, current_tti_rx, preamble_idx)));
|
||||
sched_ptr->ue_cfg(rnti, ue_cfg_);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
void sched_nr_sim_base::slot_indication(srsran::tti_point tti_rx)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
logger.set_context(tti_rx.to_uint());
|
||||
mac_logger.set_context(tti_rx.to_uint());
|
||||
current_tti_rx = tti_rx;
|
||||
logger.info("---------------- TTI=%d ---------------", tti_rx.to_uint());
|
||||
for (auto& ue : ue_db) {
|
||||
ue_tti_events events;
|
||||
set_default_tti_events(ue.second.get_ctxt(), events);
|
||||
set_external_tti_events(ue.second.get_ctxt(), events);
|
||||
apply_tti_events(ue.second.get_ctxt(), events);
|
||||
}
|
||||
}
|
||||
sched_ptr->slot_indication(tti_rx);
|
||||
}
|
||||
|
||||
void sched_nr_sim_base::update(sched_nr_cc_output_res_t& cc_out)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
for (auto& ue_pair : ue_db) {
|
||||
ue_pair.second.update(cc_out);
|
||||
}
|
||||
}
|
||||
|
||||
int sched_nr_sim_base::set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events)
|
||||
{
|
||||
pending_events.cc_list.clear();
|
||||
pending_events.cc_list.resize(cell_params.size());
|
||||
pending_events.tti_rx = current_tti_rx;
|
||||
|
||||
for (uint32_t enb_cc_idx = 0; enb_cc_idx < pending_events.cc_list.size(); ++enb_cc_idx) {
|
||||
auto& cc_feedback = pending_events.cc_list[enb_cc_idx];
|
||||
|
||||
cc_feedback.configured = true;
|
||||
cc_feedback.ue_cc_idx = enb_cc_idx;
|
||||
for (uint32_t pid = 0; pid < SCHED_NR_MAX_HARQ; ++pid) {
|
||||
auto& dl_h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[pid];
|
||||
auto& ul_h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[pid];
|
||||
|
||||
// Set default DL ACK
|
||||
if (dl_h.active and (dl_h.last_tti_rx + 8) == current_tti_rx) {
|
||||
cc_feedback.dl_pid = pid;
|
||||
cc_feedback.dl_ack = true; // default is ACK
|
||||
}
|
||||
|
||||
// Set default UL ACK
|
||||
if (ul_h.active and (ul_h.last_tti_rx + 8) == current_tti_rx) {
|
||||
cc_feedback.ul_pid = pid;
|
||||
cc_feedback.ul_ack = true;
|
||||
}
|
||||
|
||||
// TODO: other CSI
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int sched_nr_sim_base::apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_events& events)
|
||||
{
|
||||
for (uint32_t enb_cc_idx = 0; enb_cc_idx < events.cc_list.size(); ++enb_cc_idx) {
|
||||
const auto& cc_feedback = events.cc_list[enb_cc_idx];
|
||||
if (not cc_feedback.configured) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cc_feedback.dl_pid >= 0) {
|
||||
auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].dl_harqs[cc_feedback.dl_pid];
|
||||
|
||||
if (cc_feedback.dl_ack) {
|
||||
logger.info("DL ACK rnti=0x%x tti_dl_tx=%u cc=%d pid=%d",
|
||||
ue_ctxt.rnti,
|
||||
to_tx_dl(h.last_tti_rx).to_uint(),
|
||||
enb_cc_idx,
|
||||
cc_feedback.dl_pid);
|
||||
}
|
||||
|
||||
// update scheduler
|
||||
sched_ptr->dl_ack_info(ue_ctxt.rnti, enb_cc_idx, cc_feedback.dl_pid, cc_feedback.tb, cc_feedback.dl_ack);
|
||||
|
||||
// update UE sim context
|
||||
if (cc_feedback.dl_ack or ue_ctxt.is_last_dl_retx(cc_feedback.ue_cc_idx, cc_feedback.dl_pid)) {
|
||||
h.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cc_feedback.ul_pid >= 0) {
|
||||
auto& h = ue_ctxt.cc_list[cc_feedback.ue_cc_idx].ul_harqs[cc_feedback.ul_pid];
|
||||
|
||||
if (cc_feedback.ul_ack) {
|
||||
logger.info("UL ACK rnti=0x%x, tti_ul_tx=%u, cc=%d pid=%d",
|
||||
ue_ctxt.rnti,
|
||||
to_tx_ul(h.last_tti_rx).to_uint(),
|
||||
enb_cc_idx,
|
||||
cc_feedback.ul_pid);
|
||||
}
|
||||
|
||||
// // update scheduler
|
||||
// if (sched_ptr->ul_crc_info(events.tti_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++;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
@ -0,0 +1,128 @@
|
||||
/**
|
||||
*
|
||||
* \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_SIM_UE_H
|
||||
#define SRSRAN_SCHED_NR_SIM_UE_H
|
||||
|
||||
#include "../sched_sim_ue.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr.h"
|
||||
#include <condition_variable>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
struct sched_nr_cc_output_res_t {
|
||||
tti_point tti_rx;
|
||||
uint32_t cc;
|
||||
sched_nr_interface::dl_tti_request_t* dl_cc_result;
|
||||
sched_nr_interface::ul_tti_request_t* ul_cc_result;
|
||||
};
|
||||
|
||||
struct sim_nr_ue_ctxt_t {
|
||||
uint16_t rnti;
|
||||
uint32_t preamble_idx;
|
||||
srsran::tti_point prach_tti_rx;
|
||||
sched_nr_interface::ue_cfg_t ue_cfg;
|
||||
std::vector<ue_cc_ctxt_t> cc_list;
|
||||
|
||||
bool is_last_dl_retx(uint32_t ue_cc_idx, uint32_t pid) const
|
||||
{
|
||||
auto& h = cc_list.at(ue_cc_idx).dl_harqs[pid];
|
||||
return h.nof_retxs + 1 >= ue_cfg.maxharq_tx;
|
||||
}
|
||||
};
|
||||
|
||||
class sched_nr_ue_sim
|
||||
{
|
||||
public:
|
||||
sched_nr_ue_sim(uint16_t rnti_,
|
||||
const sched_nr_interface::ue_cfg_t& ue_cfg_,
|
||||
tti_point prach_tti_rx,
|
||||
uint32_t preamble_idx);
|
||||
|
||||
int update(const sched_nr_cc_output_res_t& cc_out);
|
||||
|
||||
const sim_nr_ue_ctxt_t& get_ctxt() const { return ctxt; }
|
||||
sim_nr_ue_ctxt_t& get_ctxt() { return ctxt; }
|
||||
|
||||
private:
|
||||
void update_dl_harqs(const sched_nr_cc_output_res_t& sf_out);
|
||||
|
||||
srslog::basic_logger& logger;
|
||||
sim_nr_ue_ctxt_t ctxt;
|
||||
};
|
||||
|
||||
class sched_nr_sim_base
|
||||
{
|
||||
public:
|
||||
sched_nr_sim_base(const sched_nr_interface::sched_cfg_t& sched_args,
|
||||
const std::vector<sched_nr_interface::cell_cfg_t>& cell_params_,
|
||||
std::string test_name);
|
||||
virtual ~sched_nr_sim_base();
|
||||
|
||||
int add_user(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg_, uint32_t preamble_idx);
|
||||
|
||||
void slot_indication(srsran::tti_point tti_rx);
|
||||
void update(sched_nr_cc_output_res_t& cc_out);
|
||||
|
||||
sched_nr_ue_sim& at(uint16_t rnti) { return ue_db.at(rnti); }
|
||||
const sched_nr_ue_sim& at(uint16_t rnti) const { return ue_db.at(rnti); }
|
||||
sched_nr_ue_sim* find_rnti(uint16_t rnti)
|
||||
{
|
||||
auto it = ue_db.find(rnti);
|
||||
return it != ue_db.end() ? &it->second : nullptr;
|
||||
}
|
||||
const sched_nr_ue_sim* find_rnti(uint16_t rnti) const
|
||||
{
|
||||
auto it = ue_db.find(rnti);
|
||||
return it != ue_db.end() ? &it->second : nullptr;
|
||||
}
|
||||
bool user_exists(uint16_t rnti) const { return ue_db.count(rnti) > 0; }
|
||||
const sched_nr_interface::ue_cfg_t* get_user_cfg(uint16_t rnti) const
|
||||
{
|
||||
const sched_nr_ue_sim* ret = find_rnti(rnti);
|
||||
return ret == nullptr ? nullptr : &ret->get_ctxt().ue_cfg;
|
||||
}
|
||||
sched_nr* get_sched() { return sched_ptr.get(); }
|
||||
srsran::const_span<sched_nr_impl::sched_cell_params> get_cell_params() { return cell_params; }
|
||||
tti_point get_tti_rx() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
return current_tti_rx;
|
||||
}
|
||||
|
||||
std::map<uint16_t, sched_nr_ue_sim>::iterator begin() { return ue_db.begin(); }
|
||||
std::map<uint16_t, sched_nr_ue_sim>::iterator end() { return ue_db.end(); }
|
||||
|
||||
// configurable by simulator concrete implementation
|
||||
virtual void set_external_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events) {}
|
||||
|
||||
private:
|
||||
int set_default_tti_events(const sim_nr_ue_ctxt_t& ue_ctxt, ue_tti_events& pending_events);
|
||||
int apply_tti_events(sim_nr_ue_ctxt_t& ue_ctxt, const ue_tti_events& events);
|
||||
|
||||
std::string test_name;
|
||||
srslog::basic_logger& logger;
|
||||
srslog::basic_logger& mac_logger;
|
||||
std::unique_ptr<sched_nr> sched_ptr;
|
||||
std::vector<sched_nr_impl::sched_cell_params> cell_params;
|
||||
|
||||
srsran::tti_point current_tti_rx;
|
||||
std::map<uint16_t, sched_nr_ue_sim> ue_db;
|
||||
int error_counter = 0;
|
||||
|
||||
mutable std::mutex mutex;
|
||||
std::condition_variable cond_var;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_SIM_UE_H
|
Loading…
Reference in New Issue