diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-09-04 18:20:41 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 12:16:25 -0800 |
commit | f9f9cb0d2cd29b1f2da21c026560215e7f3043a5 (patch) | |
tree | 5eced81c32930554901e177947384981074b698d /host/lib/rfnoc | |
parent | 7d69dcdcc318ccdf87038b732acbf2bf7c087b60 (diff) | |
download | uhd-f9f9cb0d2cd29b1f2da21c026560215e7f3043a5.tar.gz uhd-f9f9cb0d2cd29b1f2da21c026560215e7f3043a5.tar.bz2 uhd-f9f9cb0d2cd29b1f2da21c026560215e7f3043a5.zip |
rfnoc: Add DMA FIFO block controller
Diffstat (limited to 'host/lib/rfnoc')
-rw-r--r-- | host/lib/rfnoc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/lib/rfnoc/dmafifo_block_control.cpp | 71 | ||||
-rw-r--r-- | host/lib/rfnoc/node.cpp | 2 |
3 files changed, 73 insertions, 1 deletions
diff --git a/host/lib/rfnoc/CMakeLists.txt b/host/lib/rfnoc/CMakeLists.txt index 5f5838a29..ae531275f 100644 --- a/host/lib/rfnoc/CMakeLists.txt +++ b/host/lib/rfnoc/CMakeLists.txt @@ -42,6 +42,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/block_control.cpp ${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}/null_block_control.cpp ${CMAKE_CURRENT_SOURCE_DIR}/radio_control_impl.cpp ) diff --git a/host/lib/rfnoc/dmafifo_block_control.cpp b/host/lib/rfnoc/dmafifo_block_control.cpp new file mode 100644 index 000000000..c34746a28 --- /dev/null +++ b/host/lib/rfnoc/dmafifo_block_control.cpp @@ -0,0 +1,71 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include <uhd/rfnoc/dmafifo_block_control.hpp> +#include <uhd/rfnoc/registry.hpp> +#include <uhdlib/usrp/cores/dma_fifo_core_3000.hpp> +#include <boost/format.hpp> +#include <mutex> + +using namespace uhd; +using namespace uhd::rfnoc; + +namespace { + +//! Default FIFO depth per channel: 32 MiB +constexpr uint32_t DEFAULT_SIZE = 32 * 1024 * 1024; +constexpr uint64_t BYTES_PER_BIST = 8000000; +constexpr double BIST_TIMEOUT = 0.5; // s +//! Address space between FIFO controls +const uint32_t REG_OFFSET = 128; + +} // namespace + +class dmafifo_block_control_impl : public dmafifo_block_control +{ +public: + RFNOC_BLOCK_CONSTRUCTOR(dmafifo_block_control) + { + UHD_ASSERT_THROW(get_num_input_ports() == get_num_output_ports()); + set_action_forwarding_policy(forwarding_policy_t::ONE_TO_ONE); + set_prop_forwarding_policy(forwarding_policy_t::ONE_TO_ONE); + // Now init DMA/DRAM control + _fifo_cores.reserve(get_num_input_ports()); + for (size_t i = 0; i < get_num_input_ports(); i++) { + _fifo_cores.push_back(dma_fifo_core_3000::make( + [this, i](const uint32_t addr, const uint32_t data) { + regs().poke32(addr + i * REG_OFFSET, data); + }, + [this, i]( + const uint32_t addr) { return regs().peek32(addr + i * REG_OFFSET); }, + i)); + RFNOC_LOG_DEBUG("Initialized FIFO core " << i << "."); + if (_fifo_cores.back()->has_bist()) { + RFNOC_LOG_DEBUG("Running BIST..."); + const double throughput = + _fifo_cores.back()->run_bist(BYTES_PER_BIST, BIST_TIMEOUT); + RFNOC_LOG_INFO( + boost::format("BIST passed (Estimated Minimum Throughput: %.0f MB/s)") + % (throughput / 1e6)); + } else { + RFNOC_LOG_DEBUG("Channel " << i << " does not support BIST, skipping."); + } + } + } + + uint32_t get_packet_count(const size_t chan) + { + UHD_ASSERT_THROW(chan < _fifo_cores.size()); + return _fifo_cores.at(chan)->get_packet_count(); + } + +private: + //! One FIFO core object per FIFO + std::vector<dma_fifo_core_3000::sptr> _fifo_cores; +}; + +UHD_RFNOC_BLOCK_REGISTER_DIRECT( + dmafifo_block_control, 0xF1F00000, "DmaFIFO", CLOCK_KEY_GRAPH, "bus_clk") diff --git a/host/lib/rfnoc/node.cpp b/host/lib/rfnoc/node.cpp index 90f0a0a91..23d5a340d 100644 --- a/host/lib/rfnoc/node.cpp +++ b/host/lib/rfnoc/node.cpp @@ -446,7 +446,7 @@ void node_t::clean_props() prop_accessor_t prop_accessor{}; for (const auto& type_prop_pair : _props) { for (const auto& prop : type_prop_pair.second) { - if (prop->is_dirty() && _clean_cb_registry.count(prop)) { + if (prop->is_valid() && prop->is_dirty() && _clean_cb_registry.count(prop)) { _clean_cb_registry.at(prop)(); } prop_accessor.mark_clean(*prop); |