diff options
-rw-r--r-- | host/include/uhd/rfnoc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/defaults.hpp | 1 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/switchboard_block_control.hpp | 48 | ||||
-rw-r--r-- | host/lib/rfnoc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/lib/rfnoc/switchboard_block_control.cpp | 130 |
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") |