diff options
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp | 4 | ||||
-rw-r--r-- | host/lib/rfnoc/ddc_block_control.cpp | 25 | ||||
-rw-r--r-- | host/lib/rfnoc/duc_block_control.cpp | 25 | ||||
-rw-r--r-- | host/lib/rfnoc/radio_control_impl.cpp | 61 |
4 files changed, 61 insertions, 54 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp index 1a78d7cab..69577b9e4 100644 --- a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp +++ b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp @@ -5,6 +5,7 @@ // #include <uhd/rfnoc/defaults.hpp> +#include <uhd/rfnoc/multichan_register_iface.hpp> #include <uhd/rfnoc/radio_control.hpp> #include <unordered_map> #include <mutex> @@ -296,6 +297,9 @@ protected: //! Properties for samp_rate (one per port) std::vector<property_t<double>> _samp_rate_out; + //! Block-specific register interface + multichan_register_iface _radio_reg_iface; + private: //! Validator for the async messages // diff --git a/host/lib/rfnoc/ddc_block_control.cpp b/host/lib/rfnoc/ddc_block_control.cpp index 8942d128d..a35d750ff 100644 --- a/host/lib/rfnoc/ddc_block_control.cpp +++ b/host/lib/rfnoc/ddc_block_control.cpp @@ -7,6 +7,7 @@ #include <uhd/exception.hpp> #include <uhd/rfnoc/ddc_block_control.hpp> #include <uhd/rfnoc/defaults.hpp> +#include <uhd/rfnoc/multichan_register_iface.hpp> #include <uhd/rfnoc/property.hpp> #include <uhd/rfnoc/registry.hpp> #include <uhd/types/ranges.hpp> @@ -56,7 +57,8 @@ 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) + _residual_scaling(get_num_input_ports(), DEFAULT_SCALING), + _ddc_reg_iface(*this, 0, REG_CHAN_OFFSET) { UHD_ASSERT_THROW(get_num_input_ports() == get_num_output_ports()); UHD_ASSERT_THROW(_cic_max_decim > 0 && _cic_max_decim <= 0xFF); @@ -186,6 +188,10 @@ public: issue_stream_cmd_action_handler(dst_edge, new_action); } +protected: + //! Block-specific register interface + multichan_register_iface _ddc_reg_iface; + private: //! Shorthand for num ports, since num input ports always equals num output ports inline size_t get_num_ports() @@ -193,11 +199,6 @@ private: return get_num_input_ports(); } - inline uint32_t get_addr(const uint32_t base_addr, const size_t chan) - { - return base_addr + REG_CHAN_OFFSET * chan; - } - /************************************************************************** * Initialization *************************************************************************/ @@ -468,14 +469,14 @@ private: UHD_ASSERT_THROW(hb_enable <= _num_halfbands); UHD_ASSERT_THROW(cic_decim > 0 and cic_decim <= _cic_max_decim); const uint32_t decim_word = (hb_enable << 8) | cic_decim; - regs().poke32(get_addr(SR_DECIM_ADDR, chan), decim_word); + _ddc_reg_iface.poke32(SR_DECIM_ADDR, decim_word, chan); // Rate change = M/N - regs().poke32(get_addr(SR_N_ADDR, chan), decim); + _ddc_reg_iface.poke32(SR_N_ADDR, decim, chan); // FIXME: // - eiscat DDC had a real mode, where M needed to be 2 // - TwinRX had some issues with M == 1 - regs().poke32(get_addr(SR_M_ADDR, chan), 1); + _ddc_reg_iface.poke32(SR_M_ADDR, 1, chan); if (cic_decim > 1 and hb_enable == 0) { RFNOC_LOG_WARNING( @@ -515,7 +516,7 @@ private: const int32_t actual_factor = boost::math::iround(target_factor); // Write DDC with scaling correction for CIC and DDS that maximizes // dynamic range - regs().poke32(get_addr(SR_SCALE_IQ_ADDR, chan), actual_factor); + _ddc_reg_iface.poke32(SR_SCALE_IQ_ADDR, actual_factor, chan); // Calculate the error introduced by using fixedpoint representation for // the scaler, can be corrected in host later. @@ -538,8 +539,8 @@ private: int32_t freq_word; std::tie(actual_freq, freq_word) = get_freq_and_freq_word(requested_freq, input_rate); - regs().poke32( - get_addr(SR_FREQ_ADDR, chan), uint32_t(freq_word), get_command_time(chan)); + _ddc_reg_iface.poke32( + SR_FREQ_ADDR, uint32_t(freq_word), chan, get_command_time(chan)); return actual_freq; } diff --git a/host/lib/rfnoc/duc_block_control.cpp b/host/lib/rfnoc/duc_block_control.cpp index ff1c4e97a..1795a275a 100644 --- a/host/lib/rfnoc/duc_block_control.cpp +++ b/host/lib/rfnoc/duc_block_control.cpp @@ -7,6 +7,7 @@ #include <uhd/exception.hpp> #include <uhd/rfnoc/defaults.hpp> #include <uhd/rfnoc/duc_block_control.hpp> +#include <uhd/rfnoc/multichan_register_iface.hpp> #include <uhd/rfnoc/property.hpp> #include <uhd/rfnoc/registry.hpp> #include <uhd/types/ranges.hpp> @@ -54,7 +55,8 @@ public: , _fpga_compat(regs().peek32(RB_COMPAT_NUM)), _num_halfbands(regs().peek32(RB_NUM_HB)), _cic_max_interp(regs().peek32(RB_CIC_MAX_INTERP)), - _residual_scaling(get_num_input_ports(), DEFAULT_SCALING) + _residual_scaling(get_num_input_ports(), DEFAULT_SCALING), + _duc_reg_iface(*this, 0, REG_CHAN_OFFSET) { UHD_ASSERT_THROW(get_num_input_ports() == get_num_output_ports()); UHD_ASSERT_THROW(_cic_max_interp > 0 && _cic_max_interp <= 0xFF); @@ -167,6 +169,10 @@ public: return _samp_rate_in.at(chan).get(); } +protected: + //! Block-specific register interface + multichan_register_iface _duc_reg_iface; + private: //! Shorthand for num ports, since num input ports always equals num output ports inline size_t get_num_ports() @@ -174,11 +180,6 @@ private: return get_num_input_ports(); } - inline uint32_t get_addr(const uint32_t base_addr, const size_t chan) - { - return base_addr + REG_CHAN_OFFSET * chan; - } - /************************************************************************** * Initialization *************************************************************************/ @@ -454,13 +455,13 @@ private: UHD_ASSERT_THROW(hb_enable <= _num_halfbands); UHD_ASSERT_THROW(cic_interp > 0 and cic_interp <= _cic_max_interp); const uint32_t interp_word = (hb_enable << 8) | cic_interp; - regs().poke32(get_addr(SR_INTERP_ADDR, chan), interp_word); + _duc_reg_iface.poke32(SR_INTERP_ADDR, interp_word, chan); // Rate change = M/N, where N = 1 - regs().poke32(get_addr(SR_M_ADDR, chan), interp); + _duc_reg_iface.poke32(SR_M_ADDR, interp, chan); // FIXME: // - TwinRX had some issues with N == 1 - regs().poke32(get_addr(SR_N_ADDR, chan), 1); + _duc_reg_iface.poke32(SR_N_ADDR, 1, chan); if (cic_interp > 1 and hb_enable == 0) { RFNOC_LOG_WARNING( @@ -496,7 +497,7 @@ private: const int32_t actual_factor = boost::math::iround(target_factor); // Write DUC with scaling correction for CIC and DDS that maximizes // dynamic range - regs().poke32(get_addr(SR_SCALE_IQ_ADDR, chan), actual_factor); + _duc_reg_iface.poke32(SR_SCALE_IQ_ADDR, actual_factor, chan); // Calculate the error introduced by using fixedpoint representation for // the scaler, can be corrected in host later. @@ -519,8 +520,8 @@ private: int32_t freq_word; std::tie(actual_freq, freq_word) = get_freq_and_freq_word(requested_freq, input_rate); - regs().poke32( - get_addr(SR_FREQ_ADDR, chan), uint32_t(freq_word), get_command_time(chan)); + _duc_reg_iface.poke32( + SR_FREQ_ADDR, uint32_t(freq_word), chan, get_command_time(chan)); return actual_freq; } diff --git a/host/lib/rfnoc/radio_control_impl.cpp b/host/lib/rfnoc/radio_control_impl.cpp index faa6a01a6..b5c3181a5 100644 --- a/host/lib/rfnoc/radio_control_impl.cpp +++ b/host/lib/rfnoc/radio_control_impl.cpp @@ -6,6 +6,8 @@ #include <uhd/exception.hpp> #include <uhd/rfnoc/mb_controller.hpp> +#include <uhd/rfnoc/multichan_register_iface.hpp> +#include <uhd/rfnoc/register_iface.hpp> #include <uhd/utils/log.hpp> #include <uhdlib/rfnoc/radio_control_impl.hpp> #include <uhdlib/utils/compat_check.hpp> @@ -16,12 +18,6 @@ using namespace uhd::rfnoc; namespace { -inline uint32_t get_addr(const uint32_t base_addr, const size_t chan) -{ - return radio_control_impl::regmap::RADIO_BASE_ADDR + base_addr - + radio_control_impl::regmap::REG_CHAN_OFFSET * chan; -} - const std::string DEFAULT_GAIN_PROFILE("default"); } // namespace @@ -77,6 +73,9 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args) , _spc(_radio_width & 0xFFFF) , _last_stream_cmd( get_num_output_ports(), uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS) + , _radio_reg_iface(*this, + radio_control_impl::regmap::RADIO_BASE_ADDR, + radio_control_impl::regmap::REG_CHAN_OFFSET) { uhd::assert_fpga_compat(MAJOR_COMPAT, MINOR_COMPAT, @@ -156,8 +155,8 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args) const uint32_t words_per_pkt = spp.get(); RFNOC_LOG_TRACE( "Setting words_per_pkt to " << words_per_pkt << " on chan " << chan); - regs().poke32( - get_addr(regmap::REG_RX_MAX_WORDS_PER_PKT, chan), words_per_pkt); + _radio_reg_iface.poke32( + regmap::REG_RX_MAX_WORDS_PER_PKT, words_per_pkt, chan); }); register_property(&_samp_rate_in.back()); register_property(&_samp_rate_out.back()); @@ -220,28 +219,30 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args) for (size_t tx_chan = 0; tx_chan < get_num_output_ports(); tx_chan++) { // Set the EPID and port of our regs() object (all async messages go to // the same location) - regs().poke32( - get_addr(regmap::REG_TX_ERR_REM_EPID, tx_chan), regs().get_src_epid()); - regs().poke32( - get_addr(regmap::REG_TX_ERR_REM_PORT, tx_chan), regs().get_port_num()); + _radio_reg_iface.poke32( + regmap::REG_TX_ERR_REM_EPID, regs().get_src_epid(), tx_chan); + _radio_reg_iface.poke32( + regmap::REG_TX_ERR_REM_PORT, regs().get_port_num(), tx_chan); // Set the crossbar port for the async packet routing - regs().poke32(get_addr(regmap::REG_TX_ERR_PORT, tx_chan), xbar_port); + _radio_reg_iface.poke32(regmap::REG_TX_ERR_PORT, xbar_port, tx_chan); // Set the async message address - regs().poke32(get_addr(regmap::REG_TX_ERR_ADDR, tx_chan), - regmap::SWREG_TX_ERR + regmap::SWREG_CHAN_OFFSET * tx_chan); + _radio_reg_iface.poke32(regmap::REG_TX_ERR_ADDR, + regmap::SWREG_TX_ERR + regmap::SWREG_CHAN_OFFSET * tx_chan, + tx_chan); } for (size_t rx_chan = 0; rx_chan < get_num_input_ports(); rx_chan++) { // Set the EPID and port of our regs() object (all async messages go to // the same location) - regs().poke32( - get_addr(regmap::REG_RX_ERR_REM_EPID, rx_chan), regs().get_src_epid()); - regs().poke32( - get_addr(regmap::REG_RX_ERR_REM_PORT, rx_chan), regs().get_port_num()); + _radio_reg_iface.poke32( + regmap::REG_RX_ERR_REM_EPID, regs().get_src_epid(), rx_chan); + _radio_reg_iface.poke32( + regmap::REG_RX_ERR_REM_PORT, regs().get_port_num(), rx_chan); // Set the crossbar port for the async packet routing - regs().poke32(get_addr(regmap::REG_RX_ERR_PORT, rx_chan), xbar_port); + _radio_reg_iface.poke32(regmap::REG_RX_ERR_PORT, xbar_port, rx_chan); // Set the async message address - regs().poke32(get_addr(regmap::REG_RX_ERR_ADDR, rx_chan), - regmap::SWREG_RX_ERR + regmap::SWREG_CHAN_OFFSET * rx_chan); + _radio_reg_iface.poke32(regmap::REG_RX_ERR_ADDR, + regmap::SWREG_RX_ERR + regmap::SWREG_CHAN_OFFSET * rx_chan, + rx_chan); } // Now register a function to receive the async messages regs().register_async_msg_validator( @@ -827,22 +828,22 @@ void radio_control_impl::issue_stream_cmd( "requested fewer samples."); throw uhd::value_error("Requested too many samples in a single burst."); } - regs().poke32( - get_addr(regmap::REG_RX_CMD_NUM_WORDS_HI, chan), uint32_t(num_words >> 32)); - regs().poke32(get_addr(regmap::REG_RX_CMD_NUM_WORDS_LO, chan), - uint32_t(num_words & 0xFFFFFFFF)); + _radio_reg_iface.poke32( + regmap::REG_RX_CMD_NUM_WORDS_HI, uint32_t(num_words >> 32), chan); + _radio_reg_iface.poke32( + regmap::REG_RX_CMD_NUM_WORDS_LO, uint32_t(num_words & 0xFFFFFFFF), chan); } if (!stream_cmd.stream_now) { const uint64_t ticks = stream_cmd.time_spec.to_ticks(get_tick_rate()); - regs().poke32(get_addr(regmap::REG_RX_CMD_TIME_HI, chan), uint32_t(ticks >> 32)); - regs().poke32(get_addr(regmap::REG_RX_CMD_TIME_LO, chan), uint32_t(ticks >> 0)); + _radio_reg_iface.poke32(regmap::REG_RX_CMD_TIME_HI, uint32_t(ticks >> 32), chan); + _radio_reg_iface.poke32(regmap::REG_RX_CMD_TIME_LO, uint32_t(ticks >> 0), chan); } - regs().poke32(get_addr(regmap::REG_RX_CMD, chan), cmd_word); + _radio_reg_iface.poke32(regmap::REG_RX_CMD, cmd_word, chan); } void radio_control_impl::enable_rx_timestamps(const bool enable, const size_t chan) { - regs().poke32(get_addr(regmap::REG_RX_HAS_TIME, chan), enable ? 0x1 : 0x0); + _radio_reg_iface.poke32(regmap::REG_RX_HAS_TIME, enable ? 0x1 : 0x0, chan); } /****************************************************************************** |