aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/rfnoc
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/rfnoc')
-rw-r--r--host/lib/rfnoc/radio_control_impl.cpp37
-rw-r--r--host/lib/rfnoc/rfnoc_rx_streamer.cpp33
-rw-r--r--host/lib/rfnoc/rfnoc_tx_streamer.cpp32
3 files changed, 92 insertions, 10 deletions
diff --git a/host/lib/rfnoc/radio_control_impl.cpp b/host/lib/rfnoc/radio_control_impl.cpp
index a5c69e229..a08470d8a 100644
--- a/host/lib/rfnoc/radio_control_impl.cpp
+++ b/host/lib/rfnoc/radio_control_impl.cpp
@@ -9,6 +9,7 @@
#include <uhd/rfnoc/multichan_register_iface.hpp>
#include <uhd/rfnoc/register_iface.hpp>
#include <uhd/utils/log.hpp>
+#include <uhd/utils/math.hpp>
#include <uhdlib/rfnoc/radio_control_impl.hpp>
#include <uhdlib/utils/compat_check.hpp>
#include <map>
@@ -106,6 +107,8 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
});
// Register spp properties and resolvers
_spp_prop.reserve(get_num_output_ports());
+ _atomic_item_size_in.reserve(get_num_input_ports());
+ _atomic_item_size_out.reserve(get_num_output_ports());
_samp_rate_in.reserve(get_num_input_ports());
_samp_rate_out.reserve(get_num_output_ports());
_type_in.reserve(get_num_input_ports());
@@ -116,6 +119,14 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
get_max_spp(get_max_payload_size({res_source_info::OUTPUT_EDGE, chan}));
_spp_prop.push_back(
property_t<int>(PROP_KEY_SPP, default_spp, {res_source_info::USER, chan}));
+ _atomic_item_size_in.push_back(
+ property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE,
+ get_atomic_item_size(),
+ {res_source_info::INPUT_EDGE, chan}));
+ _atomic_item_size_out.push_back(
+ property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE,
+ get_atomic_item_size(),
+ {res_source_info::OUTPUT_EDGE, chan}));
_samp_rate_in.push_back(property_t<double>(
PROP_KEY_SAMP_RATE, get_tick_rate(), {res_source_info::INPUT_EDGE, chan}));
_samp_rate_out.push_back(property_t<double>(
@@ -132,6 +143,8 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
_radio_reg_iface.poke32(
regmap::REG_RX_MAX_WORDS_PER_PKT, words_per_pkt, chan);
});
+ register_property(&_atomic_item_size_in.back());
+ register_property(&_atomic_item_size_out.back());
register_property(&_samp_rate_in.back());
register_property(&_samp_rate_out.back());
register_property(&_type_in.back());
@@ -163,6 +176,30 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
"spp must be greater than zero! Coercing to " << spp.get());
}
});
+ add_property_resolver({&_atomic_item_size_in.back(),
+ get_mtu_prop_ref({res_source_info::INPUT_EDGE, chan})},
+ {&_atomic_item_size_in.back()},
+ [this, chan,
+ &ais_in = _atomic_item_size_in.back()]() {
+ ais_in = uhd::math::lcm<size_t>(ais_in, get_atomic_item_size());
+ ais_in = std::min<size_t>(ais_in, get_mtu({res_source_info::INPUT_EDGE, chan}));
+ if (ais_in.get() % get_atomic_item_size() > 0) {
+ ais_in = ais_in - (ais_in.get() % get_atomic_item_size());
+ }
+ RFNOC_LOG_TRACE("Resolve atomic item size in to " << ais_in);
+ });
+ add_property_resolver({&_atomic_item_size_out.back(),
+ get_mtu_prop_ref({res_source_info::OUTPUT_EDGE, chan})},
+ {&_atomic_item_size_out.back()},
+ [this, chan,
+ &ais_out = _atomic_item_size_out.back()]() {
+ ais_out = uhd::math::lcm<size_t>(ais_out, get_atomic_item_size());
+ ais_out = std::min<size_t>(ais_out, get_mtu({res_source_info::OUTPUT_EDGE, chan}));
+ if (ais_out.get() % get_atomic_item_size() > 0) {
+ ais_out = ais_out - (ais_out.get() % get_atomic_item_size());
+ }
+ RFNOC_LOG_TRACE("Resolve atomic item size out to " << ais_out);
+ });
// Note: The following resolver calls coerce_rate(), which is virtual.
// At run time, it will use the implementation by the child class.
add_property_resolver({&_samp_rate_in.back(), &_samp_rate_out.back()},
diff --git a/host/lib/rfnoc/rfnoc_rx_streamer.cpp b/host/lib/rfnoc/rfnoc_rx_streamer.cpp
index d57b8aab2..5e6dddcbe 100644
--- a/host/lib/rfnoc/rfnoc_rx_streamer.cpp
+++ b/host/lib/rfnoc/rfnoc_rx_streamer.cpp
@@ -59,6 +59,7 @@ rfnoc_rx_streamer::rfnoc_rx_streamer(const size_t num_chans,
_tick_rate_in.reserve(num_chans);
_type_in.reserve(num_chans);
_mtu_in.reserve(num_chans);
+ _atomic_item_size_in.reserve(num_chans);
for (size_t i = 0; i < num_chans; i++) {
_register_props(i, stream_args.otw_format);
@@ -188,13 +189,16 @@ void rfnoc_rx_streamer::_register_props(const size_t chan, const std::string& ot
PROP_KEY_TYPE, otw_format, {res_source_info::INPUT_EDGE, chan}));
_mtu_in.emplace_back(
property_t<size_t>(PROP_KEY_MTU, get_mtu(), {res_source_info::INPUT_EDGE, chan}));
+ _atomic_item_size_in.emplace_back(
+ property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE, 1, {res_source_info::INPUT_EDGE, chan}));
// Give us some shorthands for the rest of this function
- property_t<double>* scaling_in = &_scaling_in.back();
- property_t<double>* samp_rate_in = &_samp_rate_in.back();
- property_t<double>* tick_rate_in = &_tick_rate_in.back();
- property_t<std::string>* type_in = &_type_in.back();
- property_t<size_t>* mtu_in = &_mtu_in.back();
+ property_t<double>* scaling_in = &_scaling_in.back();
+ property_t<double>* samp_rate_in = &_samp_rate_in.back();
+ property_t<double>* tick_rate_in = &_tick_rate_in.back();
+ property_t<std::string>* type_in = &_type_in.back();
+ property_t<size_t>* mtu_in = &_mtu_in.back();
+ property_t<size_t>* atomic_item_size_in = &_atomic_item_size_in.back();
// Register them
register_property(scaling_in);
@@ -202,6 +206,7 @@ void rfnoc_rx_streamer::_register_props(const size_t chan, const std::string& ot
register_property(tick_rate_in);
register_property(type_in);
register_property(mtu_in);
+ register_property(atomic_item_size_in);
// Add resolvers
add_property_resolver({scaling_in}, {}, [& scaling_in = *scaling_in, chan, this]() {
@@ -228,6 +233,24 @@ void rfnoc_rx_streamer::_register_props(const size_t chan, const std::string& ot
this->set_tick_rate(tick_rate_in.get());
}
});
+
+ add_property_resolver(
+ {atomic_item_size_in, mtu_in}, {}, [&ais = *atomic_item_size_in, chan, this]() {
+ const auto UHD_UNUSED(log_chan) = chan;
+ RFNOC_LOG_TRACE("Calling resolver for `atomic_item_size'@" << chan);
+ if (ais.is_valid()) {
+ const auto spp = this->rx_streamer_impl::get_max_num_samps();
+ if (spp < ais.get()) {
+ throw uhd::value_error("samples per package must not be smaller than atomic item size");
+ }
+ const auto misalignment = spp % ais.get();
+ RFNOC_LOG_TRACE("Check atomic item size " << ais.get() << " divides spp " << spp);
+ if (misalignment > 0) {
+ RFNOC_LOG_TRACE("Reduce spp by " << misalignment << " to align with atomic item size");
+ this->rx_streamer_impl::set_max_num_samps(spp - misalignment);
+ }
+ }
+ });
}
void rfnoc_rx_streamer::_handle_rx_event_action(
diff --git a/host/lib/rfnoc/rfnoc_tx_streamer.cpp b/host/lib/rfnoc/rfnoc_tx_streamer.cpp
index 969c41ae6..411affe62 100644
--- a/host/lib/rfnoc/rfnoc_tx_streamer.cpp
+++ b/host/lib/rfnoc/rfnoc_tx_streamer.cpp
@@ -47,6 +47,7 @@ rfnoc_tx_streamer::rfnoc_tx_streamer(const size_t num_chans,
_tick_rate_out.reserve(num_chans);
_type_out.reserve(num_chans);
_mtu_out.reserve(num_chans);
+ _atomic_item_size_out.reserve(num_chans);
for (size_t i = 0; i < num_chans; i++) {
_register_props(i, stream_args.otw_format);
@@ -171,13 +172,16 @@ void rfnoc_tx_streamer::_register_props(const size_t chan, const std::string& ot
PROP_KEY_TYPE, otw_format, {res_source_info::OUTPUT_EDGE, chan}));
_mtu_out.push_back(property_t<size_t>(
PROP_KEY_MTU, get_mtu(), {res_source_info::OUTPUT_EDGE, chan}));
+ _atomic_item_size_out.push_back(
+ property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE, 1, {res_source_info::OUTPUT_EDGE, chan}));
// Give us some shorthands for the rest of this function
- property_t<double>* scaling_out = &_scaling_out.back();
- property_t<double>* samp_rate_out = &_samp_rate_out.back();
- property_t<double>* tick_rate_out = &_tick_rate_out.back();
- property_t<std::string>* type_out = &_type_out.back();
- property_t<size_t>* mtu_out = &_mtu_out.back();
+ property_t<double>* scaling_out = &_scaling_out.back();
+ property_t<double>* samp_rate_out = &_samp_rate_out.back();
+ property_t<double>* tick_rate_out = &_tick_rate_out.back();
+ property_t<std::string>* type_out = &_type_out.back();
+ property_t<size_t>* mtu_out = &_mtu_out.back();
+ property_t<size_t>* atomic_item_size_out = &_atomic_item_size_out.back();
// Register them
register_property(scaling_out);
@@ -185,6 +189,7 @@ void rfnoc_tx_streamer::_register_props(const size_t chan, const std::string& ot
register_property(tick_rate_out);
register_property(type_out);
register_property(mtu_out);
+ register_property(atomic_item_size_out);
// Add resolvers
add_property_resolver(
@@ -212,6 +217,23 @@ void rfnoc_tx_streamer::_register_props(const size_t chan, const std::string& ot
this->set_tick_rate(tick_rate_out.get());
}
});
+ add_property_resolver(
+ {atomic_item_size_out, mtu_out}, {}, [&ais = *atomic_item_size_out, chan, this]() {
+ const auto UHD_UNUSED(log_chan) = chan;
+ RFNOC_LOG_TRACE("Calling resolver for `atomic_item_size'@" << chan);
+ if (ais.is_valid()) {
+ const auto spp = this->tx_streamer_impl::get_max_num_samps();
+ if (spp < ais.get()) {
+ throw uhd::value_error("samples per package must not be smaller than atomic item size");
+ }
+ const auto misalignment = spp % ais.get();
+ RFNOC_LOG_TRACE("Check atomic item size " << ais.get() << " divides spp " << spp);
+ if (misalignment > 0) {
+ RFNOC_LOG_TRACE("Reduce spp by " << misalignment << " to align with atomic item size");
+ this->tx_streamer_impl::set_max_num_samps(spp - misalignment);
+ }
+ }
+ });
}
void rfnoc_tx_streamer::_handle_tx_event_action(