aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/rfnoc/noc_block_base.cpp
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-06-13 13:34:11 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:27 -0800
commit3da938f1242219fdf993576dcfdce7440a63c044 (patch)
tree145b8999ba2c72ebc8e1115ceedd6a8a3a0d2210 /host/lib/rfnoc/noc_block_base.cpp
parentde246ea6174e3a6d5fe0dd554d5208f24c2932bb (diff)
downloaduhd-3da938f1242219fdf993576dcfdce7440a63c044.tar.gz
uhd-3da938f1242219fdf993576dcfdce7440a63c044.tar.bz2
uhd-3da938f1242219fdf993576dcfdce7440a63c044.zip
rfnoc: Add clock selection to blocks
During registration, blocks must now specify which clock they are using for the timebase (i.e., for timed commands) and for the ctrlport (this is used to determine the length of sleeps and polls). For example, the X300 provides bus_clk and radio_clk; typically, the former is used for the control port, and the latter for the timebase clock. Another virtual clock is called "__graph__", and it means the clock is derived from property propagation via the graph. The actual clocks are provided by the mb_iface. It has two new API calls: get_timebase_clock() and get_ctrlport_clock(), which take an argument as to which clock exactly is requested. On block initialization, those clock_iface objects are copied into the block controller. The get_tick_rate() API call for blocks now exclusively checks the timebase clock_iface, and will no longer cache the current tick rate in a separate _tick_rate member variable. Block controllers can't manually modify the clock_iface, unless they also have access to the mb_controller (like the radio block), and that mb_controller has provided said access. This commit also adds the clock selection API changes to the DDC block, the Null block, and the default block.
Diffstat (limited to 'host/lib/rfnoc/noc_block_base.cpp')
-rw-r--r--host/lib/rfnoc/noc_block_base.cpp50
1 files changed, 37 insertions, 13 deletions
diff --git a/host/lib/rfnoc/noc_block_base.cpp b/host/lib/rfnoc/noc_block_base.cpp
index c0d8cf2a9..68093d9b1 100644
--- a/host/lib/rfnoc/noc_block_base.cpp
+++ b/host/lib/rfnoc/noc_block_base.cpp
@@ -23,21 +23,28 @@ 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)
+ , _ctrlport_clock_iface(make_args->ctrlport_clk_iface)
+ , _tb_clock_iface(make_args->tb_clk_iface)
, _mb_controller(std::move(make_args->mb_control))
, _block_args(make_args->args)
, _tree(make_args->tree)
{
+ RFNOC_LOG_TRACE(
+ "Using timebase clock: `" << _tb_clock_iface->get_name() << "'. Current frequency: "
+ << (_tb_clock_iface->get_freq() / 1e6) << " MHz");
+ RFNOC_LOG_TRACE("Using ctrlport clock: `"
+ << _ctrlport_clock_iface->get_name() << "'. Current frequency: "
+ << (_ctrlport_clock_iface->get_freq() / 1e6) << " MHz");
// 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,
+ _tb_clock_iface->get_freq(),
{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,
+ _tb_clock_iface->get_freq(),
{res_source_info::OUTPUT_EDGE, output_port}));
}
// Register all the tick_rate properties and create a default resolver
@@ -51,14 +58,16 @@ noc_block_base::noc_block_base(make_args_ptr make_args)
auto prop_refs_copy = prop_refs;
add_property_resolver(
{&prop}, std::move(prop_refs_copy), [this, source_prop = &prop]() {
+ // _set_tick_rate() will update _tick_rate, but only if that's
+ // a valid operation for this block
+ this->_set_tick_rate(source_prop->get());
+ // Now, _tick_rate is valid and we will pass its value to all
+ // tick_rate properties
for (property_t<double>& tick_rate_prop : _tick_rate_props) {
- tick_rate_prop = source_prop->get();
+ tick_rate_prop = get_tick_rate();
}
- this->_set_tick_rate(source_prop->get());
});
}
- // Now enable this clock iface
- _clock_iface->set_running(true);
}
noc_block_base::~noc_block_base()
@@ -89,13 +98,19 @@ void noc_block_base::set_num_output_ports(const size_t num_ports)
}
+double noc_block_base::get_tick_rate() const
+{
+ return _tb_clock_iface->get_freq();
+}
+
void noc_block_base::set_tick_rate(const double tick_rate)
{
- if (_tick_rate == tick_rate) {
+ if (tick_rate == get_tick_rate()) {
return;
}
// Update this node
- _set_tick_rate(tick_rate);
+ RFNOC_LOG_TRACE("Setting tb clock freq to " << tick_rate/1e6 << " MHz");
+ _tb_clock_iface->set_freq(tick_rate);
// Now trigger property propagation
if (!_tick_rate_props.empty()) {
auto src_info = _tick_rate_props.at(0).get_src_info();
@@ -105,12 +120,21 @@ void noc_block_base::set_tick_rate(const double tick_rate)
void noc_block_base::_set_tick_rate(const double tick_rate)
{
- if (tick_rate == _tick_rate) {
+ if (tick_rate == get_tick_rate()) {
+ return;
+ }
+ if (tick_rate <= 0) {
+ RFNOC_LOG_WARNING("Attempting to set tick rate to 0. Skipping.")
return;
}
- RFNOC_LOG_TRACE("Updating tick rate to " << (tick_rate / 1e6) << " MHz");
- _clock_iface->set_freq(tick_rate);
- _tick_rate = tick_rate;
+ if (_tb_clock_iface->get_name() == CLOCK_KEY_GRAPH) {
+ RFNOC_LOG_TRACE("Updating tick rate to " << (tick_rate / 1e6) << " MHz");
+ _tb_clock_iface->set_freq(tick_rate);
+ } else {
+ RFNOC_LOG_WARNING("Cannot change tick rate to "
+ << (tick_rate / 1e6)
+ << " MHz, this clock is not configurable by the graph!");
+ }
}
void noc_block_base::shutdown()