aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/rfnoc
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-09-04 18:20:41 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 12:16:25 -0800
commitf9f9cb0d2cd29b1f2da21c026560215e7f3043a5 (patch)
tree5eced81c32930554901e177947384981074b698d /host/lib/rfnoc
parent7d69dcdcc318ccdf87038b732acbf2bf7c087b60 (diff)
downloaduhd-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.txt1
-rw-r--r--host/lib/rfnoc/dmafifo_block_control.cpp71
-rw-r--r--host/lib/rfnoc/node.cpp2
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);