From 152823d5083d709b7eaafe42c918738e90ecaa4d Mon Sep 17 00:00:00 2001 From: Jesse Zhang <65556515+jessezhang-ni@users.noreply.github.com> Date: Wed, 22 Jul 2020 17:09:06 -0500 Subject: rfnoc: Add Switchboard block support --- host/lib/rfnoc/CMakeLists.txt | 1 + host/lib/rfnoc/switchboard_block_control.cpp | 130 +++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 host/lib/rfnoc/switchboard_block_control.cpp (limited to 'host/lib') 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 +#include +#include +#include +#include + +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(PROP_KEY_INPUT_SELECT, static_cast(input), output); + set_property(PROP_KEY_OUTPUT_SELECT, static_cast(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( + 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(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( + 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(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> _input_select; + std::vector> _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") -- cgit v1.2.3