aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/rfnoc/CMakeLists.txt1
-rw-r--r--host/lib/rfnoc/switchboard_block_control.cpp130
2 files changed, 131 insertions, 0 deletions
diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt
index 63bdccf4d..a9c3c9ed0 100644
--- a/host/lib/rfnoc/CMakeLists.txt
+++ b/host/lib/rfnoc/CMakeLists.txt
@@ -53,6 +53,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/null_block_control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/radio_control_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/split_stream_block_control.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/switchboard_block_control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vector_iir_block_control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/window_block_control.cpp
)
diff --git a/host/lib/rfnoc/switchboard_block_control.cpp b/host/lib/rfnoc/switchboard_block_control.cpp
new file mode 100644
index 000000000..229c224e9
--- /dev/null
+++ b/host/lib/rfnoc/switchboard_block_control.cpp
@@ -0,0 +1,130 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/rfnoc/defaults.hpp>
+#include <uhd/rfnoc/multichan_register_iface.hpp>
+#include <uhd/rfnoc/property.hpp>
+#include <uhd/rfnoc/registry.hpp>
+#include <uhd/rfnoc/switchboard_block_control.hpp>
+
+using namespace uhd::rfnoc;
+
+// Register offsets
+const uint32_t switchboard_block_control::REG_BLOCK_SIZE = 8;
+const uint32_t switchboard_block_control::REG_DEMUX_SELECT_ADDR = 0;
+const uint32_t switchboard_block_control::REG_MUX_SELECT_ADDR = 4;
+
+// User properties
+const char* const PROP_KEY_INPUT_SELECT = "input_select";
+const char* const PROP_KEY_OUTPUT_SELECT = "output_select";
+
+class switchboard_block_control_impl : public switchboard_block_control
+{
+public:
+ RFNOC_BLOCK_CONSTRUCTOR(switchboard_block_control),
+ _num_input_ports(get_num_input_ports()),
+ _num_output_ports(get_num_output_ports()),
+ _switchboard_reg_iface(*this, 0, REG_BLOCK_SIZE)
+ {
+ UHD_ASSERT_THROW(_num_input_ports > 0 && _num_output_ports > 0);
+
+ _register_props();
+
+ // Configure property propagation and action forwarding behavior.
+ set_prop_forwarding_policy(forwarding_policy_t::USE_MAP);
+ set_action_forwarding_policy(forwarding_policy_t::USE_MAP);
+
+ _update_forwarding_map();
+ }
+
+ void connect(const size_t input, const size_t output)
+ {
+ set_property<int>(PROP_KEY_INPUT_SELECT, static_cast<int>(input), output);
+ set_property<int>(PROP_KEY_OUTPUT_SELECT, static_cast<int>(output), input);
+
+ _update_forwarding_map();
+ }
+
+private:
+ const size_t _num_input_ports;
+ const size_t _num_output_ports;
+
+ void _register_props()
+ {
+ _input_select.reserve(_num_output_ports);
+ _output_select.reserve(_num_input_ports);
+
+ // Register _input_select properties
+ for (size_t output_port = 0; output_port < _num_output_ports; output_port++) {
+ _input_select.emplace_back(property_t<int>(
+ PROP_KEY_INPUT_SELECT, 0, {res_source_info::USER, output_port}));
+
+ register_property(&_input_select.back(), [this, output_port]() {
+ int select_val = _input_select.at(output_port).get();
+ if (select_val < 0
+ || static_cast<unsigned int>(select_val) >= _num_input_ports)
+ throw uhd::value_error("Index out of bounds");
+ _switchboard_reg_iface.poke32(
+ REG_MUX_SELECT_ADDR, select_val, output_port);
+ });
+ }
+
+ // Register _output_select properties
+ for (size_t input_port = 0; input_port < _num_input_ports; input_port++) {
+ _output_select.emplace_back(property_t<int>(
+ PROP_KEY_OUTPUT_SELECT, 0, {res_source_info::USER, input_port}));
+
+ register_property(&_output_select.back(), [this, input_port]() {
+ int select_val = _output_select.at(input_port).get();
+ if (select_val < 0
+ || static_cast<unsigned int>(select_val) >= _num_output_ports)
+ throw uhd::value_error("Index out of bounds");
+ _switchboard_reg_iface.poke32(
+ REG_DEMUX_SELECT_ADDR, select_val, input_port);
+ });
+ }
+ }
+
+ void _update_forwarding_map()
+ {
+ node_t::forwarding_map_t prop_fwd_map;
+ node_t::forwarding_map_t action_fwd_map;
+
+ // Property propagation scheme:
+ // Connected inputs and outputs will propagate to each other.
+ // Unconnected inputs and outputs do not propagate.
+ for (size_t input_port = 0; input_port < _num_input_ports; input_port++) {
+ size_t linked_output_port = _output_select.at(input_port).get();
+ size_t linked_input_port = _input_select.at(linked_output_port).get();
+ if (linked_input_port == input_port) {
+ prop_fwd_map.insert({{res_source_info::INPUT_EDGE, linked_input_port},
+ {{res_source_info::OUTPUT_EDGE, linked_output_port}}});
+ prop_fwd_map.insert({{res_source_info::OUTPUT_EDGE, linked_output_port},
+ {{res_source_info::INPUT_EDGE, linked_input_port}}});
+ action_fwd_map.insert({{res_source_info::INPUT_EDGE, linked_input_port},
+ {{res_source_info::OUTPUT_EDGE, linked_output_port}}});
+ action_fwd_map.insert({{res_source_info::OUTPUT_EDGE, linked_output_port},
+ {{res_source_info::INPUT_EDGE, linked_input_port}}});
+ }
+ }
+ set_prop_forwarding_map(prop_fwd_map);
+ set_action_forwarding_map(action_fwd_map);
+ }
+
+ /**************************************************************************
+ * Attributes
+ *************************************************************************/
+ std::vector<property_t<int>> _input_select;
+ std::vector<property_t<int>> _output_select;
+
+ /**************************************************************************
+ * Register Interface
+ *************************************************************************/
+ multichan_register_iface _switchboard_reg_iface;
+};
+
+UHD_RFNOC_BLOCK_REGISTER_DIRECT(
+ switchboard_block_control, SWITCHBOARD_BLOCK, "Switchboard", CLOCK_KEY_GRAPH, "bus_clk")