diff options
Diffstat (limited to 'host')
-rw-r--r-- | host/include/uhd/rfnoc/node.hpp | 57 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/res_source_info.hpp | 5 | ||||
-rw-r--r-- | host/lib/rfnoc/node.cpp | 78 |
3 files changed, 122 insertions, 18 deletions
diff --git a/host/include/uhd/rfnoc/node.hpp b/host/include/uhd/rfnoc/node.hpp index a907de5a4..b26546643 100644 --- a/host/include/uhd/rfnoc/node.hpp +++ b/host/include/uhd/rfnoc/node.hpp @@ -38,6 +38,8 @@ public: using resolve_callback_t = std::function<void(void)>; using action_handler_t = std::function<void(const res_source_info&, action_info::sptr)>; + using forwarding_map_t = + std::unordered_map<res_source_info, std::vector<res_source_info>>; //! Types of property/action forwarding for those not defined by the block itself enum class forwarding_policy_t { @@ -53,7 +55,9 @@ public: //! Forward the property to all ports ONE_TO_ALL, //! Property propagation ends here - DROP + DROP, + //! Forward the property based on a client-provided map + USE_MAP }; static const size_t ANY_PORT = size_t(~0); @@ -273,6 +277,27 @@ protected: void set_prop_forwarding_policy( forwarding_policy_t policy, const std::string& prop_id = ""); + /*! Specify a table that maps how a property should be forwarded + * + * Whenever this node is asked to handle a property that is not registered, + * and the forwarding policy for the particular property is set to + * USE_MAP, the node will consult a user-provided map to determine what + * to do with the property. The map's keys are the source edges for the + * incoming property and the value associated with each key is a vector of + * destination edges to which the property should be propagated. + * + * If there is no key in the map matching an incoming property's source + * edge, or if the value of the key is the empty vector, the property is + * dropped and not propagated further. + * + * The following conditions will generate exceptions at property + * propagation time: + * - Any value in the destination vector represents a non-existent port + * + * \param map The map describing how properties should be propagated + */ + void set_prop_forwarding_map(const forwarding_map_t& map); + /*! Set a specific property that belongs to this block. * * This is like set_property(), but it also allows setting edge properties. @@ -342,6 +367,30 @@ protected: void set_action_forwarding_policy( forwarding_policy_t policy, const std::string& action_key = ""); + /*! Specify a table that maps how an action should be forwarded + * + * Whenever this node is asked to handle an action that is not registered, + * and the forwarding policy for the particular action is set to + * USE_MAP, the node will consult a user-provided map to determine what + * to do with the action. The map's keys are the source edges for the + * incoming action and the value associated with each key is a vector of + * destination edges to which the action should be forwarded. + * + * incoming action and the value is a vector of destination edges to + * which the action should be forwarded. + * + * If there is no key in the map matching an incoming action's source + * edge, or if the value of the key is the empty vector, the action is + * dropped and not forwarded further. + * + * The following conditions will generate exceptions at action + * forwarding time: + * - Any value in the destination vector represents a non-existent port + * + * \param map The map describing how actions should be forwarded + */ + void set_action_forwarding_map(const forwarding_map_t& map); + /*! Post an action to an up- or downstream node in the graph. * * If the action is posted to an edge which is not connected, the action @@ -604,6 +653,9 @@ private: std::unordered_map<std::string, forwarding_policy_t> _prop_fwd_policies{ {"", forwarding_policy_t::ONE_TO_ONE}}; + //! Map describing how incoming properties should be propagated for USE_MAP + forwarding_map_t _prop_fwd_map; + /************************************************************************** * Action-related attributes *************************************************************************/ @@ -622,6 +674,9 @@ private: action_handler_t _post_action_cb = [](const res_source_info&, action_info::sptr) { /* nop */ }; + //! Map describing how incoming actions should be forwarded for USE_MAP + forwarding_map_t _action_fwd_map; + /************************************************************************** * Other attributes *************************************************************************/ diff --git a/host/include/uhd/rfnoc/res_source_info.hpp b/host/include/uhd/rfnoc/res_source_info.hpp index 7174c95e4..05d92e5bf 100644 --- a/host/include/uhd/rfnoc/res_source_info.hpp +++ b/host/include/uhd/rfnoc/res_source_info.hpp @@ -46,6 +46,11 @@ struct res_source_info return rhs.type == type && rhs.instance == instance; } + bool operator!=(const res_source_info& rhs) const + { + return !(*this == rhs); + } + //! Returns a string representation of the source std::string to_string() const { diff --git a/host/lib/rfnoc/node.cpp b/host/lib/rfnoc/node.cpp index 7cc656a26..0abbb0d3b 100644 --- a/host/lib/rfnoc/node.cpp +++ b/host/lib/rfnoc/node.cpp @@ -154,6 +154,11 @@ void node_t::set_prop_forwarding_policy( _prop_fwd_policies[prop_id] = policy; } +void node_t::set_prop_forwarding_map(const forwarding_map_t& map) +{ + _prop_fwd_map = map; +} + void node_t::register_action_handler(const std::string& id, action_handler_t&& handler) { if (_action_handlers.count(id)) { @@ -168,6 +173,11 @@ void node_t::set_action_forwarding_policy( _action_fwd_policies[action_key] = policy; } +void node_t::set_action_forwarding_map(const forwarding_map_t& map) +{ + _action_fwd_map = map; +} + void node_t::post_action(const res_source_info& edge_info, action_info::sptr action) { _post_action_cb(edge_info, action); @@ -335,6 +345,27 @@ property_base_t* node_t::inject_edge_property( } }); } + if (fwd_policy == forwarding_policy_t::USE_MAP) { + const auto src_info = new_prop->get_src_info(); + const auto& map_entry = _prop_fwd_map.find(src_info); + if (map_entry != _prop_fwd_map.end()) { + for (const auto& dst : map_entry->second) { + if (!_has_port(dst)) { + throw uhd::rfnoc_error("Destination port " + dst.to_string() + + " in prop map does not exist"); + } + auto next_prop = inject_edge_property(new_prop, dst); + // Now add a resolver that will always forward the value from this + // property to the other one. + add_property_resolver({new_prop}, {next_prop}, [new_prop, next_prop]() { + prop_accessor_t{}.forward<false>(new_prop, next_prop); + }); + } + } else { + RFNOC_LOG_TRACE("Dropping incoming prop on " << src_info.to_string() + << " (no destinations in map)"); + } + } return new_prop; } @@ -459,16 +490,15 @@ void node_t::forward_edge_property( UHD_ASSERT_THROW( incoming_prop->get_src_info().type == res_source_info::INPUT_EDGE || incoming_prop->get_src_info().type == res_source_info::OUTPUT_EDGE); - UHD_LOG_TRACE(get_unique_id(), - "Incoming edge property: `" << incoming_prop->get_id() << "`, source info: " - << incoming_prop->get_src_info().to_string()); + RFNOC_LOG_TRACE("Incoming edge property: `" + << incoming_prop->get_id() + << "`, source info: " << incoming_prop->get_src_info().to_string()); // Don't forward properties that are not yet valid if (!incoming_prop->is_valid()) { - UHD_LOG_TRACE(get_unique_id(), - "Skipped empty edge property: `" - << incoming_prop->get_id() - << "`, source info: " << incoming_prop->get_src_info().to_string()); + RFNOC_LOG_TRACE("Skipped empty edge property: `" + << incoming_prop->get_id() << "`, source info: " + << incoming_prop->get_src_info().to_string()); return; } @@ -488,7 +518,7 @@ void node_t::forward_edge_property( // If there is no such property, we're forwarding a new property if (local_prop_set.empty()) { - UHD_LOG_TRACE(get_unique_id(), + RFNOC_LOG_TRACE( "Received unknown incoming edge prop: " << incoming_prop->get_id()); local_prop_set.emplace( inject_edge_property(incoming_prop, {prop_src_type, incoming_port})); @@ -527,11 +557,10 @@ void node_t::receive_action(const res_source_info& src_info, action_info::sptr a // Now implement custom forwarding for all forwarding policies: if (fwd_policy == forwarding_policy_t::DROP) { - UHD_LOG_TRACE(get_unique_id(), "Dropping action " << action->key); + RFNOC_LOG_TRACE("Dropping action " << action->key); } if (fwd_policy == forwarding_policy_t::ONE_TO_ONE) { - UHD_LOG_TRACE( - get_unique_id(), "Forwarding action " << action->key << " to opposite port"); + RFNOC_LOG_TRACE("Forwarding action " << action->key << " to opposite port"); const res_source_info dst_info{ res_source_info::invert_edge(src_info.type), src_info.instance}; if (_has_port(dst_info)) { @@ -539,8 +568,7 @@ void node_t::receive_action(const res_source_info& src_info, action_info::sptr a } } if (fwd_policy == forwarding_policy_t::ONE_TO_FAN) { - UHD_LOG_TRACE(get_unique_id(), - "Forwarding action " << action->key << " to all opposite ports"); + RFNOC_LOG_TRACE("Forwarding action " << action->key << " to all opposite ports"); const auto new_edge_type = res_source_info::invert_edge(src_info.type); const size_t num_ports = new_edge_type == res_source_info::INPUT_EDGE ? get_num_input_ports() @@ -551,8 +579,7 @@ void node_t::receive_action(const res_source_info& src_info, action_info::sptr a } if (fwd_policy == forwarding_policy_t::ONE_TO_ALL || fwd_policy == forwarding_policy_t::ONE_TO_ALL_IN) { - UHD_LOG_TRACE(get_unique_id(), - "Forwarding action " << action->key << " to all input ports"); + RFNOC_LOG_TRACE("Forwarding action " << action->key << " to all input ports"); for (size_t i = 0; i < get_num_input_ports(); i++) { if (src_info.type == res_source_info::INPUT_EDGE && i == src_info.instance) { continue; @@ -562,8 +589,7 @@ void node_t::receive_action(const res_source_info& src_info, action_info::sptr a } if (fwd_policy == forwarding_policy_t::ONE_TO_ALL || fwd_policy == forwarding_policy_t::ONE_TO_ALL_OUT) { - UHD_LOG_TRACE(get_unique_id(), - "Forwarding action " << action->key << " to all output ports"); + RFNOC_LOG_TRACE("Forwarding action " << action->key << " to all output ports"); for (size_t i = 0; i < get_num_output_ports(); i++) { if (src_info.type == res_source_info::OUTPUT_EDGE && i == src_info.instance) { continue; @@ -571,6 +597,24 @@ void node_t::receive_action(const res_source_info& src_info, action_info::sptr a post_action({res_source_info::OUTPUT_EDGE, i}, action); } } + if (fwd_policy == forwarding_policy_t::USE_MAP) { + const auto& map_entry = _action_fwd_map.find(src_info); + if (map_entry != _action_fwd_map.end()) { + for (const auto& dst : map_entry->second) { + if (!_has_port(dst)) { + throw uhd::rfnoc_error("Destination port " + dst.to_string() + + " in action map does not exist"); + } + RFNOC_LOG_TRACE( + "Forwarding action " << action->key << " to " << dst.to_string()); + post_action(dst, action); + } + } else { + RFNOC_LOG_TRACE("Dropping action " << action->key << " on " + << src_info.to_string() + << " (no destinations in map)"); + } + } } void node_t::shutdown() |