sched,nr: extended sched nr DL output to account for RAR content and assist with RAR encoding in the mac_nr class

master
Francisco Paisana 3 years ago
parent b486d2a1b5
commit 05a5f4115f

@ -81,6 +81,9 @@ private:
// PDU processing
int handle_pdu(srsran::unique_byte_buffer_t pdu);
// Encoding
srsran::byte_buffer_t* assemble_rar(srsran::const_span<sched_nr_interface::sched_rar_grant_t> grants);
// Interaction with other components
phy_interface_stack_nr* phy = nullptr;
stack_interface_mac* stack = nullptr;

@ -47,7 +47,7 @@ public:
void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) override;
void ul_sr_info(slot_point slot_rx, uint16_t rnti) override;
int get_dl_sched(slot_point pdsch_tti, uint32_t cc, dl_sched_t& result) override;
int get_dl_sched(slot_point pdsch_tti, uint32_t cc, dl_sched_res_t& result) override;
int get_ul_sched(slot_point pusch_tti, uint32_t cc, ul_sched_t& result) override;
private:

@ -32,6 +32,7 @@ using slot_coreset_list = std::array<srsran::optional<coreset_re
using pdsch_t = mac_interface_phy_nr::pdsch_t;
using pdsch_list_t = srsran::bounded_vector<pdsch_t, MAX_GRANTS>;
using rar_list_t = sched_nr_interface::sched_rar_list_t;
struct harq_ack_t {
const srsran::phy_cfg_nr_t* phy_cfg;
@ -48,6 +49,7 @@ struct bwp_slot_grid {
pdcch_dl_list_t dl_pdcchs;
pdcch_ul_list_t ul_pdcchs;
pdsch_list_t pdschs;
rar_list_t rar;
slot_coreset_list coresets;
pusch_list_t puschs;
harq_ack_list_t pending_acks;

@ -100,11 +100,24 @@ public:
using dl_sched_t = mac_interface_phy_nr::dl_sched_t;
using ul_sched_t = mac_interface_phy_nr::ul_sched_t;
virtual ~sched_nr_interface() = default;
virtual int cell_cfg(srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_t& result) = 0;
virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0;
struct sched_rar_grant_t {
dl_sched_rar_info_t data;
srsran_dci_rar_grant_t grant = {};
};
struct sched_rar_t {
srsran::bounded_vector<sched_rar_grant_t, MAX_GRANTS> grants;
};
using sched_rar_list_t = srsran::bounded_vector<sched_rar_t, MAX_GRANTS>;
struct dl_sched_res_t {
sched_rar_list_t rar;
dl_sched_t dl_sched;
};
virtual ~sched_nr_interface() = default;
virtual int cell_cfg(srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
virtual int get_dl_sched(slot_point slot_rx, uint32_t cc, dl_sched_res_t& result) = 0;
virtual int get_ul_sched(slot_point slot_rx, uint32_t cc, ul_sched_t& result) = 0;
virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0;
virtual void ul_crc_info(uint16_t rnti, uint32_t cc, uint32_t pid, bool crc) = 0;

@ -27,8 +27,9 @@
namespace srsenb {
namespace sched_nr_impl {
using dl_sched_t = sched_nr_interface::dl_sched_t;
using ul_sched_t = sched_nr_interface::ul_sched_t;
using dl_sched_t = sched_nr_interface::dl_sched_t;
using ul_sched_t = sched_nr_interface::ul_sched_t;
using dl_sched_res_t = sched_nr_interface::dl_sched_res_t;
class slot_cc_worker
{
@ -92,7 +93,7 @@ public:
sched_worker_manager(sched_worker_manager&&) = delete;
~sched_worker_manager();
void run_slot(slot_point slot_tx, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res);
void run_slot(slot_point slot_tx, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res);
void enqueue_event(uint16_t rnti, srsran::move_callback<void()> ev);
void enqueue_cc_event(uint32_t cc, srsran::move_callback<void()> ev);
@ -102,7 +103,7 @@ public:
}
private:
bool save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res);
bool save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res);
const sched_params& cfg;
ue_map_t& ue_db;

@ -265,23 +265,35 @@ int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched
pdsch_slot++;
}
int ret = sched.get_dl_sched(pdsch_slot, 0, dl_sched);
for (pdsch_t& pdsch : dl_sched.pdsch) {
for (auto& tb_data : pdsch.data) {
if (tb_data != nullptr) {
// TODO: exclude retx from packing
uint16_t rnti = pdsch.sch.grant.rnti;
srsran::rwlock_read_guard rw_lock(rwlock);
if (not is_rnti_active_unsafe(rnti)) {
continue;
}
ue_db[rnti]->generate_pdu(tb_data, pdsch.sch.grant.tb->tbs / 8);
sched_nr_interface::dl_sched_res_t dl_res;
int ret = sched.get_dl_sched(pdsch_slot, 0, dl_res);
if (ret != SRSRAN_SUCCESS) {
return ret;
}
dl_sched = dl_res.dl_sched;
if (pcap != nullptr) {
uint32_t pid = 0; // TODO: get PID from PDCCH struct?
pcap->write_dl_crnti_nr(tb_data->msg, tb_data->N_bytes, rnti, pid, slot_cfg.idx);
uint32_t rar_count = 0;
srsran::rwlock_read_guard rw_lock(rwlock);
for (pdsch_t& pdsch : dl_sched.pdsch) {
if (pdsch.sch.grant.rnti_type == srsran_rnti_type_c) {
uint16_t rnti = pdsch.sch.grant.rnti;
if (not is_rnti_active_unsafe(rnti)) {
continue;
}
for (auto& tb_data : pdsch.data) {
if (tb_data != nullptr) {
// TODO: exclude retx from packing
ue_db[rnti]->generate_pdu(tb_data, pdsch.sch.grant.tb->tbs / 8);
if (pcap != nullptr) {
uint32_t pid = 0; // TODO: get PID from PDCCH struct?
pcap->write_dl_crnti_nr(tb_data->msg, tb_data->N_bytes, rnti, pid, slot_cfg.idx);
}
}
}
} else if (pdsch.sch.grant.rnti_type == srsran_rnti_type_ra) {
sched_nr_interface::sched_rar_t& rar = dl_res.rar[rar_count++];
pdsch.data[0] = assemble_rar(rar.grants);
}
}
return SRSRAN_SUCCESS;
@ -307,11 +319,11 @@ int mac_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_ph
return SRSRAN_SUCCESS;
}
bool mac_nr::handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value)
bool mac_nr::handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg_, const srsran_uci_value_nr_t& value)
{
// Process HARQ-ACK
for (uint32_t i = 0; i < cfg.ack.count; i++) {
const srsran_harq_ack_bit_t* ack_bit = &cfg.ack.bits[i];
for (uint32_t i = 0; i < cfg_.ack.count; i++) {
const srsran_harq_ack_bit_t* ack_bit = &cfg_.ack.bits[i];
bool is_ok = (value.ack[i] == 1) and value.valid;
sched.dl_ack_info(rnti, 0, ack_bit->pid, 0, is_ok);
}
@ -351,4 +363,9 @@ int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr::
return SRSRAN_SUCCESS;
}
srsran::byte_buffer_t* mac_nr::assemble_rar(srsran::const_span<sched_nr_interface::sched_rar_grant_t> grants)
{
return nullptr;
}
} // namespace srsenb

@ -34,7 +34,7 @@ public:
}
}
dl_sched_t& add_dl_result(slot_point tti, uint32_t cc)
dl_sched_res_t& add_dl_result(slot_point tti, uint32_t cc)
{
if (not has_dl_result(tti, cc)) {
results[tti.to_uint()][cc].slot_dl = tti;
@ -55,7 +55,7 @@ public:
bool has_ul_result(slot_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].slot_ul == tti; }
dl_sched_t pop_dl_result(slot_point tti, uint32_t cc)
dl_sched_res_t pop_dl_result(slot_point tti, uint32_t cc)
{
if (has_dl_result(tti, cc)) {
results[tti.to_uint()][cc].slot_dl.clear();
@ -75,10 +75,10 @@ public:
private:
struct slot_result_t {
slot_point slot_dl;
slot_point slot_ul;
dl_sched_t dl_res;
ul_sched_t ul_res;
slot_point slot_dl;
slot_point slot_ul;
dl_sched_res_t dl_res;
ul_sched_t ul_res;
};
srsran::circular_array<std::vector<slot_result_t>, TTIMOD_SZ> results;
@ -129,8 +129,8 @@ void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg)
int sched_nr::generate_slot_result(slot_point pdcch_tti, uint32_t cc)
{
// Copy results to intermediate buffer
dl_sched_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc);
ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc);
dl_sched_res_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc);
ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc);
// Generate {slot_idx,cc} result
sched_workers->run_slot(pdcch_tti, cc, dl_res, ul_res);
@ -138,7 +138,7 @@ int sched_nr::generate_slot_result(slot_point pdcch_tti, uint32_t cc)
return SRSRAN_SUCCESS;
}
int sched_nr::get_dl_sched(slot_point slot_tx, uint32_t cc, dl_sched_t& result)
int sched_nr::get_dl_sched(slot_point slot_tx, uint32_t cc, dl_sched_res_t& result)
{
if (not pending_results->has_dl_result(slot_tx, cc)) {
generate_slot_result(slot_tx, cc);

@ -153,6 +153,8 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
const int mcs = 0, max_harq_msg3_retx = 4;
int dai = 0;
slot_cfg.idx = msg3_slot.slot_idx();
bwp_pdcch_slot.rar.emplace_back();
sched_nr_interface::sched_rar_t& rar_out = bwp_pdcch_slot.rar.back();
for (const dl_sched_rar_info_t& grant : pending_rars) {
slot_ue& ue = (*slot_ues)[grant.temp_crnti];
@ -166,6 +168,13 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t
fill_dci_msg3(ue, *bwp_grid.cfg, msg3_pdcch.dci);
msg3_pdcch.dci.time_domain_assigment = dai++;
// Generate RAR grant
rar_out.grants.emplace_back();
auto& rar_grant = rar_out.grants.back();
rar_grant.data = grant;
rar_grant.grant.rba = msg3_pdcch.dci.freq_domain_assigment;
rar_grant.grant.trunc_mcs = msg3_pdcch.dci.mcs;
// Generate PUSCH
bwp_msg3_slot.puschs.emplace_back();
pusch_t& pusch = bwp_msg3_slot.puschs.back();

@ -117,13 +117,14 @@ void log_sched_bwp_result(srslog::basic_logger& logger,
const bwp_res_grid& res_grid,
const slot_ue_map_t& slot_ues)
{
const bwp_slot_grid& bwp_slot = res_grid[pdcch_slot];
const bwp_slot_grid& bwp_slot = res_grid[pdcch_slot];
size_t rar_count = 0;
for (const pdcch_dl_t& pdcch : bwp_slot.dl_pdcchs) {
fmt::memory_buffer fmtbuf;
if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) {
const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti];
fmt::format_to(fmtbuf,
"SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, grant={}, nrtx={}, dai={}, tbs={}, "
"SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, f={}, prbs={}, nrtx={}, dai={}, tbs={}, "
"pdsch_slot={}, tti_ack={}",
ue.h_dl->nof_retx() == 0 ? "tx" : "retx",
res_grid.cfg->cc,
@ -137,17 +138,19 @@ void log_sched_bwp_result(srslog::basic_logger& logger,
ue.pdsch_slot,
ue.uci_slot);
} else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) {
const pdsch_t& pdsch = bwp_slot.pdschs[std::distance(bwp_slot.dl_pdcchs.data(), &pdcch)];
const pdsch_t& pdsch = bwp_slot.pdschs[std::distance(bwp_slot.dl_pdcchs.data(), &pdcch)];
srsran::const_span<bool> prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + pdsch.sch.grant.nof_prb};
uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true));
uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true));
uint32_t end_idx = std::distance(prbs.begin(), std::find(prbs.begin() + start_idx, prbs.end(), false));
fmt::format_to(fmtbuf,
"SCHED: DL RAR, cc={}, ra-rnti=0x{:x}, grant={}, pdsch_slot={}, msg3_slot={}",
"SCHED: DL RAR, cc={}, ra-rnti=0x{:x}, prbs={}, pdsch_slot={}, msg3_slot={}, nof_grants={}",
res_grid.cfg->cc,
pdcch.dci.ctx.rnti,
srsran::interval<uint32_t>{start_idx, end_idx},
pdcch_slot,
pdcch_slot + res_grid.cfg->pusch_ra_list[0].msg3_delay);
pdcch_slot + res_grid.cfg->pusch_ra_list[0].msg3_delay,
bwp_slot.rar[rar_count].grants.size());
rar_count++;
} else {
fmt::format_to(fmtbuf, "SCHED: unknown format");
}

