aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-07-26 15:08:18 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:33 -0800
commit9b8e4e652c168e76f7cf2ca0a699640961b8e6ce (patch)
treec7ed65d9898aca0cddcc469b403dfe19c7292609 /host/lib
parentab87597e9e76854237b5d78f7d35959b14e9737b (diff)
downloaduhd-9b8e4e652c168e76f7cf2ca0a699640961b8e6ce.tar.gz
uhd-9b8e4e652c168e76f7cf2ca0a699640961b8e6ce.tar.bz2
uhd-9b8e4e652c168e76f7cf2ca0a699640961b8e6ce.zip
rfnoc: Add MTU tracking
MTUs are now tracked through the framework for all childs of noc_block_base. Every edge gets an 'mtu' property. MTU can be set and get either through the prop API, or through new API calls (get_mtu(), set_mtu()). It is also possible to create custom properties that depend on the MTU by asking for a reference to the MTU property, and then adding that to the input list of a property resolver. The radio_control_impl includes a change in this commit where it sets the spp based on the MTU. Blocks can also set an MTU forwarding policy. The DDC block includes a change in this commit that sets a forwarding policy of ONE_TO_ONE, meaning that the MTU on an input edge is forwarded to the corresponding output edge (but not the other edges, as with the tick rate).
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/rfnoc/ddc_block_control.cpp1
-rw-r--r--host/lib/rfnoc/noc_block_base.cpp114
-rw-r--r--host/lib/rfnoc/radio_control_impl.cpp12
-rw-r--r--host/lib/rfnoc/rfnoc_graph.cpp2
4 files changed, 124 insertions, 5 deletions
diff --git a/host/lib/rfnoc/ddc_block_control.cpp b/host/lib/rfnoc/ddc_block_control.cpp
index 0c2721833..37286b29d 100644
--- a/host/lib/rfnoc/ddc_block_control.cpp
+++ b/host/lib/rfnoc/ddc_block_control.cpp
@@ -71,6 +71,7 @@ public:
<< " halfbands and "
"max CIC decimation "
<< _cic_max_decim);
+ set_mtu_forwarding_policy(forwarding_policy_t::ONE_TO_ONE);
// Load list of valid decimation values
std::set<size_t> decims{1}; // 1 is always a valid decimatino
for (size_t hb = 0; hb < _num_halfbands; hb++) {
diff --git a/host/lib/rfnoc/noc_block_base.cpp b/host/lib/rfnoc/noc_block_base.cpp
index 68093d9b1..8f76ac1d1 100644
--- a/host/lib/rfnoc/noc_block_base.cpp
+++ b/host/lib/rfnoc/noc_block_base.cpp
@@ -48,14 +48,14 @@ noc_block_base::noc_block_base(make_args_ptr make_args)
{res_source_info::OUTPUT_EDGE, output_port}));
}
// Register all the tick_rate properties and create a default resolver
- prop_ptrs_t prop_refs;
- prop_refs.reserve(_tick_rate_props.size());
+ prop_ptrs_t tick_rate_prop_refs;
+ tick_rate_prop_refs.reserve(_tick_rate_props.size());
for (auto& prop : _tick_rate_props) {
- prop_refs.insert(&prop);
+ tick_rate_prop_refs.insert(&prop);
register_property(&prop);
}
for (auto& prop : _tick_rate_props) {
- auto prop_refs_copy = prop_refs;
+ auto prop_refs_copy = tick_rate_prop_refs;
add_property_resolver(
{&prop}, std::move(prop_refs_copy), [this, source_prop = &prop]() {
// _set_tick_rate() will update _tick_rate, but only if that's
@@ -68,6 +68,68 @@ noc_block_base::noc_block_base(make_args_ptr make_args)
}
});
}
+ // Now, the same thing for MTU props
+ // Create one mtu property for every port
+ _mtu_props.reserve(_num_input_ports + _num_output_ports);
+ for (size_t input_port = 0; input_port < _num_input_ports; input_port++) {
+ _mtu_props.push_back(property_t<size_t>(
+ PROP_KEY_MTU, make_args->mtu, {res_source_info::INPUT_EDGE, input_port}));
+ _mtu.insert({{res_source_info::INPUT_EDGE, input_port}, make_args->mtu});
+ }
+ for (size_t output_port = 0; output_port < _num_output_ports; output_port++) {
+ _mtu_props.push_back(property_t<size_t>(
+ PROP_KEY_MTU, make_args->mtu, {res_source_info::OUTPUT_EDGE, output_port}));
+ _mtu.insert({{res_source_info::OUTPUT_EDGE, output_port}, make_args->mtu});
+ }
+ // Register all the mtu properties and create a default resolver
+ prop_ptrs_t mtu_prop_refs;
+ mtu_prop_refs.reserve(_mtu_props.size());
+ for (auto& prop : _mtu_props) {
+ mtu_prop_refs.insert(&prop);
+ register_property(&prop);
+ }
+ for (auto& prop : _mtu_props) {
+ auto prop_refs_copy = mtu_prop_refs;
+ add_property_resolver(
+ {&prop}, std::move(prop_refs_copy), [this, source_prop = &prop]() {
+ const res_source_info src_edge = source_prop->get_src_info();
+ // First, coerce the MTU to its appropriate min value
+ const size_t new_mtu = std::min(source_prop->get(), _mtu.at(src_edge));
+ source_prop->set(new_mtu);
+ _mtu.at(src_edge) = source_prop->get();
+ RFNOC_LOG_TRACE("MTU is now " << _mtu.at(src_edge) << " on edge "
+ << src_edge.to_string());
+ auto update_pred = [src_edge, fwd_policy = _mtu_fwd_policy](
+ const res_source_info& mtu_src) -> bool {
+ switch (fwd_policy) {
+ case forwarding_policy_t::DROP:
+ return false;
+ case forwarding_policy_t::ONE_TO_ONE:
+ return res_source_info::invert_edge(mtu_src.type)
+ == src_edge.type
+ && mtu_src.instance == src_edge.instance;
+ case forwarding_policy_t::ONE_TO_ALL:
+ return mtu_src.type != src_edge.type && mtu_src.instance
+ && src_edge.instance;
+ case forwarding_policy_t::ONE_TO_FAN:
+ return res_source_info::invert_edge(mtu_src.type)
+ == src_edge.type;
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ }
+ };
+
+ for (auto& mtu_prop : _mtu_props) {
+ if (update_pred(mtu_prop.get_src_info())
+ && mtu_prop.get() != new_mtu) {
+ RFNOC_LOG_TRACE("Forwarding new MTU value to edge "
+ << mtu_prop.get_src_info().to_string());
+ mtu_prop.set(new_mtu);
+ _mtu.at(mtu_prop.get_src_info()) = mtu_prop.get();
+ }
+ }
+ });
+ }
}
noc_block_base::~noc_block_base()
@@ -137,6 +199,50 @@ void noc_block_base::_set_tick_rate(const double tick_rate)
}
}
+void noc_block_base::set_mtu_forwarding_policy(const forwarding_policy_t policy)
+{
+ if (policy == forwarding_policy_t::DROP || policy == forwarding_policy_t::ONE_TO_ONE
+ || policy == forwarding_policy_t::ONE_TO_ALL
+ || policy == forwarding_policy_t::ONE_TO_FAN) {
+ _mtu_fwd_policy = policy;
+ return;
+ }
+ RFNOC_LOG_ERROR("Setting invalid MTU forwarding policy!");
+ throw uhd::value_error("MTU forwarding policy must be either DROP, ONE_TO_ONE, "
+ "ONE_TO_ALL, or ONE_TO_FAN!");
+}
+
+void noc_block_base::set_mtu(const res_source_info& edge, const size_t new_mtu)
+{
+ if (edge.type != res_source_info::INPUT_EDGE
+ && edge.type != res_source_info::OUTPUT_EDGE) {
+ throw uhd::value_error(
+ "set_mtu() must be called on either an input or output edge!");
+ }
+ set_property<size_t>(PROP_KEY_MTU, new_mtu, edge);
+}
+
+
+size_t noc_block_base::get_mtu(const res_source_info& edge)
+{
+ if (!_mtu.count(edge)) {
+ throw uhd::value_error(
+ std::string("Cannot get MTU on edge: ") + edge.to_string());
+ }
+ return _mtu.at(edge);
+}
+
+property_base_t* noc_block_base::get_mtu_prop_ref(const res_source_info& edge)
+{
+ for (size_t mtu_prop_idx = 0; mtu_prop_idx < _mtu_props.size(); mtu_prop_idx++) {
+ if (_mtu_props.at(mtu_prop_idx).get_src_info() == edge) {
+ return &_mtu_props.at(mtu_prop_idx);
+ }
+ }
+ throw uhd::value_error(
+ std::string("Could not find MTU property for edge: ") + edge.to_string());
+}
+
void noc_block_base::shutdown()
{
RFNOC_LOG_TRACE("Calling deinit()");
diff --git a/host/lib/rfnoc/radio_control_impl.cpp b/host/lib/rfnoc/radio_control_impl.cpp
index 4ed0c4b60..f71c73289 100644
--- a/host/lib/rfnoc/radio_control_impl.cpp
+++ b/host/lib/rfnoc/radio_control_impl.cpp
@@ -170,10 +170,20 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
register_property(&_samp_rate_out.back());
register_property(&_type_in.back());
register_property(&_type_out.back());
- add_property_resolver({&_spp_prop.back()},
+ add_property_resolver(
+ {&_spp_prop.back(), get_mtu_prop_ref({res_source_info::OUTPUT_EDGE, chan})},
{&_spp_prop.back()},
[this, chan, &spp = _spp_prop.back()]() {
RFNOC_LOG_TRACE("Calling resolver for spp@" << chan);
+ const int mtu =
+ static_cast<int>(get_mtu({res_source_info::OUTPUT_EDGE, chan}));
+ const int max_spp_per_mtu = mtu / (_samp_width / 8) - (mtu % _spc);
+ if (spp.get() > max_spp_per_mtu) {
+ RFNOC_LOG_WARNING("spp value " << spp.get() << " exceeds MTU of "
+ << mtu << "! Coercing to "
+ << max_spp_per_mtu);
+ spp = max_spp_per_mtu;
+ }
if (spp.get() % _spc) {
spp = spp.get() - (spp.get() % _spc);
RFNOC_LOG_WARNING(
diff --git a/host/lib/rfnoc/rfnoc_graph.cpp b/host/lib/rfnoc/rfnoc_graph.cpp
index bf49ca28b..511e61f05 100644
--- a/host/lib/rfnoc/rfnoc_graph.cpp
+++ b/host/lib/rfnoc/rfnoc_graph.cpp
@@ -409,6 +409,8 @@ private:
make_args_uptr->block_id = block_id;
make_args_uptr->num_input_ports = block_info.num_inputs;
make_args_uptr->num_output_ports = block_info.num_outputs;
+ make_args_uptr->mtu =
+ (1 << block_info.data_mtu) * chdr_w_to_bits(mb.get_chdr_w()) / 8;
make_args_uptr->reg_iface = block_reg_iface;
make_args_uptr->tb_clk_iface = tb_clk_iface;
make_args_uptr->ctrlport_clk_iface = ctrlport_clk_iface;