aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorAaron Rossetto <aaron.rossetto@ni.com>2020-05-08 08:59:54 -0500
committerAaron Rossetto <aaron.rossetto@ni.com>2020-06-29 13:41:15 -0500
commit619f9d637224627d5359e7d63e88a70660164a86 (patch)
treef62b37bd1ec471dced82113a2937dde7d19b5c54 /host
parent38caced6946243f0390c541df54160c45e4959cc (diff)
downloaduhd-619f9d637224627d5359e7d63e88a70660164a86.tar.gz
uhd-619f9d637224627d5359e7d63e88a70660164a86.tar.bz2
uhd-619f9d637224627d5359e7d63e88a70660164a86.zip
rfnoc: Add window RFNoC block controller
Diffstat (limited to 'host')
-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/window_block_control.hpp74
-rw-r--r--host/lib/rfnoc/CMakeLists.txt1
-rw-r--r--host/lib/rfnoc/window_block_control.cpp143
5 files changed, 220 insertions, 0 deletions
diff --git a/host/include/uhd/rfnoc/CMakeLists.txt b/host/include/uhd/rfnoc/CMakeLists.txt
index 9c389af03..cc91a6125 100644
--- a/host/include/uhd/rfnoc/CMakeLists.txt
+++ b/host/include/uhd/rfnoc/CMakeLists.txt
@@ -42,6 +42,7 @@ UHD_INSTALL(FILES
radio_control.hpp
split_stream_block_control.hpp
vector_iir_block_control.hpp
+ window_block_control.hpp
DESTINATION ${INCLUDE_DIR}/uhd/rfnoc
COMPONENT headers
diff --git a/host/include/uhd/rfnoc/defaults.hpp b/host/include/uhd/rfnoc/defaults.hpp
index e8f1c11e7..2104e8416 100644
--- a/host/include/uhd/rfnoc/defaults.hpp
+++ b/host/include/uhd/rfnoc/defaults.hpp
@@ -81,5 +81,6 @@ static const noc_id_t FOSPHOR_BLOCK = 0x666F0000;
static const noc_id_t SPLIT_STREAM_BLOCK = 0x57570000;
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;
}} // namespace uhd::rfnoc
diff --git a/host/include/uhd/rfnoc/window_block_control.hpp b/host/include/uhd/rfnoc/window_block_control.hpp
new file mode 100644
index 000000000..316a1a288
--- /dev/null
+++ b/host/include/uhd/rfnoc/window_block_control.hpp
@@ -0,0 +1,74 @@
+//
+// 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>
+#include <uhd/types/ranges.hpp>
+
+namespace uhd { namespace rfnoc {
+
+/*! Window Block Control Class
+ *
+ * The Window Block is a windowing block for RFNoC that is intended to be
+ * used with the FFT block. The block can be configured with coefficients,
+ * by which the samples in each input packet are multiplied before begin
+ * output. The first sample of the first packet is multiplied by the first
+ * first coefficient, the second sample is multiplied by the second
+ * coefficient, and so on.
+ *
+ * The RFNoC window block supports a configurable number of pairs of input
+ * and output ports of sc16 data (16-bit fixed-point complex samples) and
+ * a configurable window length and coefficients for each.
+ */
+class UHD_API window_block_control : public noc_block_base
+{
+public:
+ RFNOC_DECLARE_BLOCK(window_block_control)
+
+ // Block registers
+ static const uint32_t REG_WINDOW_BLOCK_SIZE;
+
+ static const uint32_t REG_WINDOW_LEN_OFFSET;
+ static const uint32_t REG_WINDOW_MAX_LEN_OFFSET;
+ static const uint32_t REG_WINDOW_LOAD_COEFF_OFFSET;
+ static const uint32_t REG_WINDOW_LOAD_COEFF_LAST_OFFSET;
+
+ /*! Get the maximum number of window coefficients supported by this block
+ *
+ * Get the maximum number of window coefficients supported by this
+ * block.
+ *
+ * \param chan The channel to retrieve the maximum number of coefficients from
+ * \returns The maximum number of window coefficients supported by this block
+ */
+ virtual size_t get_max_num_coefficients(const size_t chan) const = 0;
+
+ /*! Set the window coefficients
+ *
+ * Set the window coefficients for a given channel. The number of
+ * coefficients must be equal to or less than the maximum number of
+ * coefficients supported by the given channel of the block.
+ *
+ * \param coeffs A vector of integer coefficients for the window
+ * \param chan The channel to apply the coefficients to
+ */
+ virtual void set_coefficients(
+ const std::vector<int16_t>& coeffs, const size_t chan) = 0;
+
+ /*! Get the window coefficients
+ *
+ * Return a vector with the current window coefficients for a given channel.
+ *
+ * \param chan The channel to retrieve the current window coefficients from
+ * \returns The vector of current window coefficients
+ */
+ virtual std::vector<int16_t> get_coefficients(const size_t chan) const = 0;
+};
+
+}} // namespace uhd::rfnoc
+
diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt
index 8f74e9e6f..1a45ab1ff 100644
--- a/host/lib/rfnoc/CMakeLists.txt
+++ b/host/lib/rfnoc/CMakeLists.txt
@@ -52,5 +52,6 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/radio_control_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/split_stream_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/window_block_control.cpp b/host/lib/rfnoc/window_block_control.cpp
new file mode 100644
index 000000000..1bd6a1295
--- /dev/null
+++ b/host/lib/rfnoc/window_block_control.cpp
@@ -0,0 +1,143 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/exception.hpp>
+#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/window_block_control.hpp>
+
+using namespace uhd::rfnoc;
+
+const uint32_t window_block_control::REG_WINDOW_BLOCK_SIZE = 1 << 4;
+const uint32_t window_block_control::REG_WINDOW_LEN_OFFSET = 0x00;
+const uint32_t window_block_control::REG_WINDOW_MAX_LEN_OFFSET = 0x04;
+const uint32_t window_block_control::REG_WINDOW_LOAD_COEFF_OFFSET = 0x08;
+const uint32_t window_block_control::REG_WINDOW_LOAD_COEFF_LAST_OFFSET = 0x0C;
+
+// User property names
+const char* const PROP_KEY_MAX_LEN = "max_len";
+
+class window_block_control_impl : public window_block_control
+{
+public:
+ RFNOC_BLOCK_CONSTRUCTOR(window_block_control),
+ _window_reg_iface(*this, 0, REG_WINDOW_BLOCK_SIZE)
+ {
+ UHD_ASSERT_THROW(get_num_input_ports() == get_num_output_ports());
+ _register_props();
+ }
+
+ size_t get_max_num_coefficients(const size_t chan) const
+ {
+ return _max_len.at(chan);
+ }
+
+ void set_coefficients(const std::vector<int16_t>& coeffs, const size_t chan)
+ {
+ if (coeffs.size() > _max_len.at(chan)) {
+ std::string error_msg = "Too many window coefficients specified (max "
+ + std::to_string(_max_len.at(chan)) + ")";
+ throw uhd::value_error(error_msg);
+ }
+
+ _coeffs[chan] = coeffs;
+ _program_coefficients(chan);
+ }
+
+ std::vector<int16_t> get_coefficients(const size_t chan) const
+ {
+ return _coeffs.at(chan);
+ }
+
+private:
+ void _register_props()
+ {
+ const size_t num_chans = get_num_input_ports();
+ _max_len.reserve(num_chans);
+ _coeffs.reserve(num_chans);
+ _prop_max_len.reserve(num_chans);
+ _prop_type_in.reserve(num_chans);
+ _prop_type_out.reserve(num_chans);
+
+ for (size_t chan = 0; chan < num_chans; chan++) {
+ const uint32_t max_len =
+ _window_reg_iface.peek32(REG_WINDOW_MAX_LEN_OFFSET, chan);
+ _max_len.emplace_back(max_len);
+
+ // set a default rectangular window for each channel
+ std::vector<int16_t> rect_coeffs(
+ max_len, std::numeric_limits<int16_t>::max());
+ _coeffs.emplace_back(rect_coeffs);
+ _program_coefficients(chan);
+
+ // register user properties
+ _prop_max_len.emplace_back(property_t<int>{PROP_KEY_MAX_LEN,
+ static_cast<int>(max_len),
+ {res_source_info::USER, chan}});
+ register_property(&_prop_max_len.back());
+ add_property_resolver({&ALWAYS_DIRTY},
+ {&_prop_max_len.back()},
+ [this, chan, max_len]() { _prop_max_len.at(chan).set(max_len); });
+
+ // register edge properties
+ _prop_type_in.emplace_back(property_t<std::string>{
+ PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::INPUT_EDGE, chan}});
+ _prop_type_out.emplace_back(property_t<std::string>{
+ PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::OUTPUT_EDGE, chan}});
+ register_property(&_prop_type_in.back());
+ register_property(&_prop_type_out.back());
+
+ // add resolvers for type
+ add_property_resolver({&_prop_type_in.back()},
+ {&_prop_type_in.back()},
+ [this, chan]() { _prop_type_in.at(chan).set(IO_TYPE_SC16); });
+ add_property_resolver({&_prop_type_out.back()},
+ {&_prop_type_out.back()},
+ [this, chan]() { _prop_type_out.at(chan).set(IO_TYPE_SC16); });
+ }
+ }
+
+ void _program_coefficients(size_t chan)
+ {
+ // Write coefficients [0..num_coeffs-2]...
+ const size_t num_coeffs = _coeffs.at(chan).size();
+ std::vector<uint32_t> coeffs_addr(num_coeffs - 1, REG_WINDOW_LOAD_COEFF_OFFSET);
+ std::vector<uint32_t> coeffs_minus_last(num_coeffs - 1);
+ std::transform(_coeffs.at(chan).begin(),
+ _coeffs.at(chan).end() - 1,
+ coeffs_minus_last.begin(),
+ [this](int16_t value) -> uint32_t { return static_cast<uint32_t>(value); });
+
+ _window_reg_iface.multi_poke32(coeffs_addr, coeffs_minus_last, chan);
+ // ...and the final coefficient (num_coeffs-1)
+ _window_reg_iface.poke32(REG_WINDOW_LOAD_COEFF_LAST_OFFSET,
+ static_cast<uint32_t>(_coeffs.at(chan).at(num_coeffs - 1)),
+ chan);
+ }
+
+ //! Maximum length of window
+ std::vector<size_t> _max_len;
+
+ //! Current window coefficients
+ std::vector<std::vector<int16_t>> _coeffs;
+
+ /**************************************************************************
+ * Attributes
+ *************************************************************************/
+ std::vector<property_t<std::string>> _prop_type_in;
+ std::vector<property_t<std::string>> _prop_type_out;
+ std::vector<property_t<int>> _prop_max_len;
+
+ /**************************************************************************
+ * Register interface
+ *************************************************************************/
+ multichan_register_iface _window_reg_iface;
+};
+
+UHD_RFNOC_BLOCK_REGISTER_DIRECT(
+ window_block_control, WINDOW_BLOCK, "Window", CLOCK_KEY_GRAPH, "bus_clk")