mirror of https://github.com/pvnis/srsRAN_4G.git
nr,gnb,sched: implemented standalone PDSCH allocator class
parent
b2f5f6c620
commit
107e2aa938
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \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_PDSCH_H
|
||||||
|
#define SRSRAN_SCHED_NR_PDSCH_H
|
||||||
|
|
||||||
|
#include "srsenb/hdr/stack/mac/sched_common.h"
|
||||||
|
#include "srsgnb/hdr/stack/mac/sched_nr_cfg.h"
|
||||||
|
|
||||||
|
namespace srsenb {
|
||||||
|
|
||||||
|
namespace sched_nr_impl {
|
||||||
|
|
||||||
|
class pdsch_allocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
pdsch_allocator(const bwp_params_t& cfg_, uint32_t sl_index, pdsch_list_t& pdsch_lst);
|
||||||
|
|
||||||
|
/// Get available RBGs for allocation
|
||||||
|
rbg_bitmap available_rbgs(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const
|
||||||
|
{
|
||||||
|
return (dl_prbs | bwp_cfg.coreset_prb_limits(ss_id, dci_fmt)).rbgs();
|
||||||
|
}
|
||||||
|
/// Get available PRBs for allocation
|
||||||
|
prb_bitmap available_prbs(uint32_t ss_id, srsran_dci_format_nr_t dci_fmt) const
|
||||||
|
{
|
||||||
|
return (dl_prbs | bwp_cfg.coreset_prb_limits(ss_id, dci_fmt)).prbs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if provided PDSCH arguments produce a valid PDSCH that fits into cell PRBs and does not collide with other
|
||||||
|
/// allocations
|
||||||
|
alloc_result is_grant_valid(uint32_t ss_id,
|
||||||
|
srsran_dci_format_nr_t dci_fmt,
|
||||||
|
const prb_grant& grant,
|
||||||
|
ue_carrier_params_t* ue = nullptr) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tries to allocate PDSCH grant. Ensures that there are no collisions with other previous PDSCH allocations
|
||||||
|
* @param dci_ctx[in] PDCCH DL DCI context information
|
||||||
|
* @param ss_id[in] SearchSpaceId used for allocation
|
||||||
|
* @param grant[in] PRBs used for the grant
|
||||||
|
* @param pdcch[out] PDCCH where frequency_assignment and time_assignment get stored.
|
||||||
|
* @return pdsch_t object pointer in case of success. alloc_result error code in case of failure
|
||||||
|
*/
|
||||||
|
srsran::expected<pdsch_t*, alloc_result>
|
||||||
|
alloc_pdsch(const srsran_dci_ctx_t& dci_ctx, uint32_t ss_id, const prb_grant& grant, pdcch_dl_t& pdcch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocates PDSCH grant without verifying for collisions. Useful to avoid redundant is_grant_valid(...) calls
|
||||||
|
* @param dci_ctx[in] PDCCH DL DCI context information
|
||||||
|
* @param grant[in] PRBs used for the grant
|
||||||
|
* @param pdcch[out] PDCCH where frequency and time assignment get stored.
|
||||||
|
*/
|
||||||
|
pdsch_t& alloc_pdsch_unchecked(const srsran_dci_ctx_t& dci_ctx, const prb_grant& grant, pdcch_dl_t& pdcch);
|
||||||
|
|
||||||
|
void cancel_last_pdsch();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bwp_params_t& bwp_cfg;
|
||||||
|
uint32_t slot_idx = 0;
|
||||||
|
|
||||||
|
pdsch_list_t& pdschs;
|
||||||
|
bwp_rb_bitmap dl_prbs;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sched_nr_impl
|
||||||
|
|
||||||
|
} // namespace srsenb
|
||||||
|
|
||||||
|
#endif // SRSRAN_SCHED_NR_PDSCH_H
|
@ -0,0 +1,143 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \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 "srsgnb/hdr/stack/mac/sched_nr_pdsch.h"
|
||||||
|
#include "srsran/common/string_helpers.h"
|
||||||
|
|
||||||
|
namespace srsenb {
|
||||||
|
namespace sched_nr_impl {
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void log_alloc_failure(srslog::log_channel& log_ch, uint32_t ss_id, const char* cause_fmt, Args&&... args)
|
||||||
|
{
|
||||||
|
if (not log_ch.enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log allocation failure
|
||||||
|
fmt::memory_buffer fmtbuf;
|
||||||
|
fmt::format_to(fmtbuf, "SCHED: Failure to allocate PDSCH in SS#{}. Cause: ", ss_id);
|
||||||
|
fmt::format_to(fmtbuf, cause_fmt, std::forward<Args>(args)...);
|
||||||
|
log_ch("%s", srsran::to_c_str(fmtbuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
pdsch_allocator::pdsch_allocator(const bwp_params_t& cfg_, uint32_t slot_index, pdsch_list_t& pdsch_lst) :
|
||||||
|
bwp_cfg(cfg_),
|
||||||
|
slot_idx(slot_index),
|
||||||
|
pdschs(pdsch_lst),
|
||||||
|
dl_prbs(bwp_cfg.cfg.rb_width, bwp_cfg.cfg.start_rb, bwp_cfg.cfg.pdsch.rbg_size_cfg_1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void pdsch_allocator::reset()
|
||||||
|
{
|
||||||
|
pdschs.clear();
|
||||||
|
dl_prbs.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc_result pdsch_allocator::is_grant_valid(uint32_t ss_id,
|
||||||
|
srsran_dci_format_nr_t dci_fmt,
|
||||||
|
const prb_grant& grant,
|
||||||
|
ue_carrier_params_t* ue) const
|
||||||
|
{
|
||||||
|
// DL must be active in given slot
|
||||||
|
if (not bwp_cfg.slots[slot_idx].is_dl) {
|
||||||
|
log_alloc_failure(bwp_cfg.logger.error, ss_id, "DL is disabled for slot={}", slot_idx);
|
||||||
|
return alloc_result::no_sch_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No space in Scheduler PDSCH output list
|
||||||
|
if (pdschs.full()) {
|
||||||
|
log_alloc_failure(bwp_cfg.logger.warning, ss_id, "SearchSpace has not been configured.");
|
||||||
|
return alloc_result::no_sch_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify SearchSpace validity
|
||||||
|
const srsran_search_space_t* ss = (ue == nullptr) ? bwp_cfg.get_ss(ss_id) : ue->get_ss(ss_id);
|
||||||
|
if (ss == nullptr) {
|
||||||
|
// Couldn't find SearchSpace
|
||||||
|
log_alloc_failure(bwp_cfg.logger.error, ss_id, "SearchSpace has not been configured.");
|
||||||
|
return alloc_result::invalid_grant_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SRSRAN_SEARCH_SPACE_IS_COMMON(ss_id)) {
|
||||||
|
// In case of common SearchSpaces, the PRBs must be contiguous
|
||||||
|
if (grant.is_alloc_type0()) {
|
||||||
|
log_alloc_failure(bwp_cfg.logger.warning, ss_id, "AllocType0 not allowed in common SearchSpace.");
|
||||||
|
return alloc_result::invalid_grant_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grant PRBs do not collide with CORESET PRB limits (in case of common SearchSpace)
|
||||||
|
if (bwp_cfg.coreset_prb_limits(ss_id, dci_fmt).collides(grant)) {
|
||||||
|
bwp_cfg.logger.debug("SCHED: Provided RBG mask falls outside common CORESET PRB boundaries.");
|
||||||
|
return alloc_result::sch_collision;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grant PRBs do not collide with previous PDSCH allocations
|
||||||
|
if (dl_prbs.collides(grant)) {
|
||||||
|
bwp_cfg.logger.debug("SCHED: Provided RBG mask collides with allocation previously made.");
|
||||||
|
return alloc_result::sch_collision;
|
||||||
|
}
|
||||||
|
|
||||||
|
return alloc_result::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
srsran::expected<pdsch_t*, alloc_result>
|
||||||
|
pdsch_allocator::alloc_pdsch(const srsran_dci_ctx_t& dci_ctx, uint32_t ss_id, const prb_grant& grant, pdcch_dl_t& pdcch)
|
||||||
|
{
|
||||||
|
alloc_result code = is_grant_valid(ss_id, dci_ctx.format, grant);
|
||||||
|
if (code != alloc_result::success) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {&alloc_pdsch_unchecked(dci_ctx, grant, pdcch)};
|
||||||
|
}
|
||||||
|
|
||||||
|
pdsch_t&
|
||||||
|
pdsch_allocator::alloc_pdsch_unchecked(const srsran_dci_ctx_t& dci_ctx, const prb_grant& grant, pdcch_dl_t& pdcch)
|
||||||
|
{
|
||||||
|
// Create new PDSCH entry in output PDSCH list
|
||||||
|
pdschs.emplace_back();
|
||||||
|
pdsch_t& pdsch = pdschs.back();
|
||||||
|
|
||||||
|
// Register allocated PRBs in accumulated bitmap
|
||||||
|
dl_prbs |= grant;
|
||||||
|
|
||||||
|
// Fill DCI with PDSCH freq/time allocation information
|
||||||
|
pdcch.dci.time_domain_assigment = 0;
|
||||||
|
if (grant.is_alloc_type0()) {
|
||||||
|
pdcch.dci.freq_domain_assigment = grant.rbgs().to_uint64();
|
||||||
|
} else {
|
||||||
|
uint32_t rb_start = grant.prbs().start(), nof_prb = bwp_cfg.nof_prb();
|
||||||
|
if (SRSRAN_SEARCH_SPACE_IS_COMMON(dci_ctx.ss_type)) {
|
||||||
|
if (dci_ctx.format == srsran_dci_format_nr_1_0) {
|
||||||
|
rb_start -= dci_ctx.coreset_start_rb;
|
||||||
|
}
|
||||||
|
if (dci_ctx.coreset_id == 0) {
|
||||||
|
nof_prb = bwp_cfg.coreset_bw(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srsran_sanity_check(rb_start + grant.prbs().length() <= nof_prb, "Invalid PRB grant");
|
||||||
|
pdcch.dci.freq_domain_assigment = srsran_ra_nr_type1_riv(nof_prb, rb_start, grant.prbs().length());
|
||||||
|
}
|
||||||
|
|
||||||
|
return pdsch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pdsch_allocator::cancel_last_pdsch()
|
||||||
|
{
|
||||||
|
srsran_assert(not pdschs.empty(), "Trying to abort PDSCH allocation that does not exist");
|
||||||
|
pdschs.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sched_nr_impl
|
||||||
|
} // namespace srsenb
|
Loading…
Reference in New Issue