diff options
author | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-06-04 13:00:20 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-06-18 07:48:25 -0500 |
commit | bf9594641db92ea56e8a72c45e9b6e4322dc2162 (patch) | |
tree | b8fe66c97d071b7a550590138d37d1baf4082cfb /host/lib | |
parent | eeae393ad4b1c0546922eab3c4decb39e5e69f4b (diff) | |
download | uhd-bf9594641db92ea56e8a72c45e9b6e4322dc2162.tar.gz uhd-bf9594641db92ea56e8a72c45e9b6e4322dc2162.tar.bz2 uhd-bf9594641db92ea56e8a72c45e9b6e4322dc2162.zip |
rfnoc: Augment FFT RFNoC block controller
This commit augments the existing FFT RFNoC block controller with
C++ functions through which the block can be configured, as well as
adding range checking to the various properties that sit atop the FFT
RFNoC block registers.
Diffstat (limited to 'host/lib')
-rw-r--r-- | host/lib/rfnoc/fft_block_control.cpp | 150 |
1 files changed, 120 insertions, 30 deletions
diff --git a/host/lib/rfnoc/fft_block_control.cpp b/host/lib/rfnoc/fft_block_control.cpp index c002d49bb..867d458ca 100644 --- a/host/lib/rfnoc/fft_block_control.cpp +++ b/host/lib/rfnoc/fft_block_control.cpp @@ -14,30 +14,27 @@ using namespace uhd::rfnoc; namespace { -constexpr int DEFAULT_SIZE = 256; -const fft_shift DEFAULT_SHIFT = fft_shift::NORMAL; -const fft_direction DEFAULT_DIRECTION = fft_direction::FORWARD; -const fft_magnitude DEFAULT_MAGNITUDE = fft_magnitude::COMPLEX; -constexpr int DEFAULT_FFT_SCALING = 1706; +constexpr int DEFAULT_LENGTH = 256; +constexpr fft_shift DEFAULT_SHIFT = fft_shift::NORMAL; +constexpr fft_direction DEFAULT_DIRECTION = fft_direction::FORWARD; +constexpr fft_magnitude DEFAULT_MAGNITUDE = fft_magnitude::COMPLEX; +constexpr int DEFAULT_FFT_SCALING = 1706; // Conservative 1/N scaling + +// FFT IP constraints +constexpr int MIN_FFT_LENGTH = 8; +constexpr int MAX_FFT_LENGTH = 2048; const uhd::rfnoc::io_type_t DEFAULT_TYPE = uhd::rfnoc::IO_TYPE_SC16; } // namespace -const uint32_t fft_block_control::RB_FFT_RESET = 0; -const uint32_t fft_block_control::RB_MAGNITUDE_OUT = 8; -const uint32_t fft_block_control::RB_FFT_SIZE_LOG2 = 16; -const uint32_t fft_block_control::RB_FFT_DIRECTION = 24; -const uint32_t fft_block_control::RB_FFT_SCALING = 32; -const uint32_t fft_block_control::RB_FFT_SHIFT_CONFIG = 40; - -const uint32_t fft_block_control::SR_FFT_RESET = 131 * 8; -const uint32_t fft_block_control::SR_FFT_SIZE_LOG2 = 132 * 8; -const uint32_t fft_block_control::SR_MAGNITUDE_OUT = 133 * 8; -const uint32_t fft_block_control::SR_FFT_DIRECTION = 134 * 8; -const uint32_t fft_block_control::SR_FFT_SCALING = 135 * 8; -const uint32_t fft_block_control::SR_FFT_SHIFT_CONFIG = 136 * 8; +const uint32_t fft_block_control::REG_RESET_ADDR = 131 * 8; +const uint32_t fft_block_control::REG_LENGTH_LOG2_ADDR = 132 * 8; +const uint32_t fft_block_control::REG_MAGNITUDE_OUT_ADDR = 133 * 8; +const uint32_t fft_block_control::REG_DIRECTION_ADDR = 134 * 8; +const uint32_t fft_block_control::REG_SCALING_ADDR = 135 * 8; +const uint32_t fft_block_control::REG_SHIFT_CONFIG_ADDR = 136 * 8; class fft_block_control_impl : public fft_block_control { @@ -46,36 +43,129 @@ public: { set_prop_forwarding_policy(forwarding_policy_t::ONE_TO_ONE); set_action_forwarding_policy(forwarding_policy_t::ONE_TO_ONE); + _reset(); + _register_props(); } - void reset() + void set_direction(const fft_direction direction) { - regs().poke32(SR_FFT_RESET, uint32_t(1)); - regs().poke32(SR_FFT_RESET, uint32_t(0)); + set_property<int>(PROP_KEY_DIRECTION, static_cast<int>(direction)); + } + + fft_direction get_direction() const + { + return static_cast<fft_direction>(_direction.get()); + } + + void set_magnitude(const fft_magnitude magnitude) + { + set_property<int>(PROP_KEY_MAGNITUDE, static_cast<int>(magnitude)); + } + + fft_magnitude get_magnitude() const + { + return static_cast<fft_magnitude>(_magnitude.get()); + } + + void set_shift_config(const fft_shift shift) + { + set_property<int>(PROP_KEY_SHIFT_CONFIG, static_cast<int>(shift)); + } + + fft_shift get_shift_config() const + { + return static_cast<fft_shift>(_shift.get()); + } + + void set_scaling(const uint16_t scaling) + { + set_property<int>(PROP_KEY_FFT_SCALING, scaling); + } + + uint16_t get_scaling() const + { + return static_cast<uint16_t>(_scaling.get()); + } + + void set_length(const size_t size) + { + set_property<int>(PROP_KEY_LENGTH, size); + } + + size_t get_length() const + { + return static_cast<size_t>(_length.get()); } private: + void _reset() + { + regs().poke32(REG_RESET_ADDR, uint32_t(1)); + regs().poke32(REG_RESET_ADDR, uint32_t(0)); + } + /************************************************************************** * Initialization *************************************************************************/ void _register_props() { // register block specific properties - register_property(&_size, [this]() { - this->regs().poke32(SR_FFT_SIZE_LOG2, uint32_t(this->_size.get())); + register_property(&_length); + add_property_resolver({&_length}, {&_length}, [this]() { + size_t length = this->_length.get(); + if (length < MIN_FFT_LENGTH || length > MAX_FFT_LENGTH) { + throw uhd::value_error("Size value must be in [" + + std::to_string(MIN_FFT_LENGTH) + ", " + + std::to_string(MAX_FFT_LENGTH) + "]"); + } + // Find the log2(length) via highest bit set + size_t length_log2 = 0; + size_t old_length = length; + while ((length >>= 1) != 0) { + length_log2++; + } + size_t coerced_length = (1 << length_log2); + if (old_length != coerced_length) { + RFNOC_LOG_WARNING("Length " + << old_length + << " not an integral power of two; coercing to " + << coerced_length); + this->_length.set(coerced_length); + } + this->regs().poke32(REG_LENGTH_LOG2_ADDR, uint32_t(length_log2)); }); + register_property(&_magnitude, [this]() { - this->regs().poke32(SR_MAGNITUDE_OUT, uint32_t(this->_magnitude.get())); + int mag = this->_magnitude.get(); + if (mag < static_cast<int>(fft_magnitude::COMPLEX) + || mag > static_cast<int>(fft_magnitude::MAGNITUDE_SQUARED)) { + throw uhd::value_error("Magnitude value must be [0, 2]"); + } + this->regs().poke32(REG_MAGNITUDE_OUT_ADDR, uint32_t(mag)); }); register_property(&_direction, [this]() { - this->regs().poke32(SR_MAGNITUDE_OUT, uint32_t(this->_direction.get())); + int dir = _direction.get(); + if (dir < static_cast<int>(fft_direction::REVERSE) + || dir > static_cast<int>(fft_direction::FORWARD)) { + throw uhd::value_error("Direction value must be in [0, 1]"); + } + this->regs().poke32(REG_DIRECTION_ADDR, uint32_t(dir)); }); register_property(&_scaling, [this]() { - this->regs().poke32(SR_MAGNITUDE_OUT, uint32_t(this->_scaling.get())); + int scale = _scaling.get(); + if (scale < 0 || scale > (1 << 12) - 1) { + throw uhd::value_error("Scale value must be in [0, 4095]"); + } + this->regs().poke32(REG_SCALING_ADDR, uint32_t(scale)); }); register_property(&_shift, [this]() { - this->regs().poke32(SR_MAGNITUDE_OUT, uint32_t(this->_shift.get())); + int shift = this->_shift.get(); + if (shift < static_cast<int>(fft_shift::NORMAL) + || shift > static_cast<int>(fft_shift::NATURAL)) { + throw uhd::value_error("Shift value must be [0, 2]"); + } + this->regs().poke32(REG_SHIFT_CONFIG_ADDR, uint32_t(shift)); }); // register edge properties @@ -91,7 +181,7 @@ private: }); } - property_t<int> _size{PROP_KEY_FFT_LEN, DEFAULT_SIZE, {res_source_info::USER}}; + property_t<int> _length{PROP_KEY_LENGTH, DEFAULT_LENGTH, {res_source_info::USER}}; property_t<int> _magnitude = property_t<int>{ PROP_KEY_MAGNITUDE, static_cast<int>(DEFAULT_MAGNITUDE), {res_source_info::USER}}; property_t<int> _direction = property_t<int>{ @@ -99,7 +189,7 @@ private: property_t<int> _scaling = property_t<int>{ PROP_KEY_FFT_SCALING, DEFAULT_FFT_SCALING, {res_source_info::USER}}; property_t<int> _shift = property_t<int>{ - PROP_KEY_FFT_SHIFT, static_cast<int>(DEFAULT_SHIFT), {res_source_info::USER}}; + PROP_KEY_SHIFT_CONFIG, static_cast<int>(DEFAULT_SHIFT), {res_source_info::USER}}; property_t<std::string> _type_in = property_t<std::string>{ PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::INPUT_EDGE}}; @@ -108,4 +198,4 @@ private: }; UHD_RFNOC_BLOCK_REGISTER_DIRECT( - fft_block_control, 0xFF700000, "FFT", CLOCK_KEY_GRAPH, "bus_clk") + fft_block_control, FFT_BLOCK, "FFT", CLOCK_KEY_GRAPH, "bus_clk") |