sched,optimization,refactor - use of custom formatter that avoids mallocs for getting bitmasks strings in hex and binary formats

master
Francisco 4 years ago committed by Francisco Paisana
parent a03c78a777
commit d77b6e1d9c

@ -14,6 +14,7 @@
#define SRSLTE_DYN_BITSET_H #define SRSLTE_DYN_BITSET_H
#include "adt_utils.h" #include "adt_utils.h"
#include "srslte/srslog/bundled/fmt/format.h"
#include <cstdint> #include <cstdint>
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
@ -219,24 +220,25 @@ public:
return ret; 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; std::string s;
s.assign(size(), '0'); s.assign(size(), '0');
if (not reversed) { if (not reversed) {
for (size_t i = size(); i > 0; --i) { for (size_t i = size(); i > 0; --i) {
if (test(i - 1)) { fmt::format_to(mem_buffer, "{}", test(i - 1) ? '1' : '0');
s[size() - i] = '1';
}
} }
} else { } else {
for (size_t i = 0; i < size(); ++i) { for (size_t i = 0; i < size(); ++i) {
if (test(i)) { fmt::format_to(mem_buffer, "{}", test(i) ? '1' : '0');
s[i] = '1';
} }
} }
} return mem_buffer;
return s;
} }
uint64_t to_uint64() const uint64_t to_uint64() const
@ -248,19 +250,21 @@ public:
return get_word_(0); 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; if (size() == 0) {
char cstr[ceil_div(ceil_div(N, bits_per_word) * bits_per_word, 4) + 1]; return mem_buffer;
size_t count = 0;
for (int i = nof_words_() - 1; i >= 0; --i) {
count += sprintf(&cstr[count], "%016" PRIx64, buffer[i]);
} }
// first word may not print 16 hex digits
size_t skip = nof_words_() * bits_per_word / 4 - nof_digits; int i = nof_words_() - 1;
// printf("bitstring: %s\n", to_string().c_str()); size_t rem_symbols = ceil_div((size() - (size() / bits_per_word) * bits_per_word), 4U);
return std::string(&cstr[skip], &cstr[nof_digits + skip + 1]); 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: private:
@ -318,7 +322,7 @@ private:
template <size_t N, bool reversed> template <size_t N, bool reversed>
inline bounded_bitset<N, reversed> operator&(const bounded_bitset<N, reversed>& lhs, 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); bounded_bitset<N, reversed> res(lhs);
res &= rhs; res &= rhs;
@ -348,4 +352,34 @@ inline bounded_bitset<N, reversed> fliplr(const bounded_bitset<N, reversed>& oth
} // namespace srslte } // 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 #endif // SRSLTE_DYN_BITSET_H

@ -27,6 +27,7 @@ public:
using iterator = T*; using iterator = T*;
using const_iterator = const T*; using const_iterator = const T*;
using size_type = std::size_t; using size_type = std::size_t;
using value_type = T;
bounded_vector() = default; bounded_vector() = default;
template <typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0> template <typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0>

@ -95,7 +95,7 @@ int test_bitset_bitwise_oper()
try { try {
mask2 |= mask; mask2 |= mask;
} catch (srslte::bad_type_access& c) { } catch (srslte::bad_type_access& c) {
printf("Received exception \"%s\"\n", c.what()); printf("Received exception \"%s\" as expected\n", c.what());
caught = true; caught = true;
} }
TESTASSERT(caught); TESTASSERT(caught);
@ -104,11 +104,46 @@ int test_bitset_bitwise_oper()
return SRSLTE_SUCCESS; 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() int main()
{ {
TESTASSERT(test_zero_bitset() == SRSLTE_SUCCESS); TESTASSERT(test_zero_bitset() == SRSLTE_SUCCESS);
TESTASSERT(test_ones_bitset() == SRSLTE_SUCCESS); TESTASSERT(test_ones_bitset() == SRSLTE_SUCCESS);
TESTASSERT(test_bitset_set() == SRSLTE_SUCCESS); TESTASSERT(test_bitset_set() == SRSLTE_SUCCESS);
TESTASSERT(test_bitset_bitwise_oper() == SRSLTE_SUCCESS); TESTASSERT(test_bitset_bitwise_oper() == SRSLTE_SUCCESS);
TESTASSERT(test_bitset_print() == SRSLTE_SUCCESS);
printf("Success\n");
return 0; return 0;
} }

@ -32,7 +32,7 @@ public:
pdcch_mask_t total_mask; ///< Accumulation of all PDCCH masks for the current solution (tree route) 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 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")) {} 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()}; prbmask_t prach_mask{cc_cfg->nof_prb()};
prach_mask.fill(cc_cfg->cfg.prach_freq_offset, cc_cfg->cfg.prach_freq_offset + 6); 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 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", fmt::memory_buffer buffer;
to_tx_ul(tti_rx).to_uint(), prach_mask.to_hex(buffer);
prach_mask.to_hex().c_str()); 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 // 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; alloc_outcome_t ret = alloc_outcome_t::SUCCESS;
if (strict and (ul_mask & prbmask).any()) { 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", logger.error("There was a collision in UL channel. current mask=0x%s, new alloc mask=0x%s",
ul_mask.to_hex().c_str(), ulmask_buffer.data(),
prbmask.to_hex().c_str()); prbmask_buffer.data());
ret = alloc_outcome_t::ERROR; ret = alloc_outcome_t::ERROR;
} }
ul_mask |= prbmask; 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); data_alloc.pid, data, get_tti_tx_dl(), cc_cfg->enb_cc_idx, tti_alloc.get_cfi(), data_alloc.user_mask);
if (tbs <= 0) { 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", logger.warning("SCHED: DL %s failed rnti=0x%x, pid=%d, mask=%s, tbs=%d, buffer=%d",
is_newtx ? "tx" : "retx", is_newtx ? "tx" : "retx",
user->get_rnti(), user->get_rnti(),
data_alloc.pid, data_alloc.pid,
data_alloc.user_mask.to_hex().c_str(), buffer.data(),
tbs, tbs,
user->get_requested_dl_bytes(cc_cfg->enb_cc_idx).stop()); user->get_requested_dl_bytes(cc_cfg->enb_cc_idx).stop());
continue; continue;
} }
// Print Resulting DL Allocation // 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", !is_newtx ? "retx" : "tx",
user->get_rnti(), user->get_rnti(),
cc_cfg->enb_cc_idx, cc_cfg->enb_cc_idx,
data_alloc.pid, data_alloc.pid,
data_alloc.user_mask.to_hex().c_str(), buffer.data(),
data->dci.location.L, data->dci.location.L,
data->dci.location.ncce, data->dci.location.ncce,
dl_harq.nof_retx(0) + dl_harq.nof_retx(1), dl_harq.nof_retx(0) + dl_harq.nof_retx(1),