@ -155,7 +155,7 @@ void sched_worker_manager::enqueue_cc_event(uint32_t cc, srsran::move_callback<v
cc_worker_list[cc]->worker.enqueue_cc_event(std::move(ev));
}
void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res)
void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_res_t& dl_res, ul_sched_t& ul_res)
{
srsran::bounded_vector<std::condition_variable*, SRSRAN_MAX_CARRIERS> waiting_cvars;
{
@ -238,19 +238,23 @@ void sched_worker_manager::run_slot(slot_point slot_tx, uint32_t cc, dl_sched_t&
}
}
// Copy results to intermediate buffer
// Post-process and copy results to intermediate buffer
save_sched_result(slot_tx, cc, dl_res, ul_res);
}
bool sched_worker_manager::save_sched_result(slot_point pdcch_slot, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res)
bool sched_worker_manager::save_sched_result(slot_point pdcch_slot,
uint32_t cc,
dl_sched_res_t& dl_res,
ul_sched_t& ul_res)
{
// NOTE: Unlocked region
auto& bwp_slot = cells[cc]->bwps[0].grid[pdcch_slot];
dl_res.pdcch_dl = bwp_slot.dl_pdcchs;
dl_res.pdcch_ul = bwp_slot.ul_pdcchs;
dl_res.pdsch = bwp_slot.pdschs;
ul_res.pusch = bwp_slot.puschs;
dl_res.dl_sched.pdcch_dl = bwp_slot.dl_pdcchs;
dl_res.dl_sched.pdcch_ul = bwp_slot.ul_pdcchs;
dl_res.dl_sched.pdsch = bwp_slot.pdschs;
dl_res.rar = bwp_slot.rar;
ul_res.pusch = bwp_slot.puschs;
// Group pending HARQ ACKs
srsran_pdsch_ack_nr_t ack = {};

@ -41,8 +41,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out)
{
update_dl_harqs(cc_out);
for (uint32_t i = 0; i < cc_out.dl_cc_result->pdcch_dl.size(); ++i) {
const auto& data = cc_out.dl_cc_result->pdcch_dl[i];
for (uint32_t i = 0; i < cc_out.dl_cc_result->dl_sched.pdcch_dl.size(); ++i) {
const auto& data = cc_out.dl_cc_result->dl_sched.pdcch_dl[i];
if (data.dci.ctx.rnti != ctxt.rnti) {
continue;
}
@ -63,8 +63,8 @@ int sched_nr_ue_sim::update(const sched_nr_cc_output_res_t& cc_out)
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->pdcch_dl.size(); ++i) {
const auto& data = cc_out.dl_cc_result->pdcch_dl[i];
for (uint32_t i = 0; i < cc_out.dl_cc_result->dl_sched.pdcch_dl.size(); ++i) {
const auto& data = cc_out.dl_cc_result->dl_sched.pdcch_dl[i];
if (data.dci.ctx.rnti != ctxt.rnti) {
continue;
}
@ -160,8 +160,8 @@ void sched_nr_sim_base::update(sched_nr_cc_output_res_t& cc_out)
ctxt = get_enb_ctxt();
// Run common tests
test_dl_pdcch_consistency(cc_out.dl_cc_result->pdcch_dl);
test_pdsch_consistency(cc_out.dl_cc_result->pdsch);
test_dl_pdcch_consistency(cc_out.dl_cc_result->dl_sched.pdcch_dl);
test_pdsch_consistency(cc_out.dl_cc_result->dl_sched.pdsch);
// Run UE-dedicated tests
test_dl_sched_result(ctxt, cc_out);

@ -34,10 +34,10 @@ struct ue_nr_harq_ctxt_t {
slot_point last_slot_tx, first_slot_tx, last_slot_ack;
};
struct sched_nr_cc_output_res_t {
slot_point slot;
uint32_t cc;
const sched_nr_interface::dl_sched_t* dl_cc_result;
const sched_nr_interface::ul_sched_t* ul_cc_result;
slot_point slot;
uint32_t cc;
const sched_nr_interface::dl_sched_res_t* dl_cc_result;
const sched_nr_interface::ul_sched_t* ul_cc_result;
};
struct ue_nr_cc_ctxt_t {

@ -47,12 +47,14 @@ struct task_job_manager {
}
sl.count = nof_sectors;
}
void finish_cc(slot_point slot, const dl_sched_t& dl_res, const sched_nr_interface::ul_sched_t& ul_res)
void finish_cc(slot_point slot,
const sched_nr_interface::dl_sched_res_t& dl_res,
const sched_nr_interface::ul_sched_t& ul_res)
{
std::unique_lock<std::mutex> lock(mutex);
TESTASSERT(dl_res.pdcch_dl.size() <= 1);
TESTASSERT(dl_res.dl_sched.pdcch_dl.size() <= 1);
res_count++;
pdsch_count += dl_res.pdcch_dl.size();
pdsch_count += dl_res.dl_sched.pdcch_dl.size();
auto& sl = slot_counter[slot.to_uint() % slot_counter.size()];
if (--sl.count == 0) {
sl.cvar.notify_one();
@ -97,9 +99,9 @@ void sched_nr_cfg_serialized_test()
tasks.start_slot(slot_rx, nof_sectors);
sched_tester.new_slot(slot_tx);
for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) {
sched_nr_interface::dl_sched_t dl_res;
sched_nr_interface::ul_sched_t ul_res;
auto tp1 = std::chrono::steady_clock::now();
sched_nr_interface::dl_sched_res_t dl_res;
sched_nr_interface::ul_sched_t ul_res;
auto tp1 = std::chrono::steady_clock::now();
TESTASSERT(sched_tester.get_sched()->get_dl_sched(slot_tx, cc, dl_res) == SRSRAN_SUCCESS);
TESTASSERT(sched_tester.get_sched()->get_ul_sched(slot_tx, cc, ul_res) == SRSRAN_SUCCESS);
auto tp2 = std::chrono::steady_clock::now();
@ -107,7 +109,8 @@ void sched_nr_cfg_serialized_test()
sched_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res};
sched_tester.update(out);
tasks.finish_cc(slot_rx, dl_res, ul_res);
TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or dl_res.pdcch_dl.size() == 1);
TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or
dl_res.dl_sched.pdcch_dl.size() == 1);
}
}
@ -146,9 +149,9 @@ void sched_nr_cfg_parallel_cc_test()
sched_tester.new_slot(slot_tx);
for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) {
srsran::get_background_workers().push_task([cc, slot_tx, &tasks, &sched_tester, &nano_count]() {
sched_nr_interface::dl_sched_t dl_res;
sched_nr_interface::ul_sched_t ul_res;
auto tp1 = std::chrono::steady_clock::now();
sched_nr_interface::dl_sched_res_t dl_res;
sched_nr_interface::ul_sched_t ul_res;
auto tp1 = std::chrono::steady_clock::now();
TESTASSERT(sched_tester.get_sched()->get_dl_sched(slot_tx, cc, dl_res) == SRSRAN_SUCCESS);
TESTASSERT(sched_tester.get_sched()->get_ul_sched(slot_tx, cc, ul_res) == SRSRAN_SUCCESS);
auto tp2 = std::chrono::steady_clock::now();

@ -21,7 +21,7 @@ using namespace srsenb::sched_nr_impl;
void test_dl_sched_result(const sim_nr_enb_ctxt_t& enb_ctxt, const sched_nr_cc_output_res_t& cc_out)
{
slot_point pdcch_slot = cc_out.slot;
const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->pdcch_dl;
const pdcch_dl_list_t& pdcchs = cc_out.dl_cc_result->dl_sched.pdcch_dl;
// Iterate over UE PDCCH allocations
for (const pdcch_dl_t& pdcch : pdcchs) {

@ -417,7 +417,9 @@ public:
}
if (not use_dummy_sched) {
int ret = sched->get_dl_sched(pdsch_slot, 0, dl_sched);
srsenb::sched_nr_interface::dl_sched_res_t dl_res;
int ret = sched->get_dl_sched(pdsch_slot, 0, dl_res);
dl_sched = dl_res.dl_sched;
for (pdsch_t& pdsch : dl_sched.pdsch) {
// Set TBS

Loading…
Cancel
Save