diff options
author | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-08-05 07:33:46 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-08-05 07:47:22 -0500 |
commit | 72e4cc81d2d3305b7e5b9d6f884b10120547700e (patch) | |
tree | e83a53a0aea36a7b70e62f7854157e95c9e23fed | |
parent | b39021ac2e642c22349183b6bc697daae01da5e9 (diff) | |
download | uhd-72e4cc81d2d3305b7e5b9d6f884b10120547700e.tar.gz uhd-72e4cc81d2d3305b7e5b9d6f884b10120547700e.tar.bz2 uhd-72e4cc81d2d3305b7e5b9d6f884b10120547700e.zip |
rfnoc: Add Keep One in N block support
-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/keep_one_in_n_block_control.hpp | 84 | ||||
-rw-r--r-- | host/lib/rfnoc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/lib/rfnoc/keep_one_in_n_block_control.cpp | 120 |
5 files changed, 207 insertions, 0 deletions
diff --git a/host/include/uhd/rfnoc/CMakeLists.txt b/host/include/uhd/rfnoc/CMakeLists.txt index 965710a59..7fd1cd21d 100644 --- a/host/include/uhd/rfnoc/CMakeLists.txt +++ b/host/include/uhd/rfnoc/CMakeLists.txt @@ -37,6 +37,7 @@ UHD_INSTALL(FILES ddc_block_control.hpp duc_block_control.hpp dmafifo_block_control.hpp + keep_one_in_n_block_control.hpp fft_block_control.hpp fir_filter_block_control.hpp fosphor_block_control.hpp diff --git a/host/include/uhd/rfnoc/defaults.hpp b/host/include/uhd/rfnoc/defaults.hpp index f96dad8a0..1b9cb5016 100644 --- a/host/include/uhd/rfnoc/defaults.hpp +++ b/host/include/uhd/rfnoc/defaults.hpp @@ -81,6 +81,7 @@ static const noc_id_t FFT_BLOCK = 0xFF700000; static const noc_id_t FIR_FILTER_BLOCK = 0xF1120000; static const noc_id_t FOSPHOR_BLOCK = 0x666F0000; static const noc_id_t LOGPWR_BLOCK = 0x4C500000; +static const noc_id_t KEEP_ONE_IN_N_BLOCK = 0x02460000; static const noc_id_t MOVING_AVERAGE_BLOCK = 0xAAD20000; static const noc_id_t RADIO_BLOCK = 0x12AD1000; static const noc_id_t REPLAY_BLOCK = 0x4E91A000; diff --git a/host/include/uhd/rfnoc/keep_one_in_n_block_control.hpp b/host/include/uhd/rfnoc/keep_one_in_n_block_control.hpp new file mode 100644 index 000000000..fc6f0511b --- /dev/null +++ b/host/include/uhd/rfnoc/keep_one_in_n_block_control.hpp @@ -0,0 +1,84 @@ +// +// 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 { + +/*! Keep One in N Block Control Class + * + * The Keep One in N block has two modes: sample mode and packet mode. + * In sample mode, the first sample is kept and then N-1 samples are dropped. + * Packet mode is similar to sample mode, except a packet of samples is kept + * and then N-1 packets are dropped. The packet size is determined automatically. + */ +class UHD_API keep_one_in_n_block_control : public noc_block_base +{ +public: + RFNOC_DECLARE_BLOCK(keep_one_in_n_block_control) + + enum class mode {SAMPLE_MODE, PACKET_MODE}; + + // Block registers + static const uint32_t REG_N_OFFSET; + static const uint32_t REG_MODE_OFFSET; + static const uint32_t REG_WIDTH_N_OFFSET; + + /*! Get the maximum supported value for N + * + * Get the maximum supported value for N for all channels + * + * \returns The maximum supported value for N + */ + virtual size_t get_max_n() const = 0; + + /*! Get the current value of N + * + * Get the current value of N + * + * \param chan The block channel + * \returns The current value of N + */ + virtual size_t get_n(const size_t chan = 0) const = 0; + + /*! Set the value of N + * + * Set the value of N. + * See set_mode() for how the value of N is interpreted + * depending on the mode. + * + * \param n The number of samples or packets to drop (minus one) + * \param chan The block channel + */ + virtual void set_n(const size_t n, const size_t chan = 0) = 0; + + /*! Get the current mode + * + * Get the current mode (sample or packet mode, see mode enum) + * + * \param chan The block channel + * \returns The current mode + */ + virtual mode get_mode(const size_t chan = 0) const = 0; + + /*! Set the mode + * + * Set the mode. + * There are two modes, sample mode (0) and packet mode (1). + * In sample mode, the block will keep 1 value and then drop N-1 values. + * In packet mode, the block will keep 1 packet and then drop N-1 packets. + * + * \param mode The mode of the block + * \param chan The block channel + */ + virtual void set_mode(const mode mode, const size_t chan = 0) = 0; +}; + +}} // namespace uhd::rfnoc diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt index 6c7b8c726..33da287fe 100644 --- a/host/lib/rfnoc/CMakeLists.txt +++ b/host/lib/rfnoc/CMakeLists.txt @@ -45,6 +45,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/ddc_block_control.cpp ${CMAKE_CURRENT_SOURCE_DIR}/duc_block_control.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dmafifo_block_control.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/keep_one_in_n_block_control.cpp ${CMAKE_CURRENT_SOURCE_DIR}/fft_block_control.cpp ${CMAKE_CURRENT_SOURCE_DIR}/fir_filter_block_control.cpp ${CMAKE_CURRENT_SOURCE_DIR}/fosphor_block_control.cpp diff --git a/host/lib/rfnoc/keep_one_in_n_block_control.cpp b/host/lib/rfnoc/keep_one_in_n_block_control.cpp new file mode 100644 index 000000000..baec58fbf --- /dev/null +++ b/host/lib/rfnoc/keep_one_in_n_block_control.cpp @@ -0,0 +1,120 @@ +// +// Copyright 2020 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include <uhd/exception.hpp> +#include <uhd/rfnoc/keep_one_in_n_block_control.hpp> +#include <uhd/rfnoc/defaults.hpp> +#include <uhd/rfnoc/multichan_register_iface.hpp> +#include <uhd/rfnoc/property.hpp> +#include <uhd/rfnoc/registry.hpp> + +using namespace uhd::rfnoc; + +//! Space (in bytes) between register banks per channel +const uint32_t REG_BANK_OFFSET = 2048; + +const uint32_t keep_one_in_n_block_control::REG_N_OFFSET = 0 * 8; +const uint32_t keep_one_in_n_block_control::REG_MODE_OFFSET = 1 * 8; +const uint32_t keep_one_in_n_block_control::REG_WIDTH_N_OFFSET = 2 * 8; + +// User property names +const std::string PROP_KEY_N = "n"; +const std::string PROP_KEY_MODE = "mode"; + +class keep_one_in_n_block_control_impl : public keep_one_in_n_block_control +{ +public: + RFNOC_BLOCK_CONSTRUCTOR(keep_one_in_n_block_control), + _keep_one_in_n_reg_iface(*this, 0, REG_BANK_OFFSET), + _max_n( (2 << regs().peek32(REG_WIDTH_N_OFFSET))-1 ) // Fixed HDL parameter + { + UHD_ASSERT_THROW(get_num_input_ports() == get_num_output_ports()); + _register_props(); + } + + size_t get_max_n() const + { + return _max_n; + } + + void set_n(const size_t n, const size_t chan = 0) + { + set_property<int>(PROP_KEY_N, static_cast<int>(n), chan); + } + + size_t get_n(const size_t chan = 0) const + { + return _n.at(chan).get(); + } + + void set_mode(const mode mode, const size_t chan = 0) + { + set_property<int>(PROP_KEY_MODE, static_cast<int>(mode), chan); + } + + mode get_mode(const size_t chan = 0) const + { + return static_cast<mode>(_mode.at(chan).get()); + } + +protected: + //! Block-specific register interface + multichan_register_iface _keep_one_in_n_reg_iface; + +private: + void _register_props() + { + const size_t num_chans = get_num_input_ports(); + _n.reserve(num_chans); + _mode.reserve(num_chans); + + for (size_t chan = 0; chan < num_chans; chan++) { + + _n.push_back(property_t<int>( + PROP_KEY_N, 1, {res_source_info::USER, chan})); + _mode.push_back(property_t<int>( + PROP_KEY_MODE, static_cast<int>(mode::SAMPLE_MODE), + {res_source_info::USER, chan})); + + register_property(&_n.back()); + register_property(&_mode.back()); + + add_property_resolver({&_n.back()}, {&_n.back()}, [this, chan]() { + const int max_n = this->_max_n; + const int n = this->_n.at(chan).get(); + if (n < 1) { + throw uhd::value_error("Value of n must be positive"); + } + else if (n > max_n) { + throw uhd::value_error("Value of n must be less than " + + std::to_string(max_n)); + } + this->regs().poke32(REG_N_OFFSET, n); + }); + add_property_resolver({&_mode.back()}, + {&_mode.back()}, [this, chan]() { + const int mode = this->_mode.at(chan).get(); + this->regs().poke32(REG_MODE_OFFSET, mode); + }); + } + } + + /************************************************************************** + * Attributes + *************************************************************************/ + //! Maximum value for N + const int _max_n; + + //! Properties for scaling_in (one per port) + std::vector<property_t<int>> _n; + + //! Sample mode or Packet mode + std::vector<property_t<int>> _mode; + +}; + +UHD_RFNOC_BLOCK_REGISTER_DIRECT( + keep_one_in_n_block_control, KEEP_ONE_IN_N_BLOCK, "KeepOneInN", CLOCK_KEY_GRAPH, "bus_clk") |