@ -15,10 +15,10 @@
#include "srslte/srslog/bundled/fmt/format.h" #include "srslte/srslog/bundled/fmt/format.h"
#include <array> #include <array>
#define Debug(fmt, ...) srslog::fetch_basic_logger("MAC").debug(fmt, ##__VA_ARGS__) #define Debug(fmt, ...) get_mac_logger().debug(fmt, ##__VA_ARGS__)
#define Info(fmt, ...) srslog::fetch_basic_logger("MAC").info(fmt, ##__VA_ARGS__) #define Info(fmt, ...) get_mac_logger().info(fmt, ##__VA_ARGS__)
#define Warning(fmt, ...) srslog::fetch_basic_logger("MAC").warning(fmt, ##__VA_ARGS__) #define Warning(fmt, ...) get_mac_logger().warning(fmt, ##__VA_ARGS__)
#define Error(fmt, ...) srslog::fetch_basic_logger("MAC").error(fmt, ##__VA_ARGS__) #define Error(fmt, ...) get_mac_logger().error(fmt, ##__VA_ARGS__)
namespace srsenb { 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 dl_sched_data_t = sched_interface::dl_sched_data_t;
using custom_mem_buffer = fmt::basic_memory_buffer<char, 1024>; 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) const char* to_string_short(srslte_dci_format_t dcifmt)
{ {
switch (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; pdcch_mask_t tot_mask;
get_allocs(&vec, &tot_mask, i - prev_start); 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) { if (verbose) {
fmt::format_to(strbuf, ", allocations:\n"); fmt::format_to(strbuf, ", allocations:\n");
for (const auto& dci_alloc : vec) { for (const auto& dci_alloc : vec) {
fmt::format_to(strbuf, fmt::format_to(strbuf,
" > rnti=0x{:0x}: 0x{} / 0x{}\n", " > rnti=0x{:0x}: 0x{:x} / 0x{:x}\n",
dci_alloc->rnti, dci_alloc->rnti,
dci_alloc->current_mask.to_hex().c_str(), dci_alloc->current_mask,
dci_alloc->total_mask.to_hex().c_str()); dci_alloc->total_mask);
} }
} else { } else {
fmt::format_to(strbuf, "\n"); 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", TESTERROR("Collision Detected of %s alloc=%s and cumulative_mask=0x%s",
ch_str, ch_str,
alloc.to_string().c_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); ul_allocs.fill(alloc.start(), alloc.stop(), true);
return SRSLTE_SUCCESS; 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, CONDERROR(expected_ul_mask != nullptr and *expected_ul_mask != ul_allocs,
"The derived UL PRB mask %s does not match the expected one %s", "The derived UL PRB mask %s does not match the expected one %s",
ul_allocs.to_string().c_str(), fmt::format("{}", ul_allocs).c_str(),
expected_ul_mask->to_string().c_str()); fmt::format("{}", *expected_ul_mask).c_str());
return SRSLTE_SUCCESS; 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()) { if ((dl_allocs & alloc_mask).any()) {
TESTERROR("Detected collision in the DL %s allocation (%s intersects %s)", TESTERROR("Detected collision in the DL %s allocation (%s intersects %s)",
channel, channel,
dl_allocs.to_string().c_str(), fmt::format("{}", dl_allocs).c_str(),
alloc_mask.to_string().c_str()); fmt::format("{}", alloc_mask).c_str());
} }
dl_allocs |= alloc_mask; dl_allocs |= alloc_mask;
return SRSLTE_SUCCESS; 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, CONDERROR(expected_rbgmask != nullptr and *expected_rbgmask != rbgmask,
"The derived DL RBG mask %s does not match the expected one %s", "The derived DL RBG mask %s does not match the expected one %s",
rbgmask.to_string().c_str(), fmt::format("{}", rbgmask).c_str(),
expected_rbgmask->to_string().c_str()); fmt::format("{}", *expected_rbgmask).c_str());
return SRSLTE_SUCCESS; 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, CONDERROR(expected_cce_mask != nullptr and *expected_cce_mask != used_cce,
"The derived PDCCH mask %s does not match the expected one %s", "The derived PDCCH mask %s does not match the expected one %s",
used_cce.to_string().c_str(), fmt::format("{}", used_cce).c_str(),
expected_cce_mask->to_string().c_str()); fmt::format("{}", *expected_cce_mask).c_str());
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }

Loading…
Cancel
Save