mirror of https://github.com/PentHertz/srsLTE.git
sched,optimization,refactor - use of custom formatter that avoids mallocs for getting bitmasks strings in hex and binary formats
This commit is contained in:
parent
a03c78a777
commit
d77b6e1d9c
|
@ -14,6 +14,7 @@
|
|||
#define SRSLTE_DYN_BITSET_H
|
||||
|
||||
#include "adt_utils.h"
|
||||
#include "srslte/srslog/bundled/fmt/format.h"
|
||||
#include <cstdint>
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
|
@ -219,24 +220,25 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
template <typename OutputIt>
|
||||
OutputIt to_string(OutputIt&& mem_buffer) const
|
||||
{
|
||||
if (size() == 0) {
|
||||
return mem_buffer;
|
||||
}
|
||||
|
||||
std::string s;
|
||||
s.assign(size(), '0');
|
||||
if (not reversed) {
|
||||
for (size_t i = size(); i > 0; --i) {
|
||||
if (test(i - 1)) {
|
||||
s[size() - i] = '1';
|
||||
}
|
||||
fmt::format_to(mem_buffer, "{}", test(i - 1) ? '1' : '0');
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < size(); ++i) {
|
||||
if (test(i)) {
|
||||
s[i] = '1';
|
||||
}
|
||||
fmt::format_to(mem_buffer, "{}", test(i) ? '1' : '0');
|
||||
}
|
||||
}
|
||||
return s;
|
||||
return mem_buffer;
|
||||
}
|
||||
|
||||
uint64_t to_uint64() const
|
||||
|
@ -248,19 +250,21 @@ public:
|
|||
return get_word_(0);
|
||||
}
|
||||
|
||||
std::string to_hex() const noexcept
|
||||
template <typename OutputIt>
|
||||
OutputIt to_hex(OutputIt&& mem_buffer) const noexcept
|
||||
{
|
||||
size_t nof_digits = (size() - 1) / 4 + 1;
|
||||
char cstr[ceil_div(ceil_div(N, bits_per_word) * bits_per_word, 4) + 1];
|
||||
size_t count = 0;
|
||||
|
||||
for (int i = nof_words_() - 1; i >= 0; --i) {
|
||||
count += sprintf(&cstr[count], "%016" PRIx64, buffer[i]);
|
||||
if (size() == 0) {
|
||||
return mem_buffer;
|
||||
}
|
||||
|
||||
size_t skip = nof_words_() * bits_per_word / 4 - nof_digits;
|
||||
// printf("bitstring: %s\n", to_string().c_str());
|
||||
return std::string(&cstr[skip], &cstr[nof_digits + skip + 1]);
|
||||
// first word may not print 16 hex digits
|
||||
int i = nof_words_() - 1;
|
||||
size_t rem_symbols = ceil_div((size() - (size() / bits_per_word) * bits_per_word), 4U);
|
||||
fmt::format_to(mem_buffer, "{:0>{}x}", buffer[i], rem_symbols);
|
||||
// remaining words will occupy 16 hex digits
|
||||
for (--i; i >= 0; --i) {
|
||||
fmt::format_to(mem_buffer, "{:0>16x}", buffer[i]);
|
||||
}
|
||||
return mem_buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -318,7 +322,7 @@ private:
|
|||
|
||||
template <size_t N, bool reversed>
|
||||
inline bounded_bitset<N, reversed> operator&(const bounded_bitset<N, reversed>& lhs,
|
||||
const bounded_bitset<N, reversed>& rhs)noexcept
|
||||
const bounded_bitset<N, reversed>& rhs) noexcept
|
||||
{
|
||||
bounded_bitset<N, reversed> res(lhs);
|
||||
res &= rhs;
|
||||
|
@ -348,4 +352,34 @@ inline bounded_bitset<N, reversed> fliplr(const bounded_bitset<N, reversed>& oth
|
|||
|
||||
} // namespace srslte
|
||||
|
||||
/// Custom formatter for bounded_bitset<N, reversed>
|
||||
template <size_t N, bool reversed>
|
||||
struct fmt::formatter<srslte::bounded_bitset<N, reversed> > {
|
||||
enum { hexadecimal, binary } mode = binary;
|
||||
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin())
|
||||
{
|
||||
auto it = ctx.begin();
|
||||
while (*it != '\0' and *it != '}') {
|
||||
if (*it == 'x') {
|
||||
mode = hexadecimal;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const srslte::bounded_bitset<N, reversed>& s, FormatContext& ctx)
|
||||
-> decltype(std::declval<FormatContext>().out())
|
||||
{
|
||||
if (mode == hexadecimal) {
|
||||
return s.template to_hex(ctx.out());
|
||||
}
|
||||
return s.template to_string(ctx.out());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SRSLTE_DYN_BITSET_H
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
using size_type = std::size_t;
|
||||
using value_type = T;
|
||||
|
||||
bounded_vector() = default;
|
||||
template <typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0>
|
||||
|
|
|
@ -95,7 +95,7 @@ int test_bitset_bitwise_oper()
|
|||
try {
|
||||
mask2 |= mask;
|
||||
} catch (srslte::bad_type_access& c) {
|
||||
printf("Received exception \"%s\"\n", c.what());
|
||||
printf("Received exception \"%s\" as expected\n", c.what());
|
||||
caught = true;
|
||||
}
|
||||
TESTASSERT(caught);
|
||||
|
@ -104,11 +104,46 @@ int test_bitset_bitwise_oper()
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int test_bitset_print()
|
||||
{
|
||||
{
|
||||
srslte::bounded_bitset<100> bitset(100);
|
||||
bitset.set(0);
|
||||
bitset.set(5);
|
||||
|
||||
TESTASSERT(fmt::format("{:x}", bitset) == "0000000000000000000000021");
|
||||
TESTASSERT(fmt::format("{:b}", bitset) ==
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100001");
|
||||
|
||||
bitset.set(99);
|
||||
TESTASSERT(fmt::format("{:x}", bitset) == "8000000000000000000000021");
|
||||
TESTASSERT(fmt::format("{:b}", bitset) ==
|
||||
"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100001");
|
||||
}
|
||||
|
||||
{
|
||||
srslte::bounded_bitset<100> bitset(25);
|
||||
bitset.set(0);
|
||||
bitset.set(4);
|
||||
|
||||
TESTASSERT(fmt::format("{:x}", bitset) == "0000011");
|
||||
TESTASSERT(fmt::format("{:b}", bitset) == "0000000000000000000010001");
|
||||
|
||||
bitset.set(24);
|
||||
TESTASSERT(fmt::format("{:x}", bitset) == "1000011");
|
||||
TESTASSERT(fmt::format("{:b}", bitset) == "1000000000000000000010001");
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TESTASSERT(test_zero_bitset() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_ones_bitset() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_bitset_set() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_bitset_bitwise_oper() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_bitset_print() == SRSLTE_SUCCESS);
|
||||
printf("Success\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
pdcch_mask_t total_mask; ///< Accumulation of all PDCCH masks for the current solution (tree route)
|
||||
prbmask_t total_pucch_mask; ///< Accumulation of all PUCCH masks for the current solution/tree route
|
||||
};
|
||||
using alloc_result_t = std::vector<const alloc_t*>;
|
||||
using alloc_result_t = srslte::bounded_vector<const alloc_t*, 16>;
|
||||
|
||||
sf_cch_allocator() : logger(srslog::fetch_basic_logger("MAC")) {}
|
||||
|
||||
|
|
|
@ -156,9 +156,9 @@ void sf_grid_t::new_tti(tti_point tti_rx_)
|
|||
prbmask_t prach_mask{cc_cfg->nof_prb()};
|
||||
prach_mask.fill(cc_cfg->cfg.prach_freq_offset, cc_cfg->cfg.prach_freq_offset + 6);
|
||||
reserve_ul_prbs(prach_mask, false); // TODO: set to true once test sib.conf files are updated
|
||||
logger.debug("SCHED: Allocated PRACH RBs for tti_tx_ul=%d. Mask: 0x%s",
|
||||
to_tx_ul(tti_rx).to_uint(),
|
||||
prach_mask.to_hex().c_str());
|
||||
fmt::memory_buffer buffer;
|
||||
prach_mask.to_hex(buffer);
|
||||
logger.debug("SCHED: Allocated PRACH RBs for tti_tx_ul=%d. Mask: 0x%s", to_tx_ul(tti_rx).to_uint(), buffer.data());
|
||||
}
|
||||
|
||||
// internal state
|
||||
|
@ -281,9 +281,12 @@ alloc_outcome_t sf_grid_t::reserve_ul_prbs(const prbmask_t& prbmask, bool strict
|
|||
{
|
||||
alloc_outcome_t ret = alloc_outcome_t::SUCCESS;
|
||||
if (strict and (ul_mask & prbmask).any()) {
|
||||
fmt::memory_buffer ulmask_buffer, prbmask_buffer;
|
||||
ul_mask.to_hex(ulmask_buffer);
|
||||
prbmask.to_hex(prbmask_buffer);
|
||||
logger.error("There was a collision in UL channel. current mask=0x%s, new alloc mask=0x%s",
|
||||
ul_mask.to_hex().c_str(),
|
||||
prbmask.to_hex().c_str());
|
||||
ulmask_buffer.data(),
|
||||
prbmask_buffer.data());
|
||||
ret = alloc_outcome_t::ERROR;
|
||||
}
|
||||
ul_mask |= prbmask;
|
||||
|
@ -826,23 +829,27 @@ void sf_sched::set_dl_data_sched_result(const sf_cch_allocator::alloc_result_t&
|
|||
data_alloc.pid, data, get_tti_tx_dl(), cc_cfg->enb_cc_idx, tti_alloc.get_cfi(), data_alloc.user_mask);
|
||||
|
||||
if (tbs <= 0) {
|
||||
fmt::memory_buffer buffer;
|
||||
data_alloc.user_mask.to_hex(buffer);
|
||||
logger.warning("SCHED: DL %s failed rnti=0x%x, pid=%d, mask=%s, tbs=%d, buffer=%d",
|
||||
is_newtx ? "tx" : "retx",
|
||||
user->get_rnti(),
|
||||
data_alloc.pid,
|
||||
data_alloc.user_mask.to_hex().c_str(),
|
||||
buffer.data(),
|
||||
tbs,
|
||||
user->get_requested_dl_bytes(cc_cfg->enb_cc_idx).stop());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Print Resulting DL Allocation
|
||||
logger.info("SCHED: DL %s rnti=0x%x, cc=%d, pid=%d, mask=0x%s, dci=(%d,%d), n_rtx=%d, tbs=%d, buffer=%d/%d",
|
||||
fmt::memory_buffer buffer;
|
||||
data_alloc.user_mask.to_hex(buffer);
|
||||
logger.info("SCHED: DL %s rnti=0x%x, cc=%d, pid=%d, mask=%s, dci=(%d,%d), n_rtx=%d, tbs=%d, buffer=%d/%d",
|
||||
!is_newtx ? "retx" : "tx",
|
||||
user->get_rnti(),
|
||||
cc_cfg->enb_cc_idx,
|
||||
data_alloc.pid,
|
||||
data_alloc.user_mask.to_hex().c_str(),
|
||||
buffer.data(),
|
||||
data->dci.location.L,
|
||||
data->dci.location.ncce,
|
||||
dl_harq.nof_retx(0) + dl_harq.nof_retx(1),
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#include "srslte/srslog/bundled/fmt/format.h"
|
||||
#include <array>
|
||||
|
||||
#define Debug(fmt, ...) srslog::fetch_basic_logger("MAC").debug(fmt, ##__VA_ARGS__)
|
||||
#define Info(fmt, ...) srslog::fetch_basic_logger("MAC").info(fmt, ##__VA_ARGS__)
|
||||
#define Warning(fmt, ...) srslog::fetch_basic_logger("MAC").warning(fmt, ##__VA_ARGS__)
|
||||
#define Error(fmt, ...) srslog::fetch_basic_logger("MAC").error(fmt, ##__VA_ARGS__)
|
||||
#define Debug(fmt, ...) get_mac_logger().debug(fmt, ##__VA_ARGS__)
|
||||
#define Info(fmt, ...) get_mac_logger().info(fmt, ##__VA_ARGS__)
|
||||
#define Warning(fmt, ...) get_mac_logger().warning(fmt, ##__VA_ARGS__)
|
||||
#define Error(fmt, ...) get_mac_logger().error(fmt, ##__VA_ARGS__)
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
|
@ -26,6 +26,12 @@ using dl_sched_res_t = sched_interface::dl_sched_res_t;
|
|||
using dl_sched_data_t = sched_interface::dl_sched_data_t;
|
||||
using custom_mem_buffer = fmt::basic_memory_buffer<char, 1024>;
|
||||
|
||||
srslog::basic_logger& get_mac_logger()
|
||||
{
|
||||
static srslog::basic_logger& mac_logger = srslog::fetch_basic_logger("MAC");
|
||||
return mac_logger;
|
||||
}
|
||||
|
||||
const char* to_string_short(srslte_dci_format_t dcifmt)
|
||||
{
|
||||
switch (dcifmt) {
|
||||
|
|
|
@ -307,15 +307,15 @@ std::string sf_cch_allocator::alloc_tree_t::result_to_string(bool verbose) const
|
|||
pdcch_mask_t tot_mask;
|
||||
get_allocs(&vec, &tot_mask, i - prev_start);
|
||||
|
||||
fmt::format_to(strbuf, "[{}]: total mask=0x{}", count, tot_mask.to_hex().c_str());
|
||||
fmt::format_to(strbuf, "[{}]: total mask=0x{:x}", count, tot_mask);
|
||||
if (verbose) {
|
||||
fmt::format_to(strbuf, ", allocations:\n");
|
||||
for (const auto& dci_alloc : vec) {
|
||||
fmt::format_to(strbuf,
|
||||
" > rnti=0x{:0x}: 0x{} / 0x{}\n",
|
||||
" > rnti=0x{:0x}: 0x{:x} / 0x{:x}\n",
|
||||
dci_alloc->rnti,
|
||||
dci_alloc->current_mask.to_hex().c_str(),
|
||||
dci_alloc->total_mask.to_hex().c_str());
|
||||
dci_alloc->current_mask,
|
||||
dci_alloc->total_mask);
|
||||
}
|
||||
} else {
|
||||
fmt::format_to(strbuf, "\n");
|
||||
|
|
|
@ -32,7 +32,7 @@ int test_pusch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co
|
|||
TESTERROR("Collision Detected of %s alloc=%s and cumulative_mask=0x%s",
|
||||
ch_str,
|
||||
alloc.to_string().c_str(),
|
||||
ul_allocs.to_hex().c_str());
|
||||
fmt::format("{:x}", ul_allocs).c_str());
|
||||
}
|
||||
ul_allocs.fill(alloc.start(), alloc.stop(), true);
|
||||
return SRSLTE_SUCCESS;
|
||||
|
@ -64,8 +64,8 @@ int test_pusch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co
|
|||
|
||||
CONDERROR(expected_ul_mask != nullptr and *expected_ul_mask != ul_allocs,
|
||||
"The derived UL PRB mask %s does not match the expected one %s",
|
||||
ul_allocs.to_string().c_str(),
|
||||
expected_ul_mask->to_string().c_str());
|
||||
fmt::format("{}", ul_allocs).c_str(),
|
||||
fmt::format("{}", *expected_ul_mask).c_str());
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
@ -105,8 +105,8 @@ int test_pdsch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co
|
|||
if ((dl_allocs & alloc_mask).any()) {
|
||||
TESTERROR("Detected collision in the DL %s allocation (%s intersects %s)",
|
||||
channel,
|
||||
dl_allocs.to_string().c_str(),
|
||||
alloc_mask.to_string().c_str());
|
||||
fmt::format("{}", dl_allocs).c_str(),
|
||||
fmt::format("{}", alloc_mask).c_str());
|
||||
}
|
||||
dl_allocs |= alloc_mask;
|
||||
return SRSLTE_SUCCESS;
|
||||
|
@ -150,8 +150,8 @@ int test_pdsch_collisions(const sf_output_res_t& sf_out, uint32_t enb_cc_idx, co
|
|||
|
||||
CONDERROR(expected_rbgmask != nullptr and *expected_rbgmask != rbgmask,
|
||||
"The derived DL RBG mask %s does not match the expected one %s",
|
||||
rbgmask.to_string().c_str(),
|
||||
expected_rbgmask->to_string().c_str());
|
||||
fmt::format("{}", rbgmask).c_str(),
|
||||
fmt::format("{}", *expected_rbgmask).c_str());
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
@ -246,8 +246,8 @@ int test_pdcch_collisions(const sf_output_res_t& sf_out,
|
|||
|
||||
CONDERROR(expected_cce_mask != nullptr and *expected_cce_mask != used_cce,
|
||||
"The derived PDCCH mask %s does not match the expected one %s",
|
||||
used_cce.to_string().c_str(),
|
||||
expected_cce_mask->to_string().c_str());
|
||||
fmt::format("{}", used_cce).c_str(),
|
||||
fmt::format("{}", *expected_cce_mask).c_str());
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue