aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/rfnoc/noc_block_base.hpp32
-rw-r--r--host/include/uhd/rfnoc/noc_block_make_args.hpp4
-rw-r--r--host/lib/rfnoc/ddc_block_control.cpp40
-rw-r--r--host/lib/rfnoc/noc_block_base.cpp62
-rw-r--r--host/tests/rfnoc_blocks_test.cpp1
5 files changed, 99 insertions, 40 deletions
diff --git a/host/include/uhd/rfnoc/noc_block_base.hpp b/host/include/uhd/rfnoc/noc_block_base.hpp
index b671e6525..0959e5bdd 100644
--- a/host/include/uhd/rfnoc/noc_block_base.hpp
+++ b/host/include/uhd/rfnoc/noc_block_base.hpp
@@ -22,6 +22,8 @@
namespace uhd { namespace rfnoc {
+class clock_iface;
+
/*!
* The primary interface to a NoC block in the FPGA
*
@@ -83,10 +85,30 @@ public:
*/
const block_id_t& get_block_id() const { return _block_id; }
+ /*! Returns the tick rate of the current time base
+ *
+ * Note there is only ever one time base (or tick rate) per block.
+ */
+ double get_tick_rate() const { return _tick_rate; }
+
protected:
noc_block_base(make_args_ptr make_args);
+ /*! Update tick rate for this node and all the connected nodes
+ *
+ * Careful: Calling this function will trigger a property propagation to any
+ * block this block is connected to.
+ */
+ void set_tick_rate(const double tick_rate);
+
private:
+ /*! Update the tick rate of this block
+ *
+ * This will make sure that the underlying register_iface is notified of the
+ * change in timebase.
+ */
+ void _set_tick_rate(const double tick_rate);
+
//! This block's Noc-ID
noc_id_t _noc_id;
@@ -100,6 +122,16 @@ private:
//! Number of output ports
size_t _num_output_ports;
+
+ //! Container for the 'tick rate' property. This will hold one edge property
+ // for all in- and output edges.
+ std::vector<property_t<double>> _tick_rate_props;
+
+ //! The actual tick rate of the current time base
+ double _tick_rate;
+
+ std::shared_ptr<clock_iface> _clock_iface;
+
}; // class noc_block_base
}} /* namespace uhd::rfnoc */
diff --git a/host/include/uhd/rfnoc/noc_block_make_args.hpp b/host/include/uhd/rfnoc/noc_block_make_args.hpp
index c9b530589..d3679f973 100644
--- a/host/include/uhd/rfnoc/noc_block_make_args.hpp
+++ b/host/include/uhd/rfnoc/noc_block_make_args.hpp
@@ -14,6 +14,7 @@
namespace uhd { namespace rfnoc {
class clock_iface;
+
/*! Data structure to hold the arguments passed into the noc_block_base ctor
*
* We want to hide these from the user, so she can't futz around with them.
@@ -21,6 +22,8 @@ class clock_iface;
*/
struct noc_block_base::make_args_t
{
+ ~make_args_t();
+
//! Noc-ID
noc_id_t noc_id;
@@ -38,6 +41,7 @@ struct noc_block_base::make_args_t
//! Clock interface object that is shared with the reg_iface
std::shared_ptr<clock_iface> clk_iface;
+
//! The subtree for this block
uhd::property_tree::sptr tree;
};
diff --git a/host/lib/rfnoc/ddc_block_control.cpp b/host/lib/rfnoc/ddc_block_control.cpp
index 4562585d8..0b6fd7d89 100644
--- a/host/lib/rfnoc/ddc_block_control.cpp
+++ b/host/lib/rfnoc/ddc_block_control.cpp
@@ -56,8 +56,7 @@ public:
, _fpga_compat(regs().peek32(RB_COMPAT_NUM)),
_num_halfbands(regs().peek32(RB_NUM_HB)),
_cic_max_decim(regs().peek32(RB_CIC_MAX_DECIM)),
- _residual_scaling(get_num_input_ports(), DEFAULT_SCALING),
- _tick_rate(get_num_input_ports(), DEFAULT_RATE)
+ _residual_scaling(get_num_input_ports(), DEFAULT_SCALING)
{
UHD_ASSERT_THROW(get_num_input_ports() == get_num_output_ports());
UHD_ASSERT_THROW(_cic_max_decim > 0 && _cic_max_decim <= 0xFF);
@@ -87,8 +86,6 @@ public:
// space, because we use push_back() further down, and properties must
// not change their base address after registration and resolver
// creation.
- _tick_rate_in.reserve(get_num_ports());
- _tick_rate_out.reserve(get_num_ports());
_samp_rate_in.reserve(get_num_ports());
_samp_rate_out.reserve(get_num_ports());
_scaling_in.reserve(get_num_ports());
@@ -194,10 +191,6 @@ private:
void _register_props(const size_t chan)
{
// Create actual properties and store them
- _tick_rate_in.push_back(property_t<double>(
- PROP_KEY_TICK_RATE, DEFAULT_RATE, {res_source_info::INPUT_EDGE, chan}));
- _tick_rate_out.push_back(property_t<double>(
- PROP_KEY_TICK_RATE, DEFAULT_RATE, {res_source_info::OUTPUT_EDGE, chan}));
_samp_rate_in.push_back(property_t<double>(
PROP_KEY_SAMP_RATE, DEFAULT_RATE, {res_source_info::INPUT_EDGE, chan}));
_samp_rate_out.push_back(property_t<double>(
@@ -214,8 +207,6 @@ private:
PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::INPUT_EDGE, chan}));
_type_out.emplace_back(property_t<std::string>(
PROP_KEY_TYPE, IO_TYPE_SC16, {res_source_info::OUTPUT_EDGE, chan}));
- UHD_ASSERT_THROW(_tick_rate_in.size() == chan + 1);
- UHD_ASSERT_THROW(_tick_rate_out.size() == chan + 1);
UHD_ASSERT_THROW(_samp_rate_in.size() == chan + 1);
UHD_ASSERT_THROW(_samp_rate_out.size() == chan + 1);
UHD_ASSERT_THROW(_scaling_in.size() == chan + 1);
@@ -226,8 +217,6 @@ private:
UHD_ASSERT_THROW(_type_out.size() == chan + 1);
// give us some shorthands for the rest of this function
- property_t<double>* tick_rate_in = &_tick_rate_in.back();
- property_t<double>* tick_rate_out = &_tick_rate_out.back();
property_t<double>* samp_rate_in = &_samp_rate_in.back();
property_t<double>* samp_rate_out = &_samp_rate_out.back();
property_t<double>* scaling_in = &_scaling_in.back();
@@ -238,8 +227,6 @@ private:
property_t<std::string>* type_out = &_type_out.back();
// register them
- register_property(tick_rate_in);
- register_property(tick_rate_out);
register_property(samp_rate_in);
register_property(samp_rate_out);
register_property(scaling_in);
@@ -252,24 +239,6 @@ private:
/**********************************************************************
* Add resolvers
*********************************************************************/
- // Resolver for the tick rate: The input and output edges can have
- // different time bases. However, we might want to forward the time base,
- // e.g., if the upstream block is a radio, but the downstream block is a
- // streamer and wouldn't know about time bases itself.
- // We therefore propagate tick rates only if the opposite edge has the
- // same tick rate as we do. For the output, we accept any tick rate,
- // so it gets no resolver.
- add_property_resolver({tick_rate_in},
- {tick_rate_out},
- [this,
- chan,
- &tick_rate_in = *tick_rate_in,
- &tick_rate_out = *tick_rate_out]() {
- if (tick_rate_out.get() == _tick_rate.at(chan)) {
- tick_rate_out = tick_rate_in.get();
- }
- _tick_rate[chan] = tick_rate_in.get();
- });
// Resolver for the output scaling: This cannot be updated, we reset it
// to its previous value.
add_property_resolver({scaling_out},
@@ -529,17 +498,10 @@ private:
//! Cache the current residual scaling
std::vector<double> _residual_scaling;
- //! Tick rate for every input channel
- std::vector<double> _tick_rate;
-
//! Properties for type_in (one per port)
std::vector<property_t<std::string>> _type_in;
//! Properties for type_out (one per port)
std::vector<property_t<std::string>> _type_out;
- //! Properties for tick_rate_in (one per port)
- std::vector<property_t<double>> _tick_rate_in;
- //! Properties for tick_rate_out (one per port)
- std::vector<property_t<double>> _tick_rate_out;
//! Properties for samp_rate_in (one per port)
std::vector<property_t<double>> _samp_rate_in;
//! Properties for samp_rate_out (one per port)
diff --git a/host/lib/rfnoc/noc_block_base.cpp b/host/lib/rfnoc/noc_block_base.cpp
index 838e05e74..2bbf52928 100644
--- a/host/lib/rfnoc/noc_block_base.cpp
+++ b/host/lib/rfnoc/noc_block_base.cpp
@@ -4,12 +4,16 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//
+#include <uhd/exception.hpp>
+#include <uhd/rfnoc/defaults.hpp>
#include <uhd/rfnoc/noc_block_base.hpp>
#include <uhd/rfnoc/register_iface.hpp>
-#include <uhd/exception.hpp>
+#include <uhdlib/rfnoc/clock_iface.hpp>
using namespace uhd::rfnoc;
+noc_block_base::make_args_t::~make_args_t() = default;
+
/******************************************************************************
* Structors
*****************************************************************************/
@@ -19,7 +23,39 @@ noc_block_base::noc_block_base(make_args_ptr make_args)
, _block_id(make_args->block_id)
, _num_input_ports(make_args->num_input_ports)
, _num_output_ports(make_args->num_output_ports)
+ , _clock_iface(make_args->clk_iface)
{
+ // First, create one tick_rate property for every port
+ _tick_rate_props.reserve(get_num_input_ports() + get_num_output_ports());
+ for (size_t input_port = 0; input_port < get_num_input_ports(); input_port++) {
+ _tick_rate_props.push_back(property_t<double>(PROP_KEY_TICK_RATE,
+ DEFAULT_TICK_RATE,
+ {res_source_info::INPUT_EDGE, input_port}));
+ }
+ for (size_t output_port = 0; output_port < get_num_output_ports(); output_port++) {
+ _tick_rate_props.push_back(property_t<double>(PROP_KEY_TICK_RATE,
+ DEFAULT_TICK_RATE,
+ {res_source_info::OUTPUT_EDGE, output_port}));
+ }
+ // Register all the tick_rate properties and create a default resolver
+ prop_ptrs_t prop_refs;
+ prop_refs.reserve(_tick_rate_props.size());
+ for (auto& prop : _tick_rate_props) {
+ prop_refs.insert(&prop);
+ register_property(&prop);
+ }
+ for (auto& prop : _tick_rate_props) {
+ auto prop_refs_copy = prop_refs;
+ add_property_resolver(
+ {&prop}, std::move(prop_refs_copy), [this, source_prop = &prop]() {
+ for (property_t<double>& tick_rate_prop : _tick_rate_props) {
+ tick_rate_prop = source_prop->get();
+ }
+ this->_set_tick_rate(source_prop->get());
+ });
+ }
+ // Now enable this clock iface
+ _clock_iface->set_running(true);
}
noc_block_base::~noc_block_base()
@@ -27,3 +63,27 @@ noc_block_base::~noc_block_base()
// nop
}
+
+void noc_block_base::set_tick_rate(const double tick_rate)
+{
+ if (_tick_rate == tick_rate) {
+ return;
+ }
+ // Update this node
+ _set_tick_rate(tick_rate);
+ // Now trigger property propagation
+ if (!_tick_rate_props.empty()) {
+ auto src_info = _tick_rate_props.at(0).get_src_info();
+ set_property<double>(PROP_KEY_TICK_RATE, tick_rate, src_info);
+ }
+}
+
+void noc_block_base::_set_tick_rate(const double tick_rate)
+{
+ if (tick_rate == _tick_rate) {
+ return;
+ }
+ RFNOC_LOG_TRACE("Updating tick rate to " << (tick_rate / 1e6) << " MHz");
+ _clock_iface->set_freq(tick_rate);
+ _tick_rate = tick_rate;
+}
diff --git a/host/tests/rfnoc_blocks_test.cpp b/host/tests/rfnoc_blocks_test.cpp
index b9ffcb5f9..113fbf630 100644
--- a/host/tests/rfnoc_blocks_test.cpp
+++ b/host/tests/rfnoc_blocks_test.cpp
@@ -8,6 +8,7 @@
#include <uhd/rfnoc/ddc_block_control.hpp>
#include <uhdlib/rfnoc/clock_iface.hpp>
#include <uhdlib/rfnoc/node_accessor.hpp>
+#include <uhdlib/rfnoc/clock_iface.hpp>
#include <boost/test/unit_test.hpp>
#include <iostream>