aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/rfnoc/CMakeLists.txt1
-rw-r--r--host/include/uhd/rfnoc/defaults.hpp1
-rw-r--r--host/include/uhd/rfnoc/switchboard_block_control.hpp48
-rw-r--r--host/lib/rfnoc/CMakeLists.txt1
-rw-r--r--host/lib/rfnoc/switchboard_block_control.cpp130
5 files changed, 181 insertions, 0 deletions
diff --git a/host/include/uhd/rfnoc/CMakeLists.txt b/host/include/uhd/rfnoc/CMakeLists.txt
index 3249b51f3..7a1602f90 100644
--- a/host/include/uhd/rfnoc/CMakeLists.txt
+++ b/host/include/uhd/rfnoc/CMakeLists.txt
@@ -45,6 +45,7 @@ UHD_INSTALL(FILES
null_block_control.hpp
radio_control.hpp
split_stream_block_control.hpp
+ switchboard_block_control.hpp
vector_iir_block_control.hpp
window_block_control.hpp
diff --git a/host/include/uhd/rfnoc/defaults.hpp b/host/include/uhd/rfnoc/defaults.hpp
index 9964467d3..ac230b57d 100644
--- a/host/include/uhd/rfnoc/defaults.hpp
+++ b/host/include/uhd/rfnoc/defaults.hpp
@@ -83,6 +83,7 @@ static const noc_id_t FOSPHOR_BLOCK = 0x666F0000;
static const noc_id_t LOGPWR_BLOCK = 0x4C500000;
static const noc_id_t MOVING_AVERAGE_BLOCK = 0xAAD20000;
static const noc_id_t SPLIT_STREAM_BLOCK = 0x57570000;
+static const noc_id_t SWITCHBOARD_BLOCK = 0xBE110000;
static const noc_id_t RADIO_BLOCK = 0x12AD1000;
static const noc_id_t VECTOR_IIR_BLOCK = 0x11120000;
static const noc_id_t WINDOW_BLOCK = 0xD0530000;
diff --git a/host/include/uhd/rfnoc/switchboard_block_control.hpp b/host/include/uhd/rfnoc/switchboard_block_control.hpp
new file mode 100644
index 000000000..0b0b4c722
--- /dev/null
+++ b/host/include/uhd/rfnoc/switchboard_block_control.hpp
@@ -0,0 +1,48 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#pragma once
+
+#include <uhd/config.hpp>
+#include <uhd/rfnoc/noc_block_base.hpp>
+
+namespace uhd { namespace rfnoc {
+
+/*! Switchboard Block Control Class
+ *
+ * The Switchboard Block is an RFNoC block that routes any single input to any
+ * single output. Routing is 1 to 1, that is, an input port can only be connected
+ * to one output port, and vice versa.
+ *
+ * INIT: This block is initialized with only input port 0 connected to output
+ * port 0.
+ *
+ * NOTE: This block is not intended to switch during the transmission of packets.
+ * Data on disconnected inputs will stall.
+ */
+class UHD_API switchboard_block_control : public noc_block_base
+{
+public:
+ RFNOC_DECLARE_BLOCK(switchboard_block_control)
+
+ // Block registers
+ static const uint32_t REG_BLOCK_SIZE;
+
+ static const uint32_t REG_DEMUX_SELECT_ADDR;
+ static const uint32_t REG_MUX_SELECT_ADDR;
+
+ /*! Connects an input to an output
+ *
+ * Bridges an input to an output. Any existing connections on
+ * either the input or output will be dropped.
+ *
+ * \param input Index of the input port.
+ * \param output Index of the output port.
+ */
+ virtual void connect(const size_t input, const size_t output) = 0;
+};
+
+}} // namespace uhd::rfnoc
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")